evOo-local/apps/web/e2e/route-deep-link-matrix.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

67 lines
2.7 KiB
TypeScript

import { expect, test } from "@playwright/test";
import {
attachConsoleGuard,
completeOnboarding,
rpc,
signup,
waitForChatComposer,
} from "./helpers";
const mobile = { viewport: { width: 390, height: 844 }, isMobile: true, hasTouch: true };
test.describe("signed out deep links", () => {
test.use(mobile);
for (const { path, expectUrl, expectText } of [
{ path: "/", expectUrl: /\/($|\?)/, expectText: /evOo|Willkommen|Welcome/i },
{ path: "/sign-in", expectUrl: /\/sign-in/, expectText: /Sign in to evOo|Bei evOo anmelden/i },
{ path: "/sign-up", expectUrl: /\/sign-up/, expectText: /Create account|Konto erstellen/i },
{ path: "/forgot-password", expectUrl: /\/forgot-password/, expectText: /password|Passwort/i },
{ path: "/onboarding", expectUrl: /\/sign-in/, expectText: /Sign in|Anmelden/i },
{ path: "/app/heute", expectUrl: /\/sign-in/, expectText: /Sign in|Anmelden/i },
{ path: "/app/g/example-group", expectUrl: /\/sign-in/, expectText: /Sign in|Anmelden/i },
{ path: "/app/example-bot", expectUrl: /\/sign-in/, expectText: /Sign in|Anmelden/i },
]) {
test(`load ${path} without console errors`, async ({ page }) => {
const errors = attachConsoleGuard(page);
await page.goto(path, { waitUntil: "domcontentloaded" });
await expect(page).toHaveURL(expectUrl);
await expect(page.locator("body")).toContainText(expectText);
expect(errors, errors.join("\n")).toEqual([]);
});
}
});
test.describe("signed in reload matrix", () => {
test.use(mobile);
test("core app routes reload cleanly", async ({ page }) => {
const errors = attachConsoleGuard(page);
const stamp = Date.now();
await signup(page, `deeplink-${stamp}@rakazo.test`, "password12", "Deep Link");
await completeOnboarding(page, undefined, { mainConversation: true });
await waitForChatComposer(page);
const groupId = page.url().match(/\/app\/g\/([^/]+)/)?.[1];
const bots = await rpc<Array<{ id: string }>>(page, "bots/list", null);
const botId = bots[0]?.id;
expect(groupId).toBeTruthy();
expect(botId).toBeTruthy();
const routes = [`/app/heute`, `/app/g/${groupId}`, `/app/${botId}`, `/onboarding`];
for (const route of routes) {
await page.goto(route, { waitUntil: "domcontentloaded" });
if (route === "/onboarding") {
await expect(page).toHaveURL(/\/(app|onboarding)/);
} else {
await expect(page.getByTestId("shell-root")).toHaveAttribute("data-ready", "true", {
timeout: 60_000,
});
}
await page.reload({ waitUntil: "domcontentloaded" });
await expect(page.locator("body")).not.toBeEmpty();
expect(errors, errors.join("\n")).toEqual([]);
}
});
});