import { test, expect } from '@playwright/test'; test.describe('AuthGuard - Route Protection', () => { test.beforeEach(async ({ page, context }) => { // Clear storage before each test to ensure clean state await context.clearCookies(); await page.goto('/en'); await page.evaluate(() => { localStorage.clear(); sessionStorage.clear(); }); }); test('should redirect to login when accessing protected route without auth', async ({ page }) => { // Try to access a protected route (if you have one) // For now, we'll test the root if it's protected // Adjust the route based on your actual protected routes await page.goto('/en'); // If root is protected, should redirect to login or show homepage // Wait for page to stabilize await page.waitForTimeout(1000); // Should either be on login or homepage (not crashing) - with locale prefix const url = page.url(); expect(url).toMatch(/\/en(\/login)?$/); }); test('should allow access to public routes without auth', async ({ page }) => { // Test login page await page.goto('/en/login'); await expect(page).toHaveURL('/en/login'); await expect(page.locator('h2')).toContainText('Sign in to your account'); // Test register page await page.goto('/en/register'); await expect(page).toHaveURL('/en/register'); await expect(page.locator('h2')).toContainText('Create your account'); // Test password reset page await page.goto('/en/password-reset'); await expect(page).toHaveURL('/en/password-reset'); await expect(page.locator('h2')).toContainText('Reset your password'); }); test('should persist authentication across page reloads', async ({ page, context }) => { // Set localStorage before navigation using context await context.addInitScript(() => { const mockToken = { access_token: 'mock-access-token', refresh_token: 'mock-refresh-token', user: { id: 1, email: 'test@example.com', first_name: 'Test', last_name: 'User', is_active: true, }, }; localStorage.setItem('auth_token', JSON.stringify(mockToken)); }); // Now navigate - localStorage will already be set await page.goto('/en'); await page.waitForLoadState('networkidle'); // Reload the page await page.reload(); await page.waitForLoadState('networkidle'); // Should still have the token const hasToken = await page.evaluate(() => { return localStorage.getItem('auth_token') !== null; }); expect(hasToken).toBe(true); }); test('should clear authentication on logout', async ({ page }) => { // Navigate first without any auth await page.goto('/en'); await page.waitForLoadState('networkidle'); // Now inject auth token after page is loaded await page.evaluate(() => { const mockToken = { access_token: 'mock-access-token', refresh_token: 'mock-refresh-token', user: { id: 1, email: 'test@example.com', first_name: 'Test', last_name: 'User', is_active: true, }, }; localStorage.setItem('auth_token', JSON.stringify(mockToken)); }); // Verify token was set const hasToken = await page.evaluate(() => { return localStorage.getItem('auth_token') !== null; }); expect(hasToken).toBe(true); // Simulate logout by clearing storage await page.evaluate(() => { localStorage.clear(); sessionStorage.clear(); }); // Reload page await page.reload(); await page.waitForLoadState('networkidle'); // Storage should be clear after reload const tokenCleared = await page.evaluate(() => { return localStorage.getItem('auth_token') === null; }); expect(tokenCleared).toBe(true); }); test('should not allow access to auth pages when already logged in', async ({ page, context, }) => { // Set up authenticated state before navigation await context.addInitScript(() => { const mockToken = { access_token: 'mock-access-token', refresh_token: 'mock-refresh-token', user: { id: 1, email: 'test@example.com', first_name: 'Test', last_name: 'User', is_active: true, }, }; localStorage.setItem('auth_token', JSON.stringify(mockToken)); }); // Try to access login page await page.goto('/en/login'); await page.waitForLoadState('networkidle'); // Wait a bit for potential redirect await page.waitForTimeout(2000); // Check current state - might stay on login or redirect // Implementation-dependent const currentUrl = page.url(); // At minimum, page should load without errors expect(currentUrl).toBeTruthy(); }); test('should handle expired tokens gracefully', async ({ page, context }) => { // Set up authenticated state with expired token before navigation await context.addInitScript(() => { const expiredToken = { access_token: 'expired-access-token', refresh_token: 'expired-refresh-token', user: { id: 1, email: 'test@example.com', first_name: 'Test', last_name: 'User', is_active: true, }, }; localStorage.setItem('auth_token', JSON.stringify(expiredToken)); }); // Try to access a protected route // Backend should return 401, triggering logout await page.goto('/en'); await page.waitForLoadState('networkidle'); // Wait for potential redirect to login await page.waitForTimeout(3000); // Should eventually be redirected or have token cleared // This depends on token refresh logic }); test('should preserve intended destination after login', async ({ page, context }) => { // This is a nice-to-have feature that requires protected routes // For now, just verify the test doesn't crash // Login (via localStorage for testing) await context.addInitScript(() => { const mockToken = { access_token: 'mock-access-token', refresh_token: 'mock-refresh-token', user: { id: 1, email: 'test@example.com', first_name: 'Test', last_name: 'User', is_active: true, }, }; localStorage.setItem('auth_token', JSON.stringify(mockToken)); }); // Navigate with auth already set await page.goto('/en'); await page.waitForLoadState('networkidle'); // Verify page loaded successfully expect(page.url()).toBeTruthy(); }); });