test: pin both HRV label keys across every locale

The tile now calls t() with a key looked up from HRV_LABEL_KEY rather
than a literal, and the call-site coverage guard only reads literal
arguments. So the label left the guard's field of view exactly when it
became per-series: dropping either key from a bundle would ship a raw
key into the dashboard of whichever locale lost it, with nothing in the
gate to say so.

The keys are read from the map, so a third HRV series is covered by
construction rather than by remembering. The count is anchored, because
an empty map would satisfy the loop by matching nothing. A second case
asserts the RMSSD label actually names the measure in every locale,
which is the whole reason the second key exists.

Verified by deleting the key from one bundle: three cases fail and name
the locale and the key.
This commit is contained in:
Marc-André Bombeck committed 2026-09-03 20:38:13 +02:00
1 parent e961be81a2
commit fde8f9c80c
1 file changed
+48
@@ -17,6 +17,7 @@ import {
unavailableWidgetIds,
} from "@/lib/dashboard/widget-modules";
import { moduleForMeasurementType } from "@/lib/modules/measurement-scope";
import { locales } from "@/lib/i18n/config";
import type { DataSummary } from "@/lib/analytics/trends";
/**
@@ -321,3 +322,50 @@ describe("a switch that cannot do anything is not offered", () => {
expect(unavailableWidgetIds({}, { hasSdnn: false })).toEqual([]);
});
});
describe("both HRV label keys are translated everywhere", () => {
// The tile now calls `t(hrvLabelKey)` with a value looked up from
// HRV_LABEL_KEY, and `i18n-call-site-coverage.test.ts` only sees literal
// `t("ns.key")` arguments. So the moment the label became per-series it
// left the guard's field of view: dropping either key from a bundle would
// ship a raw `measurements.typeHrvRmssd` into the dashboard of whichever
// locale lost it, and nothing in the gate would say so.
//
// Read from the map rather than from two literals, so a third HRV series
// added later is covered by construction instead of by remembering.
const bundles = locales.map((locale) => ({
locale,
messages: JSON.parse(
readFileSync(join(process.cwd(), "messages", `${locale}.json`), "utf8"),
) as Record<string, Record<string, string>>,
}));
it("covers every key the tile can ask for, in all seven locales", () => {
const keys = Object.values(HRV_LABEL_KEY);
// Anchor the count: an empty map would satisfy every assertion below by
// matching nothing, which is the failure mode this project keeps finding.
expect(keys.length).toBeGreaterThanOrEqual(2);
expect(bundles).toHaveLength(7);
for (const { locale, messages } of bundles) {
for (const key of keys) {
const [namespace, name] = key.split(".");
const value = messages[namespace]?.[name];
expect(
typeof value === "string" && value.trim().length > 0,
`${locale}.json is missing ${key}`,
).toBe(true);
}
}
});
it("names the measure in the RMSSD label, in every locale", () => {
// The whole point of the second key. A label that reads plain "HRV" in
// some locale puts a 40 ms RMSSD night under the same words as an SDNN
// reading, which is the misreading this change exists to prevent.
for (const { locale, messages } of bundles) {
const [ns, name] = HRV_LABEL_KEY.HRV_RMSSD.split(".");
expect(messages[ns]?.[name], `${locale}.json`).toMatch(/RMSSD/i);
}
});
});