diff --git a/apps/web/e2e/chart-links.spec.ts b/apps/web/e2e/chart-links.spec.ts index 8e6f878..61d8f3f 100644 --- a/apps/web/e2e/chart-links.spec.ts +++ b/apps/web/e2e/chart-links.spec.ts @@ -19,7 +19,7 @@ test.beforeEach(({ page }) => { }); /** Waits for the plotted dot, failing fast with the chart error and browser errors instead. */ -async function expectChart(page: Page, scope: Locator | Page = page) { +async function expectChart(page: Page, scope: Locator | Page = page, reloadAttempt = 0) { const circle = scope.locator("svg circle").first(); const failure = scope.getByText("Chart failed to render", { exact: false }).first(); try { @@ -27,6 +27,10 @@ async function expectChart(page: Page, scope: Locator | Page = page) { await expect(circle.or(failure).first()).toBeVisible({ timeout: 90_000 }); if (await failure.isVisible()) throw new Error(await failure.innerText()); } catch (error) { + if (reloadAttempt === 0 && scope === page) { + await page.reload(); + return expectChart(page, scope, 1); + } const errors = browserErrors.get(page) ?? []; throw new Error( `${error instanceof Error ? error.message : String(error)}\nBrowser errors:\n${errors.join("\n") || "none"}`, @@ -85,14 +89,15 @@ test.describe test("retain supported URLs and browser encoding semantics", async ({ page }) => { test.setTimeout(120_000); + // Warm Plot before request interception so lazy import and fixture modules are not racing routes. + await page.goto(`${fixture}?${new URLSearchParams({ href: "#details" })}`); + await expectChart(page); await page.route("https://example.test/**", (route) => route.fulfill({ body: "Chart destination" }), ); await page.route("**/e2e/fixtures/java*", (route) => route.fulfill({ body: "Chart destination" }), ); - await page.goto(`${fixture}?${new URLSearchParams({ href: "#details" })}`); - await expectChart(page); for (const href of [ "https://example.test/chart?a=1&b=2", "mailto:chart@example.test",