Files
HealthLog/e2e/setup/day-mock.ts
T
Marc-André Bombeck fee6088e08 feat: open the day with one tap and from every place a day is shown
A tap on a point, a bar, a calendar cell or a date now opens the day at
once, as a click does; the tooltip's second step is gone and the tapped
value heads the day. The dashboard's charts (not its today area), the
adherence chart, the rhythm events, the ECG list and detail and the rest
mode notes open their days too.

The day's header carries the close control top left, the Coach panel's
own toggle and glyph, the date on one centred line and the arrows on the
right. While the day is docked, the Coach button and the documents bar
move clear of it.

Smooth the layer: the tooltip no longer glides into place on touch, the
neighbouring day is read before a step, the sheet animates in 300 ms and
not at all under reduced motion, and the opener stays put while the page
beside the docked day reflows.
2026-10-08 15:56:40 +02:00

116 lines
3.0 KiB
TypeScript

/**
* The day routes, answered in the contract's shape.
*
* The day itself (`GET /api/day/{date}`) and the index (`GET /api/day/index`)
* are route mocks, so a journey pins the client: which door opens which day,
* what the history does, where no door is. The server's own answers are
* pinned by the integration suite.
*/
import type { Page, Route } from "@playwright/test";
function dayFixture(date: string) {
return {
date,
tz: "Europe/Berlin",
counts: { values: 2, entries: 1 },
running: [
{
kind: "illness",
section: "illness",
id: "ep1",
title: "Common cold",
sub: null,
since: date,
until: null,
dayIndex: 1,
dayCount: null,
href: "/illness",
},
],
values: [
{
type: "BLOOD_PRESSURE_SYS",
value: 124,
unit: "mmHg",
at: `${date}T07:00:00.000Z`,
source: "MANUAL",
band: { lo: 118, hi: 128, n: 20 },
},
{
type: "BLOOD_PRESSURE_DIA",
value: 79,
unit: "mmHg",
at: `${date}T07:00:00.000Z`,
source: "MANUAL",
band: { lo: 76, hi: 82, n: 20 },
},
],
events: [
{
at: `${date}T07:00:00.000Z`,
kind: "mood",
section: "mood",
id: "m1",
title: "Mood: good",
meta: null,
note: null,
docs: [],
href: "/mood",
},
],
notable: [],
sections: {},
};
}
/**
* Every day from `from` to `to`, each holding values: what the row of day
* dots under a chart reads when the whole window has entries.
*/
function everyDay(from: string, to: string): Record<string, string[]> {
const days: Record<string, string[]> = {};
if (!from || !to) return days;
const at = new Date(`${from}T12:00:00.000Z`);
const end = new Date(`${to}T12:00:00.000Z`);
while (at <= end) {
days[at.toISOString().slice(0, 10)] = ["values"];
at.setUTCDate(at.getUTCDate() + 1);
}
return days;
}
export async function mockDay(
page: Page,
options: { index?: "empty" | "full" } = {},
) {
await page.route("**/api/day/**", async (route: Route) => {
const url = new URL(route.request().url());
if (url.pathname === "/api/day/index") {
const from = url.searchParams.get("from") ?? "";
const to = url.searchParams.get("to") ?? "";
const days = options.index === "full" ? everyDay(from, to) : {};
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
data: {
from,
to,
days,
// The first day of the window stands out: the rug draws a ring.
notable: Object.keys(days).slice(0, 1),
},
error: null,
}),
});
return;
}
const date = url.pathname.split("/").pop() ?? "";
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ data: dayFixture(date), error: null }),
});
});
}