Files
HealthLog/e2e/activity-calendar.spec.ts
T
Marc-André Bombeck 5eb7caebae feat(activity): add an activity calendar with personal baseline and goals
A week or month of steps, active minutes, workouts by sport and training
load, each day placed against the person's own spread over the 84 days
before the period and each period against the median of the twelve weeks
or six months before it. Optional weekly and monthly goals live on the
account (activity_goals_json), travel with the backup and are cleared by
a data wipe. The calendar sits on the workouts page; the steps page links
to it. Computed server-side without AI.
2026-10-21 21:38:32 +02:00

69 lines
2.5 KiB
TypeScript

import { expect, test } from "./setup/test";
import { STORAGE_STATE_PATH } from "./setup/global-setup";
/**
* The activity calendar on the workouts page (D1036), at phone width: the
* card renders a whole-week grid, pages back a period, switches to the week
* view, and the goals sheet saves a goal the calendar then reports.
*/
test.describe("activity calendar", () => {
test.use({
storageState: STORAGE_STATE_PATH,
viewport: { width: 390, height: 844 },
});
test("draws the month, pages back and switches to a week", async ({
page,
}) => {
await page.goto("/insights/workouts");
const card = page.locator('[data-slot="activity-calendar"]');
await expect(card).toBeVisible();
await expect(
page.locator('[data-slot="activity-calendar-label"]'),
).not.toHaveText("");
const days = page.locator('[data-slot="activity-calendar-day"]');
const monthCount = await days.count();
if (monthCount > 0) expect(monthCount % 7).toBe(0);
const label = page.locator('[data-slot="activity-calendar-label"]');
const before = await label.textContent();
await page.locator('[data-slot="activity-calendar-previous"]').click();
await expect(label).not.toHaveText(before ?? "");
await card.getByRole("radio", { name: "Week" }).click();
if ((await days.count()) > 0) await expect(days).toHaveCount(7);
// Nothing in the card pushes the page sideways on a phone.
const overflow = await page.evaluate(
() =>
document.documentElement.scrollWidth -
document.documentElement.clientWidth,
);
expect(overflow).toBeLessThanOrEqual(0);
});
test("saves a goal and shows its progress", async ({ page }) => {
await page.goto("/insights/workouts");
await page.locator('[data-slot="activity-calendar-set-goals"]').click();
await page.getByLabel("Steps per month").fill("150000");
await page.locator('[data-slot="activity-goals-save"]').click();
await expect(
page
.locator('[data-slot="activity-calendar-goals"]')
.getByText("Steps per month"),
).toBeVisible();
// Clear it again so the account is left as it was found.
await page.locator('[data-slot="activity-calendar-set-goals"]').click();
await page.getByLabel("Steps per month").fill("");
await page.locator('[data-slot="activity-goals-save"]').click();
await expect(
page
.locator('[data-slot="activity-calendar-goals"]')
.getByText("Steps per month"),
).toHaveCount(0);
});
});