mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-07 04:12:04 +00:00
test(e2e): keep route mocks authoritative against the v1.18.6 service worker
The production build registers a service worker whose v1.18.6 data branch serves allowlisted GET /api/* reads network-first. A worker-originated fetch is not subject to Playwright's page.route interception, so the worker re-fetched the real (empty) backend and bypassed every per-spec route.fulfill — a just-created row never surfaced and read-after-write assertions failed. Block the worker in the test context so the route mocks are authoritative; the shipped offline cache is untouched for real users. Separately, the dashboard now batches chart series into /api/measurements/series-batch, a sub-path the **/api/measurements* glob does not match, so it fell through to the empty backend and each chart painted an empty preloaded slice; stub the endpoint with the same populated set.
This commit is contained in:
1 parent
9633d66eea
commit
3cf9a262ca
2 files changed
+54
No files matched your search
@@ -98,10 +98,53 @@ test.describe("authenticated dashboard render", () => {
|
||||
}),
|
||||
);
|
||||
|
||||
// v1.18.6 — the dashboard now batches every visible chart's daily
|
||||
// series into ONE `/api/measurements/series-batch` round-trip and
|
||||
// hands each chart its slice via `preloadedSeries`. The route is a
|
||||
// sub-path of `/api/measurements`, which the `**/api/measurements*`
|
||||
// glob below does NOT match (Playwright's `*` does not cross `/`), so
|
||||
// without an explicit stub the request fell through to the real
|
||||
// backend. The seed user has no measurements, so the route returned
|
||||
// every requested type as an EMPTY array — and an empty-but-present
|
||||
// slice satisfies the chart's preloaded-coverage check, so each chart
|
||||
// rendered the batched empty slice instead of self-fetching. Mock the
|
||||
// endpoint with the same populated set so the charts paint.
|
||||
await page.route(/\/api\/measurements\/series-batch(\?|$)/, (route) => {
|
||||
const url = new URL(route.request().url());
|
||||
const types = (url.searchParams.get("types") ?? "WEIGHT").split(",");
|
||||
const series: Record<
|
||||
string,
|
||||
Array<{ type: string; value: number; measuredAt: string; count: number }>
|
||||
> = {};
|
||||
for (const type of types) {
|
||||
const baseValue =
|
||||
type === "BLOOD_PRESSURE_SYS"
|
||||
? 124
|
||||
: type === "BLOOD_PRESSURE_DIA"
|
||||
? 80
|
||||
: type === "PULSE"
|
||||
? 70
|
||||
: 78.5;
|
||||
series[type] = Array.from({ length: 10 }, (_, i) => ({
|
||||
type,
|
||||
value: baseValue + (i % 3) - 1,
|
||||
measuredAt: new Date(Date.now() - i * 86_400_000).toISOString(),
|
||||
count: 1,
|
||||
}));
|
||||
}
|
||||
return route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ data: { series }, error: null }),
|
||||
});
|
||||
});
|
||||
|
||||
// The chart's per-type fetch reads `json.data.measurements` and
|
||||
// expects a `meta.total`. Return a small dataset so the chart has
|
||||
// points to plot — otherwise Recharts mounts a placeholder instead
|
||||
// of the recharts-wrapper SVG and the assertion below times out.
|
||||
// (Self-fetch fallback for any chart not covered by the batch above,
|
||||
// e.g. a range-tab change that drops batched coverage.)
|
||||
await page.route("**/api/measurements*", (route) => {
|
||||
const url = new URL(route.request().url());
|
||||
const type = url.searchParams.get("type") ?? "WEIGHT";
|
||||
|
||||
@@ -33,6 +33,17 @@ export default defineConfig({
|
||||
trace: "retain-on-failure",
|
||||
screenshot: "only-on-failure",
|
||||
video: "retain-on-failure",
|
||||
// v1.18.6 — block the service worker in the test context. The
|
||||
// production build registers `/sw.js`, whose v1.18.6 data branch
|
||||
// serves allowlisted `/api/*` GET reads network-first. A worker-
|
||||
// originated `fetch` is NOT subject to Playwright's `page.route`
|
||||
// interception, so the SW would re-fetch the real (empty) backend
|
||||
// and serve that — bypassing every per-spec `route.fulfill` mock and
|
||||
// breaking read-after-write assertions (a just-created row never
|
||||
// surfaced). Blocking the worker keeps the route mocks authoritative
|
||||
// without weakening the shipped SW behaviour. Real users keep the
|
||||
// offline data cache; only the test harness opts out.
|
||||
serviceWorkers: "block",
|
||||
// HealthLog ships dark mode as the default (Dracula theme) — `globals.css`
|
||||
// sets `color-scheme: dark` on the root and the `<ThemeProvider>` defaults
|
||||
// to "system". Playwright's stock context is `colorScheme: "light"`, which
|
||||
|
||||
Reference in new issue
Block a user