import { test, expect, type Page } from '@playwright/test'; // Mocks the auth endpoints at the network level so the journey is // deterministic and doesn't require a live backend. const userFixture = { id: 'user-1', username: 'alice', created_at: '2026-01-01T00:00:00Z' }; const emptyPage = { items: [], page: { limit: 50, offset: 0, total: null } }; async function stubAnonymousThenAuthenticated(page: Page) { let loggedIn = false; await page.route('**/api/v1/auth/me', async (route) => { if (loggedIn) { await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ user: userFixture }) }); } else { await route.fulfill({ status: 401, contentType: 'application/json', body: JSON.stringify({ error: { code: 'unauthenticated', message: 'unauthenticated' } }) }); } }); await page.route('**/api/v1/auth/login', async (route) => { loggedIn = true; await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ user: userFixture }) }); }); await page.route('**/api/v1/auth/logout', async (route) => { loggedIn = false; await route.fulfill({ status: 204 }); }); await page.route('**/api/v1/mangas*', async (route) => { await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(emptyPage) }); }); } test('login then logout flips the layout between authenticated and anonymous', async ({ page }) => { await stubAnonymousThenAuthenticated(page); await page.goto('/'); // Initially anonymous → Login / Register links visible. await expect(page.getByTestId('nav-login')).toBeVisible(); // Log in. await page.goto('/login'); await page.getByTestId('login-username').fill('alice'); await page.getByTestId('login-password').fill('hunter2hunter2'); await page.getByTestId('login-submit').click(); // Authenticated → username + Logout button. await expect(page.getByTestId('session-user')).toContainText('alice'); await expect(page.getByRole('button', { name: 'Logout' })).toBeVisible(); // Log out. await page.getByRole('button', { name: 'Logout' }).click(); await expect(page).toHaveURL(/\/login$/); await expect(page.getByTestId('nav-login')).toBeVisible(); }); test('login surfaces the API error message on bad credentials', async ({ page }) => { await page.route('**/api/v1/auth/me', async (route) => { await route.fulfill({ status: 401, contentType: 'application/json', body: JSON.stringify({ error: { code: 'unauthenticated', message: 'unauthenticated' } }) }); }); await page.route('**/api/v1/auth/login', async (route) => { await route.fulfill({ status: 401, contentType: 'application/json', body: JSON.stringify({ error: { code: 'unauthenticated', message: 'unauthenticated' } }) }); }); await page.goto('/login'); await page.getByTestId('login-username').fill('alice'); await page.getByTestId('login-password').fill('wrongpassword'); await page.getByTestId('login-submit').click(); await expect(page.getByTestId('login-error')).toBeVisible(); });