mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 14:32:03 +00:00
test: prove the banner names the kind of record, not just tags it
recordKindLabel chooses between two sentences that mean different things and nothing could fail it: the journey asserted the data attribute, which that function never reads, so inverting the arms left the suite green while a guardian standing inside a managed profile was told it was an ordinary shared record.
This commit is contained in:
1 parent
7175db33f7
commit
47c4560253
3 files changed
+99
-2
No files matched your search
@@ -595,9 +595,18 @@ test.describe.serial("managed profile browser journey", () => {
|
||||
const banner = page.locator('[data-slot="shared-record-banner"]');
|
||||
await expect(banner).toBeVisible();
|
||||
await expect(banner).toHaveAttribute("data-record-kind", "managed");
|
||||
// The WORDING, not only the attribute, and this is the one place in the
|
||||
// suite where pinning copy is the right call rather than the lazy one: the
|
||||
// claim is that the banner NAMES it as a managed record, and the attribute
|
||||
// is not what a person reads. `recordKindLabel`'s ternary chooses between
|
||||
// two sentences that mean different things, and inverting it left every
|
||||
// attribute assertion green while telling a Guardian they were inside an
|
||||
// ordinary shared record. The pure function is pinned in
|
||||
// `src/components/layout/__tests__/shared-record-banner-label.test.tsx`;
|
||||
// this line proves the rendered banner really calls it.
|
||||
await expect(
|
||||
page.locator('[data-slot="shared-record-banner-context"]'),
|
||||
).toBeVisible();
|
||||
).toContainText("Managed profile");
|
||||
|
||||
// And back out, with the record still on the list.
|
||||
//
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* The banner names which KIND of record this is, and the two names differ.
|
||||
*
|
||||
* ## Why this file exists
|
||||
*
|
||||
* `recordKindLabel` is a two-arm ternary, and until this file nothing could
|
||||
* fail it. The browser journey asserted `data-record-kind="managed"` — an
|
||||
* attribute the function does not read — so inverting the arms left the whole
|
||||
* suite green while the banner told a Guardian standing inside a managed
|
||||
* profile that they were in an ordinary shared record. That is not a cosmetic
|
||||
* difference: the two records have different rules, and the banner is the one
|
||||
* line of chrome whose job is to say which one you are in.
|
||||
*
|
||||
* The mapping is asserted through the real EN bundle rather than against key
|
||||
* names, because a key that resolves to the wrong sentence passes a key-level
|
||||
* check. Both arms are named, and the two are asserted to be DIFFERENT — a
|
||||
* function that returned one sentence for both would satisfy every "contains"
|
||||
* assertion anybody would think to write.
|
||||
*/
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { recordKindLabel } from "../shared-record-banner";
|
||||
|
||||
/** The real bundle, so the assertion is about sentences and not about keys. */
|
||||
const EN = JSON.parse(
|
||||
readFileSync(join(process.cwd(), "messages/en.json"), "utf8"),
|
||||
) as {
|
||||
recordSharing: { lookingAfter: { kindManaged: string; kindShared: string } };
|
||||
};
|
||||
|
||||
/** The i18n `t` as the banner receives it, resolved against the real bundle. */
|
||||
const t = (key: string): string => {
|
||||
const leaf = key
|
||||
.split(".")
|
||||
.reduce<unknown>(
|
||||
(node, segment) =>
|
||||
typeof node === "object" && node !== null
|
||||
? (node as Record<string, unknown>)[segment]
|
||||
: undefined,
|
||||
EN,
|
||||
);
|
||||
if (typeof leaf !== "string") throw new Error(`unresolved key: ${key}`);
|
||||
return leaf;
|
||||
};
|
||||
|
||||
describe("what the shared-record banner calls the record", () => {
|
||||
it("has a translator that really resolves", () => {
|
||||
// Positive control. A `t` that returned its own key would make both legs
|
||||
// below pass on the key names while proving nothing about the sentences.
|
||||
expect(t("recordSharing.lookingAfter.kindManaged")).toBe(
|
||||
EN.recordSharing.lookingAfter.kindManaged,
|
||||
);
|
||||
expect(EN.recordSharing.lookingAfter.kindManaged.length).toBeGreaterThan(3);
|
||||
expect(EN.recordSharing.lookingAfter.kindShared.length).toBeGreaterThan(3);
|
||||
});
|
||||
|
||||
it("names a managed profile as one", () => {
|
||||
expect(recordKindLabel("managed", t)).toBe(
|
||||
EN.recordSharing.lookingAfter.kindManaged,
|
||||
);
|
||||
});
|
||||
|
||||
it("names an ordinary shared record as one", () => {
|
||||
expect(recordKindLabel("shared", t)).toBe(
|
||||
EN.recordSharing.lookingAfter.kindShared,
|
||||
);
|
||||
});
|
||||
|
||||
it("does not give the two the same sentence", () => {
|
||||
// The failure mode a pair of "contains" assertions cannot see.
|
||||
expect(recordKindLabel("managed", t)).not.toBe(
|
||||
recordKindLabel("shared", t),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -118,7 +118,17 @@ function accessLabel(
|
||||
: t("recordSharing.banner.readOnly");
|
||||
}
|
||||
|
||||
function recordKindLabel(
|
||||
/**
|
||||
* Which kind of record this is, in the banner's own words.
|
||||
*
|
||||
* Exported and pure because the ternary is the whole claim and nothing could
|
||||
* fail it: the browser journey asserted `data-record-kind="managed"`, which is
|
||||
* the attribute this function does not read, so inverting the two arms left
|
||||
* every test in the suite green while telling a Guardian they were inside an
|
||||
* ordinary shared record. Two sentences that mean different things are worth
|
||||
* one test.
|
||||
*/
|
||||
export function recordKindLabel(
|
||||
recordKind: ReturnType<typeof resolveRecordPresentation>["recordKind"],
|
||||
t: ReturnType<typeof useTranslations>["t"],
|
||||
): string {
|
||||
|
||||
Reference in new issue
Block a user