From 60939475b48ec80050c8ac77536da698337dd364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Tue, 1 Sep 2026 18:51:07 +0200 Subject: [PATCH] Give an impossible reference window no verdict at all MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A floor at or above its ceiling fell through to the one-sided branch and was read as "minimum only", which paints a high reading green. That is the wrong direction for a transcription error to fail in: the colour answers a question nobody could answer from that data. Each one-sided branch now requires the OTHER bound to be absent, so a present-but-impossible pair lands on the neutral dot instead. It matches lab-reference-range-bar.tsx, which renders nothing for the same input — the two components sitting next to each other should not disagree about what a nonsense range means. The file had no test. It has one now, covering all five window shapes plus the zero-width band; with the two conditions relaxed again, exactly the two new cases fail and the four existing ones stay green. --- .../__tests__/lab-trend-sparkline.test.tsx | 82 +++++++++++++++++++ src/components/labs/lab-trend-sparkline.tsx | 10 ++- 2 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/components/labs/__tests__/lab-trend-sparkline.test.tsx diff --git a/src/components/labs/__tests__/lab-trend-sparkline.test.tsx b/src/components/labs/__tests__/lab-trend-sparkline.test.tsx new file mode 100644 index 000000000..6b53ebb31 --- /dev/null +++ b/src/components/labs/__tests__/lab-trend-sparkline.test.tsx @@ -0,0 +1,82 @@ +/** + * Which colour each reading earns, for every shape a reference window can + * arrive in. + * + * The case worth spelling out is the inverted pair. A floor at or above its + * ceiling is not a one-sided window, it is a window that cannot be true, and + * the tempting reading — "well, we still have a minimum" — paints a high value + * green. That is the wrong direction for a transcription error to fail in, so + * it earns no verdict at all, matching what `lab-reference-range-bar.tsx` does + * with the same input. + */ +import { describe, expect, it } from "vitest"; +import { renderToStaticMarkup } from "react-dom/server"; + +import { LabTrendSparkline } from "../lab-trend-sparkline"; + +const READINGS = [10, 50, 150]; +const MUTED = [ + "fill-muted-foreground", + "fill-muted-foreground", + "fill-muted-foreground", +]; + +/** The fill class of each plotted reading, oldest → newest. */ +function fills( + referenceLow: number | null, + referenceHigh: number | null, +): string[] { + const markup = renderToStaticMarkup( + , + ); + // Each reading is a small rect, not a circle — this PR squares them off to + // match the reference-range bar's marker. + return Array.from(markup.matchAll(/]*class="([^"]*)"/gu)).map( + (m) => m[1], + ); +} + +describe("a reading's colour against its reference window", () => { + it("judges against a real band", () => { + expect(fills(30, 100)).toEqual([ + "fill-info", + "fill-success", + "fill-warning", + ]); + }); + + it("judges a floor-only window", () => { + expect(fills(30, null)).toEqual([ + "fill-info", + "fill-success", + "fill-success", + ]); + }); + + it("judges a ceiling-only window", () => { + expect(fills(null, 100)).toEqual([ + "fill-success", + "fill-success", + "fill-warning", + ]); + }); + + it("gives no verdict without a window", () => { + expect(fills(null, null)).toEqual(MUTED); + }); + + it("gives no verdict on an inverted pair rather than reading it as a floor", () => { + // 100/30 — the same numbers as the valid band, transposed. Read as + // "minimum 100" this would paint 150 green and 50 flagged. + expect(fills(100, 30)).toEqual(MUTED); + }); + + it("gives no verdict when floor and ceiling are equal", () => { + // A zero-width band cannot separate "inside" from "outside" either. + expect(fills(50, 50)).toEqual(MUTED); + }); +}); diff --git a/src/components/labs/lab-trend-sparkline.tsx b/src/components/labs/lab-trend-sparkline.tsx index 8d25e767a..e2e297a08 100644 --- a/src/components/labs/lab-trend-sparkline.tsx +++ b/src/components/labs/lab-trend-sparkline.tsx @@ -63,10 +63,16 @@ export function LabTrendSparkline({ if (value > referenceHigh) return "fill-warning"; return "fill-success"; } - if (referenceLow !== null) { + // Each one-sided branch requires the OTHER bound to be absent. Without + // that, a present-but-impossible pair (floor at or above ceiling) reads as + // "minimum only" and paints a high value green — the wrong direction for a + // transcription error to fail in. Falling through to the neutral dot + // matches `lab-reference-range-bar.tsx`, which renders nothing at all for + // the same input: a range that cannot be true earns no verdict. + if (referenceLow !== null && referenceHigh === null) { return value < referenceLow ? "fill-info" : "fill-success"; } - if (referenceHigh !== null) { + if (referenceHigh !== null && referenceLow === null) { return value > referenceHigh ? "fill-warning" : "fill-success"; } return "fill-muted-foreground";