- Improved `auth-guard.spec.ts` test formatting for readability by adjusting destructuring syntax. - Updated `settings-sessions.spec.ts` to note feature completion and skipped tests pending auth storage debugging. - Removed outdated and redundant test cases from `homepage.spec.ts` to streamline coverage. - Enabled and updated assertion in `settings-password.spec.ts` to check updated heading for password change form.
213 lines
6.5 KiB
TypeScript
213 lines
6.5 KiB
TypeScript
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();
|
|
});
|
|
});
|