// ============================================================ // SESSION PERSISTENCE — full logout → login → still on the same // tab + same sub-pill. // // The UI's login form is gated by a Cloudflare Turnstile token // whose site key is hardcoded in index.html, which can't be // completed in the e2e container (Turnstile rejects the non-prod // origin). So the test does a programmatic logout (clear the // ped_auth cookie, same effect server-side as clicking Logout) // followed by a fresh programmatic login — this exercises the // same localStorage persistence path a real logout/login would, // without depending on the bot challenge. // ============================================================ const { test, expect, E2E_BASE, loginAs } = require('../fixtures'); async function openDesktopTab(page, name) { const vp = page.viewportSize(); if (vp && vp.width <= 768) { await page.click('#btn-menu-toggle').catch(() => {}); } await page.click(`button.tab-btn[data-tab="${name}"]`); await page.waitForFunction((t) => { const el = document.getElementById(t + '-tab'); return el && el.classList.contains('active') && el.innerHTML.trim().length > 100; }, name, { timeout: 15000 }); } async function logoutClearsCookie(context) { // Remove the ped_auth cookie — identical server-side to hitting /logout. const cookies = await context.cookies(); const keep = cookies.filter(c => c.name !== 'ped_auth'); await context.clearCookies(); if (keep.length) await context.addCookies(keep); } test.describe('Logout → login restores last tab + sub-pill', () => { test('tab choice + calc pill survive a full logout/login cycle', async ({ context, request, page }) => { await loginAs(context, request); await page.goto(E2E_BASE + '/'); await page.waitForSelector('button.tab-btn', { timeout: 15000 }); await openDesktopTab(page, 'calculators'); await page.click('button.calc-nav-pill[data-calc="bili"]'); await expect(page.locator('button.calc-nav-pill[data-calc="bili"].active')).toBeVisible(); // Simulate logout (clear session cookie) await logoutClearsCookie(context); // Visiting the app with no cookie lands on the auth screen await page.goto(E2E_BASE + '/'); await expect(page.locator('#auth-screen')).toBeVisible({ timeout: 10000 }); // Log back in (fresh cookie) and revisit the app await loginAs(context, request); await page.goto(E2E_BASE + '/'); await page.waitForSelector('button.tab-btn', { timeout: 15000 }); // Restore must put us back on Calculators / Bilirubin pill await expect(page.locator('#calculators-tab.active')).toHaveCount(1, { timeout: 10000 }); await expect(page.locator('button.calc-nav-pill[data-calc="bili"].active')).toBeVisible({ timeout: 10000 }); await expect(page.locator('#calc-bili')).not.toHaveClass(/hidden/); }); test('bedside sub-pill survives logout/login', async ({ context, request, page }) => { await loginAs(context, request); await page.goto(E2E_BASE + '/'); await page.waitForSelector('button.tab-btn', { timeout: 15000 }); await openDesktopTab(page, 'bedside'); await page.click('button.calc-pill[data-em="sepsis"]'); await expect(page.locator('button.calc-pill[data-em="sepsis"].active')).toBeVisible(); await logoutClearsCookie(context); await page.goto(E2E_BASE + '/'); await expect(page.locator('#auth-screen')).toBeVisible({ timeout: 10000 }); await loginAs(context, request); await page.goto(E2E_BASE + '/'); await page.waitForSelector('button.tab-btn', { timeout: 15000 }); await expect(page.locator('#bedside-tab.active')).toHaveCount(1, { timeout: 10000 }); await expect(page.locator('button.calc-pill[data-em="sepsis"].active')).toBeVisible({ timeout: 10000 }); await expect.poll(async () => await page.locator('#em-sepsis').evaluate(el => el.style.display), { timeout: 5000 }).not.toBe('none'); }); });