/** * Login E2E Tests * * Tests authentication flow, session persistence, and error handling. */ import { test, expect } from '@playwright/test'; import { LoginPage } from '../../helpers/page-objects/LoginPage'; import { getTestUserCredentials, logout } from '../../fixtures/auth'; // These tests run without pre-authenticated state test.use({ storageState: { cookies: [], origins: [] } }); test.describe('Login Flow', () => { let loginPage: LoginPage; test.beforeEach(async ({ page }) => { loginPage = new LoginPage(page); await loginPage.goto(); }); test('should login successfully with valid credentials', async ({ page }) => { const { email, password } = getTestUserCredentials('user'); await loginPage.login(email, password); await loginPage.expectLoginSuccess(); // Verify we're redirected to homepage await expect(page).toHaveURL('/'); }); test('should show error with invalid password', async ({ page }) => { const { email } = getTestUserCredentials('user'); await loginPage.login(email, 'wrongpassword123'); await loginPage.expectLoginError(); // Verify we're still on auth page await expect(page).toHaveURL(/\/auth/); }); test('should show error with non-existent email', async ({ page }) => { await loginPage.login('nonexistent@example.com', 'password123'); await loginPage.expectLoginError(); }); test('should persist session after page refresh', async ({ page }) => { const { email, password } = getTestUserCredentials('user'); // Login await loginPage.login(email, password); await loginPage.expectLoginSuccess(); // Reload page await page.reload(); // Should still be logged in (not redirected to /auth) await expect(page).not.toHaveURL(/\/auth/); }); test('should clear session on logout', async ({ page }) => { const { email, password } = getTestUserCredentials('user'); // Login await loginPage.login(email, password); await loginPage.expectLoginSuccess(); // Logout await page.click('button:has-text("Logout")').or(page.click('[data-testid="logout"]')); // Should be redirected to auth or homepage // And trying to access protected route should redirect to auth await page.goto('/moderation/queue'); await expect(page).toHaveURL(/\/auth/); }); test('should validate email format', async ({ page }) => { await loginPage.login('invalid-email', 'password123'); // Should show validation error await expect(page.getByText(/invalid.*email/i)).toBeVisible(); }); test('should require password', async ({ page }) => { const { email } = getTestUserCredentials('user'); await page.fill('input[type="email"]', email); await page.click('button[type="submit"]'); // Should show validation error await expect(page.getByText(/password.*required/i)).toBeVisible(); }); }); test.describe('Role-Based Access', () => { test('moderator can access moderation queue', async ({ browser }) => { const context = await browser.newContext({ storageState: '.auth/moderator.json' }); const page = await context.newPage(); await page.goto('/moderation/queue'); // Should not be redirected await expect(page).toHaveURL(/\/moderation\/queue/); // Page should load successfully await expect(page.getByText(/moderation.*queue/i)).toBeVisible(); await context.close(); }); test('regular user cannot access moderation queue', async ({ browser }) => { const context = await browser.newContext({ storageState: '.auth/user.json' }); const page = await context.newPage(); await page.goto('/moderation/queue'); // Should be redirected or see access denied await expect(page.getByText(/access denied/i).or(page.getByText(/not authorized/i))).toBeVisible(); await context.close(); }); test('admin can access admin panel', async ({ browser }) => { const context = await browser.newContext({ storageState: '.auth/admin.json' }); const page = await context.newPage(); await page.goto('/admin/users'); // Should not be redirected await expect(page).toHaveURL(/\/admin/); await context.close(); }); });