From 6b2c63caea9efb103cdf08a74559950773429e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sun, 17 May 2026 14:13:39 +0200 Subject: [PATCH] test(medications): pin intake-history-list-v2 status render contract Add two SSR fixtures to lock the v1.4.37 W3 fix in place: a mixed taken+skipped seed asserts the distinct lucide icon + green styling for taken rows and the muted outline styling for skipped rows, and a German-locale skipped-only seed proves the table body never leaks the "Eingenommen" label onto a skipped row. The seed helper threads the new `status:"completed"` cache-key shard so the component reads its own seed without firing a network call. --- .../__tests__/intake-history-list-v2.test.tsx | 89 ++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/src/components/medications/__tests__/intake-history-list-v2.test.tsx b/src/components/medications/__tests__/intake-history-list-v2.test.tsx index 04ada67d2..f1843953e 100644 --- a/src/components/medications/__tests__/intake-history-list-v2.test.tsx +++ b/src/components/medications/__tests__/intake-history-list-v2.test.tsx @@ -61,13 +61,16 @@ function seedIntake( const sortDir = opts.sortDir ?? "desc"; const limit = opts.limit ?? 25; const offset = opts.offset ?? 0; + // v1.4.37 W3 — the component pins `status:"completed"` on the + // server-side query and threads it through the cache key, so the + // seed mirrors that shape verbatim. client.setQueryData( [ "medications", medId, "intake", "list", - { sortBy, sortDir, limit, offset }, + { sortBy, sortDir, limit, offset, status: "completed" }, ], { events: rows, meta: { total, limit, offset } }, ); @@ -148,6 +151,90 @@ describe(" — populated rows", () => { expect(html).toContain("Telegram / Reminder"); }); + it("renders the taken row with a green Check chip and the skipped row with an outline SkipForward chip", () => { + // v1.4.37 W3 — guards the regression Marc reported on 2026-05-17: + // before the fix, every row used the same secondary badge with the + // "Eingenommen" label regardless of skipped status. The chip must + // surface a distinct icon + label per branch and never label a + // skipped row "Eingenommen". + const client = makeClient(); + seedIntake(client, "med-status", [ + { + id: "evt-taken", + medicationId: "med-status", + scheduledFor: "2026-05-15T08:00:00.000Z", + takenAt: "2026-05-15T08:02:00.000Z", + skipped: false, + source: "WEB", + createdAt: "2026-05-15T08:02:00.000Z", + }, + { + id: "evt-skipped", + medicationId: "med-status", + scheduledFor: "2026-05-14T08:00:00.000Z", + takenAt: null, + skipped: true, + source: "REMINDER", + createdAt: "2026-05-14T20:00:00.000Z", + }, + ]); + const html = render( + , + client, + ); + + // Distinct lucide icons per branch — proves the row matched the + // correct status arm and isn't just printing a label. + expect(html).toContain("lucide-check"); + expect(html).toContain("lucide-skip-forward"); + + // The green styling pins the taken branch visually so a future + // refactor cannot silently collapse the two chips back into one + // neutral badge. + expect(html).toMatch(/bg-green-500\/20[^"]*text-green-400/); + + // Skipped rows render as a muted outline chip — never as the + // secondary "Eingenommen" badge. + expect(html).toMatch(/text-muted-foreground[^"]*gap-1[^"]*text-xs/); + + expect(html).toContain("Taken"); + expect(html).toContain("Skipped"); + }); + + it("renders the skipped chip in German without leaking the Eingenommen label", () => { + // v1.4.37 W3 — UAT echo. Marc reported a German row labelled + // both "übersprungen" and "eingenommen". The fix means a + // skipped-only fixture renders "Übersprungen" exactly once and + // "Eingenommen" zero times. + const client = makeClient(); + seedIntake(client, "med-skipped", [ + { + id: "evt-skipped", + medicationId: "med-skipped", + scheduledFor: "2026-04-29T05:00:00.000Z", + takenAt: null, + skipped: true, + source: "REMINDER", + createdAt: "2026-04-29T05:01:00.000Z", + }, + ]); + const html = render( + , + client, + "de", + ); + + // Locate the table-body slice so we only count chip labels, not + // the column headers (which also say "Eingenommen" for the + // takenAt column header). + const tbodyMatch = html.match(//); + expect(tbodyMatch).not.toBeNull(); + const body = tbodyMatch?.[0] ?? ""; + + expect(body).toContain("Übersprungen"); + expect(body).not.toContain("Eingenommen"); + }); + it("renders the section title across both locales", () => { const client = makeClient(); seedIntake(client, "med-1", []);