fix(e2e): fix locale cookie httpOnly and add hydration waits
Some checks failed
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Successful in 2m3s
CI / Backend Unit Tests (push) Successful in 2m13s
CI / E2E Tests (push) Successful in 17m49s

Paraglide's client-side setLocale writes the locale via document.cookie,
which silently fails for HttpOnly cookies. SvelteKit's cookies.set()
defaults to httpOnly: true, so locale switching never worked in tests.
Fix by setting httpOnly: false on the locale cookie (it's a UI preference,
not a credential — no security concern).

Add waitForSelector('[data-hydrated]') before any click that relies on
SvelteKit JavaScript event handlers. Without this, the click fires before
hydration and the onclick handler is not yet registered.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit was merged in pull request #16.
This commit is contained in:
Marcel
2026-03-19 20:28:43 +01:00
committed by marcel
parent 7988c62246
commit fe9b4a9569
3 changed files with 5 additions and 1 deletions

View File

@@ -10,6 +10,7 @@ test.describe('Language selector', () => {
test('switching to EN translates the navigation', async ({ page }) => { test('switching to EN translates the navigation', async ({ page }) => {
await page.goto('/'); await page.goto('/');
await page.waitForSelector('[data-hydrated]');
await page.getByRole('banner').getByRole('button', { name: 'EN', exact: true }).click(); await page.getByRole('banner').getByRole('button', { name: 'EN', exact: true }).click();
await expect(page.getByRole('navigation').getByRole('link', { name: 'Documents' })).toBeVisible(); await expect(page.getByRole('navigation').getByRole('link', { name: 'Documents' })).toBeVisible();
await expect(page.getByRole('navigation').getByRole('link', { name: 'Persons' })).toBeVisible(); await expect(page.getByRole('navigation').getByRole('link', { name: 'Persons' })).toBeVisible();
@@ -17,6 +18,7 @@ test.describe('Language selector', () => {
test('language choice persists after navigation', async ({ page }) => { test('language choice persists after navigation', async ({ page }) => {
await page.goto('/'); await page.goto('/');
await page.waitForSelector('[data-hydrated]');
await page.getByRole('banner').getByRole('button', { name: 'EN', exact: true }).click(); await page.getByRole('banner').getByRole('button', { name: 'EN', exact: true }).click();
await page.goto('/persons'); await page.goto('/persons');
await expect(page.getByRole('navigation').getByRole('link', { name: 'Documents' })).toBeVisible(); await expect(page.getByRole('navigation').getByRole('link', { name: 'Documents' })).toBeVisible();
@@ -24,6 +26,7 @@ test.describe('Language selector', () => {
test('switching back to DE restores German', async ({ page }) => { test('switching back to DE restores German', async ({ page }) => {
await page.goto('/'); await page.goto('/');
await page.waitForSelector('[data-hydrated]');
await page.getByRole('banner').getByRole('button', { name: 'EN', exact: true }).click(); await page.getByRole('banner').getByRole('button', { name: 'EN', exact: true }).click();
await page.getByRole('banner').getByRole('button', { name: 'DE', exact: true }).click(); await page.getByRole('banner').getByRole('button', { name: 'DE', exact: true }).click();
await expect(page.getByRole('navigation').getByRole('link', { name: 'Dokumente' })).toBeVisible(); await expect(page.getByRole('navigation').getByRole('link', { name: 'Dokumente' })).toBeVisible();

View File

@@ -87,6 +87,7 @@ test.describe('Conversations', () => {
test('sort toggle changes the button label', async ({ page }) => { test('sort toggle changes the button label', async ({ page }) => {
await page.goto('/conversations'); await page.goto('/conversations');
await page.waitForSelector('[data-hydrated]');
const btn = page.getByRole('button', { name: /Sortierung/i }); const btn = page.getByRole('button', { name: /Sortierung/i });
await expect(btn).toContainText('Neueste zuerst'); await expect(btn).toContainText('Neueste zuerst');
await btn.click(); await btn.click();

View File

@@ -11,7 +11,7 @@ const handleLocaleDetection: Handle = ({ event, resolve }) => {
if (!event.cookies.get(cookieName)) { if (!event.cookies.get(cookieName)) {
const locale = detectLocale(event.request.headers.get('accept-language') ?? ''); const locale = detectLocale(event.request.headers.get('accept-language') ?? '');
if (locale) { if (locale) {
event.cookies.set(cookieName, locale, { path: '/', sameSite: 'lax', maxAge: cookieMaxAge }); event.cookies.set(cookieName, locale, { path: '/', sameSite: 'lax', maxAge: cookieMaxAge, httpOnly: false });
} }
} }
return resolve(event); return resolve(event);