mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 22:02:16 +00:00
test(admin): pin when the pulse day-mean card offers apply
This commit is contained in:
1 parent
17d1c00aab
commit
0a0667fd1c
1 file changed
+116
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* The pulse day-mean admin card.
|
||||
*
|
||||
* 1. apply is offered only after a dry run finished in the last seven days,
|
||||
* and never while a dry run is queued or running;
|
||||
* 2. a finished dry run shows its figures and the per-account ordinals;
|
||||
* 3. the active method reads in the header, in German too.
|
||||
*
|
||||
* Mutation check: drop `hasFreshDryRun` from `canApply` and case 1 goes red.
|
||||
*/
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
|
||||
import { PulseDayMeanCard } from "@/components/admin/pulse-day-mean-card";
|
||||
import { I18nProvider } from "@/lib/i18n/context";
|
||||
import { queryKeys } from "@/lib/query-keys";
|
||||
import type { PulseDayMeanStatus } from "@/lib/validations/pulse-day-mean";
|
||||
|
||||
const RESULT = {
|
||||
accounts: 2,
|
||||
daysCompared: 412,
|
||||
daysChangedOver1Bpm: 37,
|
||||
maxChangeBpm: 6.4,
|
||||
distribution: [
|
||||
{ bucket: "0-1" as const, days: 375 },
|
||||
{ bucket: "1-2" as const, days: 30 },
|
||||
{ bucket: "2-5" as const, days: 6 },
|
||||
{ bucket: "5+" as const, days: 1 },
|
||||
],
|
||||
perAccount: [
|
||||
{ account: "#1", days: 400, changedOver1Bpm: 36 },
|
||||
{ account: "#2", days: 12, changedOver1Bpm: 1 },
|
||||
],
|
||||
};
|
||||
|
||||
const status = (
|
||||
lastDryRun: PulseDayMeanStatus["lastDryRun"],
|
||||
method: PulseDayMeanStatus["method"] = "hour_mean_v1",
|
||||
): PulseDayMeanStatus => ({ method, appliedAt: null, lastDryRun });
|
||||
|
||||
const done = (finishedAt: string) => ({
|
||||
status: "done" as const,
|
||||
startedAt: finishedAt,
|
||||
finishedAt,
|
||||
result: RESULT,
|
||||
});
|
||||
|
||||
function render(s: PulseDayMeanStatus, locale: "en" | "de" = "en"): string {
|
||||
const client = new QueryClient();
|
||||
client.setQueryData(queryKeys.adminPulseDayMean(), s);
|
||||
return renderToStaticMarkup(
|
||||
<QueryClientProvider client={client}>
|
||||
<I18nProvider initialLocale={locale}>
|
||||
<PulseDayMeanCard />
|
||||
</I18nProvider>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
}
|
||||
|
||||
/** Whether the apply button renders disabled. */
|
||||
function applyDisabled(html: string): boolean {
|
||||
const at = html.indexOf('data-testid="admin-pulse-day-mean-apply"');
|
||||
const tag = html.slice(
|
||||
html.lastIndexOf("<button", at),
|
||||
html.indexOf(">", at),
|
||||
);
|
||||
return /\sdisabled=""/.test(tag);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers({ toFake: ["Date"] });
|
||||
vi.setSystemTime(new Date("2026-10-16T12:00:00Z"));
|
||||
});
|
||||
afterEach(() => vi.useRealTimers());
|
||||
|
||||
describe("PulseDayMeanCard", () => {
|
||||
it("offers apply only after a fresh, finished dry run", () => {
|
||||
expect(applyDisabled(render(status(null)))).toBe(true);
|
||||
expect(
|
||||
applyDisabled(render(status(done("2026-10-08T12:00:00.000Z")))),
|
||||
).toBe(true);
|
||||
expect(
|
||||
applyDisabled(
|
||||
render(
|
||||
status({
|
||||
status: "running",
|
||||
startedAt: "2026-10-16T11:00:00.000Z",
|
||||
finishedAt: null,
|
||||
result: null,
|
||||
}),
|
||||
),
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
applyDisabled(render(status(done("2026-10-15T12:00:00.000Z")))),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("shows what the dry run found", () => {
|
||||
const html = render(status(done("2026-10-15T12:00:00.000Z")));
|
||||
expect(html).toContain("412");
|
||||
expect(html).toContain("37");
|
||||
expect(html).toContain("6.4 bpm");
|
||||
expect(html).toContain("5+ bpm");
|
||||
expect(html).toContain("Account #2");
|
||||
expect(html).toContain("36 of 400 days move");
|
||||
});
|
||||
|
||||
it("names the active method, in German too", () => {
|
||||
expect(render(status(null))).toContain("Every hour equal");
|
||||
const de = render(status(null, "weighted_hour_mean_v2"), "de");
|
||||
expect(de).toContain("Dünne Stunden gewichtet");
|
||||
expect(de).toContain("Probelauf");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user