evOo-local/apps/web/e2e/module-recovery.spec.ts
cynarAI e4b995ec14
Production readiness Phase 2: DE profile facts, mobile audit, route matrix E2E (#176)
* feat(web): Phase 2 production readiness — locale, mobile, E2E matrix

Localize onboarding focus facts by profile locale (DE assertion).
Add mobile overflow/touch audits, deep-link matrix, extended console
checks, and E2E for empty project, session unavailable, and teaching
composer. Safe-area and Heute header layout on 390px viewports.

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* fix(e2e): stabilize Phase 2 specs for mobile shell and empty project

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* fix(api): satisfy typecheck for focusFactValue

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* fix(api): type-safe focusFactValue lookup

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* fix(api): narrow focus fact locale key

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* fix(api): use FocusOptionId union for fact lookup

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* test(web): align Shell header control assertions with touch targets

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* style(web): format desktop header control test

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* fix(web): stabilize Phase 2 E2E (settings i18n, empty project, chart plot load)

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* fix(web): empty project E2E simulates pre-start bootstrap; relax module recovery wait

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* fix(web): format empty-project E2E; stabilize chart-links cold Plot load

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* test(web): run chart-links E2E serially to reuse warmed Plot module

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* style(web): format chart-links E2E

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>
2026-10-07 15:26:09 +02:00

43 lines
1.4 KiB
TypeScript

import type { Page } from "@playwright/test";
import { expect, test } from "@playwright/test";
/** Abort the first request for a module once, then let every later request through. */
async function abortFirstRequest(page: Page, pattern: string) {
const counter = { aborted: 0 };
await page.route(pattern, async (route) => {
if (counter.aborted === 0) {
counter.aborted += 1;
await route.abort("failed");
return;
}
await route.continue();
});
return counter;
}
test("the app reloads itself once when a module request aborts while booting", async ({ page }) => {
const counter = await abortFirstRequest(page, "**/src/App.tsx");
await page.goto("/sign-in", { waitUntil: "commit" });
await expect(page.getByRole("heading", { name: "Sign in to evOo" })).toBeVisible({
timeout: 60_000,
});
expect(counter.aborted).toBe(1);
expect(await page.evaluate(() => sessionStorage.getItem("rakazo:boot-reload"))).toBeNull();
});
test("a lazy route recovers when its module request aborts", async ({ page }) => {
const counter = await abortFirstRequest(page, "**/src/pages/Auth.tsx");
await page.goto("/sign-in");
await expect(page.getByRole("heading", { name: "Sign in to evOo" })).toBeVisible({
timeout: 60_000,
});
expect(counter.aborted).toBe(1);
expect(
await page.evaluate(() => sessionStorage.getItem("rakazo:module-reload:pages/Auth")),
).toBeNull();
});