import { test, expect } from '@playwright/test' test.describe('Header auth state', () => { test('shows login and register links when not authenticated', async ({ page, }) => { await page.goto('/') const header = page.locator('header') await expect(header.getByRole('link', { name: 'Logga in' })).toBeVisible() await expect( header.getByRole('link', { name: 'Registrera' }), ).toBeVisible() }) test('does not show logout button when not authenticated', async ({ page, }) => { await page.goto('/') const header = page.locator('header') await expect( header.getByRole('button', { name: 'Logga ut' }), ).not.toBeVisible() }) test('shows email and logout when authenticated', async ({ page }) => { const jwt = makeJwt({ sub: 'test@bilhej.se', role: 'user' }) await page.goto('/') await page.evaluate( (token) => localStorage.setItem('auth_token', token), jwt, ) await page.goto('/') const header = page.locator('header') await expect(header.getByText('test@bilhej.se')).toBeVisible() await expect( header.getByRole('button', { name: 'Logga ut' }), ).toBeVisible() }) test('shows orders link when authenticated', async ({ page }) => { const jwt = makeJwt({ sub: 'test@bilhej.se', role: 'user' }) await page.goto('/') await page.evaluate( (token) => localStorage.setItem('auth_token', token), jwt, ) await page.goto('/') const header = page.locator('header') const ordersLink = header.getByRole('link', { name: 'Mina beställningar', }) await expect(ordersLink).toBeVisible() await expect(ordersLink).toHaveAttribute('href', '/orders') }) test('hides login and register links when authenticated', async ({ page, }) => { const jwt = makeJwt({ sub: 'test@bilhej.se', role: 'user' }) await page.goto('/') await page.evaluate( (token) => localStorage.setItem('auth_token', token), jwt, ) await page.goto('/') const header = page.locator('header') await expect( header.getByRole('link', { name: 'Logga in' }), ).not.toBeVisible() await expect( header.getByRole('link', { name: 'Registrera' }), ).not.toBeVisible() }) test('logout restores login and register links', async ({ page }) => { const jwt = makeJwt({ sub: 'test@bilhej.se', role: 'user' }) await page.goto('/') await page.evaluate( (token) => localStorage.setItem('auth_token', token), jwt, ) await page.goto('/') const header = page.locator('header') await header.getByRole('button', { name: 'Logga ut' }).click() await expect( header.getByRole('link', { name: 'Logga in' }), ).toBeVisible() await expect( header.getByRole('link', { name: 'Registrera' }), ).toBeVisible() await expect( header.getByRole('button', { name: 'Logga ut' }), ).not.toBeVisible() await expect(header.getByText('test@bilhej.se')).not.toBeVisible() }) test('logout redirects to home page', async ({ page }) => { await page.route('**/api/orders', (route) => route.fulfill({ status: 200, contentType: 'application/json', body: '[]', }), ) const jwt = makeJwt({ sub: 'test@bilhej.se', role: 'user' }) await page.goto('/orders') await page.evaluate( (token) => localStorage.setItem('auth_token', token), jwt, ) await page.goto('/orders') await page.waitForURL('/orders') await page.locator('header').getByRole('button', { name: 'Logga ut' }).click() await expect(page).toHaveURL('/') }) test('shows admin link when admin is authenticated', async ({ page }) => { const jwt = makeJwt({ sub: 'admin@bilhalsning.se', role: 'admin' }) await page.goto('/') await page.evaluate( (token) => localStorage.setItem('auth_token', token), jwt, ) await page.goto('/') const header = page.locator('header') const adminLink = header.getByRole('link', { name: 'Admin' }) await expect(adminLink).toBeVisible() await expect(adminLink).toHaveAttribute('href', '/admin') }) test('does not show admin link for regular user', async ({ page }) => { const jwt = makeJwt({ sub: 'test@bilhej.se', role: 'user' }) await page.goto('/') await page.evaluate( (token) => localStorage.setItem('auth_token', token), jwt, ) await page.goto('/') const header = page.locator('header') await expect( header.getByRole('link', { name: 'Admin' }), ).not.toBeVisible() }) test('shows settings button when authenticated', async ({ page }) => { await authenticateUser(page) const header = page.locator('header') await expect( header.getByRole('button', { name: 'Inställningar' }), ).toBeVisible() }) test('settings menu links to change email and password pages', async ({ page, }) => { await authenticateUser(page) const header = page.locator('header') const settingsButton = header.getByRole('button', { name: 'Inställningar' }) await settingsButton.click() const menu = header.getByRole('menu') await expect( menu.getByRole('menuitem', { name: 'Byt e-postadress' }), ).toHaveAttribute('href', '/andra-epost') await expect( menu.getByRole('menuitem', { name: 'Byt lösenord' }), ).toHaveAttribute('href', '/andra-losenord') }) test('highlights settings button on change password page', async ({ page, }) => { await authenticateUser(page) await page.goto('/andra-losenord') const settingsButton = page .locator('header') .getByRole('button', { name: 'Inställningar' }) await expect(settingsButton).toHaveClass(/app-header__settings-trigger--active/) await expect( page.getByRole('heading', { name: 'Byt lösenord' }), ).toBeVisible() }) test('highlights settings button on change email page', async ({ page }) => { await authenticateUser(page) await page.goto('/andra-epost') const settingsButton = page .locator('header') .getByRole('button', { name: 'Inställningar' }) await expect(settingsButton).toHaveClass(/app-header__settings-trigger--active/) await expect( page.getByRole('heading', { name: 'Byt e-postadress' }), ).toBeVisible() }) }) test.describe('Header on mobile viewport', () => { test.use({ viewport: { width: 390, height: 844 } }) test('menu reveals navigation links when authenticated', async ({ page }) => { await authenticateUser(page) await page.goto('/') const header = page.locator('header') await expect( header.getByRole('link', { name: 'Mina beställningar' }), ).not.toBeVisible() await header.getByRole('button', { name: 'Öppna meny' }).click() await expect( header.getByRole('link', { name: 'Mina beställningar' }), ).toBeVisible() await expect( header.getByRole('link', { name: 'Byt e-postadress' }), ).toBeVisible() }) test('home page has no horizontal overflow', async ({ page }) => { await page.goto('/') const scrollWidth = await page.evaluate( () => document.documentElement.scrollWidth, ) const clientWidth = await page.evaluate( () => document.documentElement.clientWidth, ) expect(scrollWidth).toBeLessThanOrEqual(clientWidth + 1) }) }) async function authenticateUser(page: import('@playwright/test').Page) { const jwt = makeJwt({ sub: 'test@bilhej.se', role: 'user' }) await page.goto('/') await page.evaluate((token) => localStorage.setItem('auth_token', token), jwt) await page.goto('/') } function makeJwt(payload: Record): string { const header = btoa(JSON.stringify({ alg: 'HS256', typ: 'JWT' })) const body = btoa(JSON.stringify(payload)) const signature = 'test-sig' return `${header}.${body}.${signature}` }