From 6e85cbb2f19650e9e8b1d8f0e6f658e43bd9dd86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Mon, 10 Aug 2026 10:21:27 +0200 Subject: [PATCH] test(e2e): scan the mood insights page and fix its stale a11y mock The `/api/mood/insights` mock still returned the pre-heatmap shape, so `summary.totalEntries` was undefined, the empty-state guard never short-circuited, and the page threw reading `heatmap.cells`. Correct the mock to the current MoodInsightsResponse and add `/insights/mood` to the a11y route matrix so the page is scanned henceforth. --- e2e/a11y.spec.ts | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/e2e/a11y.spec.ts b/e2e/a11y.spec.ts index 855a160a0..5311a50d8 100644 --- a/e2e/a11y.spec.ts +++ b/e2e/a11y.spec.ts @@ -329,11 +329,32 @@ async function installA11yMocks(page: Page) { }), ); + // Matches the current `MoodInsightsResponse` (mood-insights-shared.tsx): the + // sections short-circuit on `summary.totalEntries === 0` and then read + // `heatmap.cells`, so `totalEntries` and a populated `heatmap` are both + // required or the page throws into its error boundary. Breakdown arrays are + // present-but-empty; the correlations block carries every metric key. await page.route("**/api/mood/insights", (route) => fulfilJson(route, { - summary: { count: 1 }, - tagBreakdown: [], - trends: [], + summary: { totalEntries: 1, inTargetPct: null }, + heatmap: { + windowDays: 30, + cells: [{ date: "2026-07-20", score: 4, samples: 1 }], + }, + distribution: [], + weekday: [], + timeOfDay: { buckets: [], reliable: false, best: null, worst: null }, + stability: null, + tags: [], + structuredTags: [], + narratives: [], + correlations: { + sleep: { result: null, points: [], n: 0 }, + steps: { result: null, points: [], n: 0 }, + pulse: { result: null, points: [], n: 0 }, + weight: { result: null, points: [], n: 0 }, + bloodPressureSystolic: { result: null, points: [], n: 0 }, + }, }), ); @@ -689,6 +710,15 @@ const INSIGHTS_ROUTES: readonly RouteCase[] = [ path: "/insights/weight", painted: (page) => page.locator(".recharts-wrapper").first(), }, + { + // Mood is event-driven, so its sub-page renders the heatmap and the mood + // line chart from `/api/mood/insights` rather than a MeasurementType series. + // Gate on the line chart's recharts wrapper — the same painted signal the + // weight sub-page uses — so the scan waits for the heavy content to land. + name: "/insights/mood metric subpage", + path: "/insights/mood", + painted: (page) => page.locator(".recharts-wrapper").first(), + }, { // The two states this page's OWN render produces: the list, or the // no-workouts empty state. Never `[role="status"]`, because the busy