fix(e2e): skip desktop-sidebar specs on mobile + stub /api/dashboard/widgets

Three remaining e2e failures after the global-setup tour-completed fix
all came from cross-project sharing — specs that target desktop-only
DOM (the `aside[aria-label="Sidebar"]` logo + Achievements link)
were running in the chromium-mobile profile too, where the sidebar
is `hidden md:flex` by design. Added `test.skip(viewport.width < 768,
...)` guards so each spec only runs in the project that can satisfy
its contract.

The fourth failure was the `/api/dashboard/widgets` endpoint that the
A5 tile-strip work added since `onboarding-flicker.spec.ts` was
written. Without a stub the unauthenticated dashboard 500s on this
query and React Query's error boundary swallows the page render
before `<GettingStartedChecklist>` mounts. Added the stub to both
flicker specs (complete + incomplete-onboarding paths).
This commit is contained in:
Marc-André Bombeck committed 2026-05-10 00:50:00 +02:00
1 parent 71652ec751
commit 00848b7ed5
3 files changed
+56 -4

No files matched your search

+12
View File
@@ -119,7 +119,19 @@ test.describe("axe-core authenticated surfaces", () => {
// bounding box must accept the click.
test("skip-link does not block logo click outside focus", async ({
page,
viewport,
}) => {
// The desktop sidebar (and its logo) is `hidden md:flex` — the
// mobile profile (Pixel 5) hides it by design. The skip-link
// regression Marc originally reported in v1.4.14 was a desktop-
// only artifact (mobile uses the topbar logo, which is a
// different DOM node). Skip the mobile project so we don't
// flake on a contract that doesn't apply there.
test.skip(
(viewport?.width ?? 0) < 768,
"desktop sidebar logo is hidden on mobile by design",
);
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.waitForLoadState("networkidle");
+16 -4
View File
@@ -55,11 +55,23 @@ test.describe("achievements page is reachable from the sidebar", () => {
);
});
test("desktop sidebar exposes the achievements link", async ({ page }) => {
test("desktop sidebar exposes the achievements link", async ({
page,
viewport,
}) => {
// The sidebar nav is hidden on small viewports (`md:flex`). The
// chromium-mobile profile (Pixel 5, 393 px wide) cannot satisfy
// this contract by design — skip there so the spec only runs in
// the chromium-desktop project (1280×720). Without this guard
// every push fails 1 / 4 specs purely because the same suite is
// sharded across both projects.
test.skip(
(viewport?.width ?? 0) < 768,
"sidebar is hidden on mobile by design (md:flex breakpoint)",
);
await page.goto("/", { waitUntil: "domcontentloaded" });
// The sidebar nav is hidden on small viewports (`md:flex`); the
// chromium-desktop project uses 1280×720 so it's visible here. Match
// by aria-label so we don't accidentally pick up a tooltip.
// Match by aria-label so we don't accidentally pick up a tooltip.
const sidebar = page.locator('aside[aria-label="Sidebar"]');
await expect(sidebar).toBeVisible();
await sidebar.getByRole("link", { name: "Achievements" }).click();
+28
View File
@@ -94,6 +94,19 @@ test.describe("dashboard onboarding card flicker guard", () => {
}),
}),
);
// Same `/api/dashboard/widgets` stub as the incomplete-onboarding
// test below — keeps the dashboard from error-boundary-bailing
// when this query 500s in CI without a real session.
await page.route("**/api/dashboard/widgets", (route) =>
route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
data: { tilesVisible: { weight: true, bp: true, pulse: true } },
error: null,
}),
}),
);
const card = page.locator('[data-testid="onboarding-card"]');
@@ -192,6 +205,21 @@ test.describe("dashboard onboarding card flicker guard", () => {
body: JSON.stringify({ data: { channels: [] }, error: null }),
}),
);
// v1.4.16 Wave-C — the dashboard added `/api/dashboard/widgets`
// (A5 tile-strip persistence) since this spec was written. Without
// a stub the unauthenticated layout query 500s in CI and React
// Query's error boundary swallows the page render before
// `<GettingStartedChecklist>` can mount.
await page.route("**/api/dashboard/widgets", (route) =>
route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
data: { tilesVisible: { weight: true, bp: true, pulse: true } },
error: null,
}),
}),
);
// Make sure no localStorage carries an `expanded=1` from a previous
// session — the spec asserts the *default* is collapsed.