112 lines
4.0 KiB
TypeScript
112 lines
4.0 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import { TEST_USERS, TIMEOUTS } from './utils/test-data';
|
|
import { TestHelpers } from './utils/test-helpers';
|
|
|
|
test.describe('Authentication', () => {
|
|
let helpers: TestHelpers;
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
helpers = new TestHelpers(page);
|
|
});
|
|
|
|
test('should display login form on initial visit', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
// Check for login form elements using Material-UI structure
|
|
await expect(page.locator('input[name="username"]')).toBeVisible();
|
|
await expect(page.locator('input[name="password"]')).toBeVisible();
|
|
await expect(page.locator('button[type="submit"]')).toBeVisible();
|
|
});
|
|
|
|
test('should login with valid credentials', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
// Fill login form with demo credentials
|
|
await page.fill('input[name="username"]', 'admin');
|
|
await page.fill('input[name="password"]', 'readur2024');
|
|
|
|
// Wait for login API call
|
|
const loginResponse = helpers.waitForApiCall('/auth/login');
|
|
|
|
await page.click('button[type="submit"]');
|
|
|
|
// Verify login was successful
|
|
await loginResponse;
|
|
|
|
// Should redirect to dashboard or main page
|
|
await page.waitForURL(/\/dashboard|\//, { timeout: TIMEOUTS.medium });
|
|
|
|
// Verify we're no longer on login page
|
|
await expect(page.locator('input[name="username"]')).not.toBeVisible();
|
|
});
|
|
|
|
test('should show error with invalid credentials', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
await page.fill('input[name="username"]', 'invaliduser');
|
|
await page.fill('input[name="password"]', 'wrongpassword');
|
|
|
|
await page.click('button[type="submit"]');
|
|
|
|
// Should show error message (Material-UI Alert)
|
|
await expect(page.locator('.MuiAlert-root, [role="alert"]')).toBeVisible({ timeout: TIMEOUTS.short });
|
|
|
|
// Should remain on login page
|
|
await expect(page.locator('input[name="username"]')).toBeVisible();
|
|
});
|
|
|
|
test('should logout successfully', async ({ page }) => {
|
|
// First login
|
|
await page.goto('/');
|
|
await page.fill('input[name="username"]', 'admin');
|
|
await page.fill('input[name="password"]', 'readur2024');
|
|
await page.click('button[type="submit"]');
|
|
|
|
await page.waitForURL(/\/dashboard|\//, { timeout: TIMEOUTS.medium });
|
|
|
|
// Find and click logout button
|
|
const logoutButton = page.locator('button:has-text("Logout"), [data-testid="logout"]');
|
|
if (await logoutButton.isVisible()) {
|
|
await logoutButton.click();
|
|
} else {
|
|
// Try menu-based logout
|
|
await page.click('[data-testid="user-menu"], .user-menu, button:has([data-testid="user-avatar"])');
|
|
await page.click('button:has-text("Logout"), [data-testid="logout"]');
|
|
}
|
|
|
|
// Should redirect back to login
|
|
await page.waitForURL(/\/login|\//, { timeout: TIMEOUTS.medium });
|
|
await expect(page.locator('input[name="username"]')).toBeVisible();
|
|
});
|
|
|
|
test('should persist session on page reload', async ({ page }) => {
|
|
// Login first
|
|
await page.goto('/');
|
|
await page.fill('input[name="username"]', 'admin');
|
|
await page.fill('input[name="password"]', 'readur2024');
|
|
await page.click('button[type="submit"]');
|
|
|
|
await page.waitForURL(/\/dashboard|\//, { timeout: TIMEOUTS.medium });
|
|
|
|
// Reload the page
|
|
await page.reload();
|
|
|
|
// Should still be logged in
|
|
await expect(page.locator('input[name="username"]')).not.toBeVisible();
|
|
});
|
|
|
|
test('should validate required fields', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
// Try to submit without filling fields
|
|
await page.click('button[type="submit"]');
|
|
|
|
// Should show validation errors or prevent submission
|
|
const usernameInput = page.locator('input[name="username"]');
|
|
const passwordInput = page.locator('input[name="password"]');
|
|
|
|
// Check for HTML5 validation or custom validation messages
|
|
await expect(usernameInput).toBeVisible();
|
|
await expect(passwordInput).toBeVisible();
|
|
});
|
|
}); |