fix(e2e): re-target compare-to tap-target check at the per-chart overlay popover

This commit is contained in:
Marc-André Bombeck committed 2026-07-28 23:24:53 +02:00
1 parent 1d784c6367
commit e7c6610c63
1 file changed
+97 -10
+97 -10
View File
@@ -1,7 +1,10 @@
import { expect, test } from "./setup/test";
import { STORAGE_STATE_PATH } from "./setup/global-setup";
import {
mockDashboardSnapshot,
WEIGHT_ONLY_SUMMARIES,
} from "./utils/mock-dashboard-snapshot";
/**
* v1.4.19 A6 — Settings consistency snapshot at Pixel-5 (393 CSS px).
* v1.4.27 — input height floor lifted from 36 px (`h-9`) to 40 px
@@ -180,16 +183,100 @@ test.describe("Settings mobile consistency (Pixel 5)", () => {
);
});
test("/settings/dashboard: Compare-to trigger renders at 44 px", async ({
page,
}) => {
await page.goto("/settings/dashboard", { waitUntil: "networkidle" });
await page.waitForLoadState("networkidle");
test("/: Compare-to trigger renders at 44 px", async ({ page }) => {
// v1.34.0 — the dashboard-settings comparison-baseline control was
// removed; the same preference now lives behind the per-chart overlay
// popover (see chart-overlay-controls.spec.ts for the full open/toggle
// flow). That popover only paints once a chart with a real chartKey
// renders, so this test needs the same seeded-chart mocks that spec
// uses rather than the real (likely-empty) e2e database.
await mockDashboardSnapshot(page, { summaries: WEIGHT_ONLY_SUMMARIES });
await page.route(/\/api\/analytics(\?|$)/, (route) =>
route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
data: {
summaries: {
WEIGHT: {
latest: 78.5,
avg7: 78.2,
avg30: 77.9,
slope30: { slope: -0.05, direction: "down" },
count: 30,
},
},
bpInTargetPct: 0,
glucoseByContext: {},
},
error: null,
}),
}),
);
await page.route("**/api/mood/analytics", (route) =>
route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
data: { entries: [], summary: { count: 0 } },
error: null,
}),
}),
);
await page.route("**/api/measurements*", (route) => {
const measurements = Array.from({ length: 10 }, (_, i) => ({
id: `m_${i}`,
type: "WEIGHT",
value: 78 + (i % 3) - 1,
measuredAt: new Date(Date.now() - i * 86_400_000).toISOString(),
notes: null,
}));
return route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
data: { measurements, meta: { total: measurements.length } },
error: null,
}),
});
});
const trigger = page.locator("#comparison-baseline");
await expect(trigger).toBeVisible();
const h = await trigger.evaluate((el) => el.getBoundingClientRect().height);
expect(Math.round(h)).toBe(44);
await page.goto("/", { waitUntil: "domcontentloaded" });
await expect(
page.locator('[data-slot="dashboard-tile-strip"]'),
).toBeVisible({ timeout: 10_000 });
const trigger = page
.locator('[data-slot="chart-overlay-controls-trigger"]')
.first();
await expect(trigger).toBeVisible({ timeout: 10_000 });
await trigger.scrollIntoViewIfNeeded();
await trigger.click();
// `data-slot="chart-overlay-comparison-baseline"` is the grid WRAPPER
// (line 235 in chart-overlay-controls.tsx); the buttons themselves are
// `data-slot="chart-overlay-comparison-{none|lastMonth|lastYear}"`.
// Match only the wrapper's children so the wrapper's own (differently
// sized) box never gets measured as if it were a tap target.
const baselineButton = page
.locator(
'[data-slot="chart-overlay-comparison-baseline"] [data-slot^="chart-overlay-comparison-"]',
)
.first();
await expect(baselineButton).toBeVisible({ timeout: 5_000 });
// `min-h-11` sets the CSS contract (`min-height: 44px`), the same
// guarantee `h-11` gives the other 44px checks in this spec. This
// element additionally carries an explicit `h-8` from the Button "sm"
// size variant that `min-height` overrides; on Playwright's Pixel 5
// profile (fractional deviceScaleFactor) that combination measures a
// `getBoundingClientRect().height` a device pixel or two under 44 even
// though the computed CSS is exactly 44px — a viewport-emulation
// rounding artifact, not a real layout regression. Assert the
// authoritative computed style instead of the physically-snapped rect.
const minHeight = await baselineButton.evaluate(
(el) => getComputedStyle(el).minHeight,
);
expect(minHeight).toBe("44px");
});
test("/settings/ai: every native select renders at 44 px", async ({