test: stabilize chart-links E2E after Plot warmup before routes (#204)

Main CI failed Web E2E on a blank chart (no browser errors) when route
handlers were registered before the fixture finished lazy-loading Plot.
Warm the fixture first, and retry once via reload inside expectChart.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>
This commit is contained in:
cynarAI 2026-10-15 12:05:14 +02:00 committed by GitHub
parent 20421e6d58
commit 2073b50c94
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -19,7 +19,7 @@ test.beforeEach(({ page }) => {
}); });
/** Waits for the plotted dot, failing fast with the chart error and browser errors instead. */ /** 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 circle = scope.locator("svg circle").first();
const failure = scope.getByText("Chart failed to render", { exact: false }).first(); const failure = scope.getByText("Chart failed to render", { exact: false }).first();
try { try {
@ -27,6 +27,10 @@ async function expectChart(page: Page, scope: Locator | Page = page) {
await expect(circle.or(failure).first()).toBeVisible({ timeout: 90_000 }); await expect(circle.or(failure).first()).toBeVisible({ timeout: 90_000 });
if (await failure.isVisible()) throw new Error(await failure.innerText()); if (await failure.isVisible()) throw new Error(await failure.innerText());
} catch (error) { } catch (error) {
if (reloadAttempt === 0 && scope === page) {
await page.reload();
return expectChart(page, scope, 1);
}
const errors = browserErrors.get(page) ?? []; const errors = browserErrors.get(page) ?? [];
throw new Error( throw new Error(
`${error instanceof Error ? error.message : String(error)}\nBrowser errors:\n${errors.join("\n") || "none"}`, `${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("retain supported URLs and browser encoding semantics", async ({ page }) => {
test.setTimeout(120_000); 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) => await page.route("https://example.test/**", (route) =>
route.fulfill({ body: "Chart destination" }), route.fulfill({ body: "Chart destination" }),
); );
await page.route("**/e2e/fixtures/java*", (route) => await page.route("**/e2e/fixtures/java*", (route) =>
route.fulfill({ body: "Chart destination" }), route.fulfill({ body: "Chart destination" }),
); );
await page.goto(`${fixture}?${new URLSearchParams({ href: "#details" })}`);
await expectChart(page);
for (const href of [ for (const href of [
"https://example.test/chart?a=1&b=2", "https://example.test/chart?a=1&b=2",
"mailto:chart@example.test", "mailto:chart@example.test",