mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 06:40:50 +00:00
fix: close four small gaps around the record surface
The privacy dashboard re-implemented the audit-retention resolver with its own default and its own floor. Two implementations of one disclosure, quoted to the same person on two pages and by the purge job; it uses the shared resolver now. The record-content branch in the settings gate matched a classification rather than a page, so a second manage-writable destination would have rendered the allergy and family-history managers under its own heading without anybody choosing that. It resolves through a slug map, and the contract test fails if the map and the classification disagree in either direction — a destination cannot join the kind without somebody deciding what it renders. The managed-profile nav filter assumed a guardian grant is always manage. It is today, which is why the check was easy to leave out; an entry below that level would have listed destinations the gate refuses. Interpolation used a replacement string, and String.replace reads $&, $`, $', $1 and $$ out of one. A display name containing $' rewrote the sentence around it — and display names land in exactly the sentences that say who did what in somebody's health record. A replacer function has no $ grammar at all, which removes the class rather than escaping the members of it somebody thought of.
This commit is contained in:
1 parent
5de488c35c
commit
6ae0cc993f
9 files changed
+272
-14
No files matched your search
@@ -8,7 +8,7 @@ const authRef: {
|
||||
active: {
|
||||
accountId: string;
|
||||
recordKind: "managed" | "shared";
|
||||
level: "manage";
|
||||
level: "manage" | "write" | "read";
|
||||
sections: null;
|
||||
canWrite: true;
|
||||
} | null;
|
||||
@@ -38,10 +38,13 @@ vi.mock("../managed-record-settings-section", () => ({
|
||||
vi.mock("../managed-integration-status", () => ({
|
||||
ManagedIntegrationStatus: () => <div data-slot="managed-integrations" />,
|
||||
}));
|
||||
vi.mock("../record-anamnesis-section", () => ({
|
||||
RecordAnamnesisSection: () => <div data-slot="record-anamnesis" />,
|
||||
}));
|
||||
|
||||
import { RecordSettingsSectionGate } from "../record-settings-section-gate";
|
||||
|
||||
function render(section: "modules" | "integrations") {
|
||||
function render(section: "modules" | "integrations" | "anamnesis" | "labs") {
|
||||
return renderToStaticMarkup(
|
||||
<I18nProvider initialLocale="en">
|
||||
<RecordSettingsSectionGate section={section}>
|
||||
@@ -77,4 +80,83 @@ describe("RecordSettingsSectionGate", () => {
|
||||
expect(html).toContain("managed-settings");
|
||||
expect(html).not.toContain("actor-settings");
|
||||
});
|
||||
|
||||
/**
|
||||
* The record-content destination, and the two ways it must not open.
|
||||
*
|
||||
* The branch keys on the SLUG as well as on the classification. Keying on
|
||||
* the kind alone would render the allergy and family-history managers under
|
||||
* the heading of any future `manage-writable` destination — silently,
|
||||
* because a category matched where a page was meant.
|
||||
*/
|
||||
describe("the anamnesis destination", () => {
|
||||
it("opens for an adult manager on an ordinary shared record", () => {
|
||||
authRef.isLoading = false;
|
||||
authRef.active = {
|
||||
accountId: "shared-record",
|
||||
recordKind: "shared",
|
||||
level: "manage",
|
||||
sections: null,
|
||||
canWrite: true,
|
||||
};
|
||||
|
||||
const html = render("anamnesis");
|
||||
|
||||
expect(html).toContain("record-anamnesis");
|
||||
expect(html).not.toContain("actor-settings");
|
||||
expect(html).not.toContain("managed-settings");
|
||||
});
|
||||
|
||||
it("opens for a Guardian, rather than the guardian configuration panel", () => {
|
||||
authRef.isLoading = false;
|
||||
authRef.active = {
|
||||
accountId: "managed-record",
|
||||
recordKind: "managed",
|
||||
level: "manage",
|
||||
sections: null,
|
||||
canWrite: true,
|
||||
};
|
||||
|
||||
const html = render("anamnesis");
|
||||
|
||||
expect(html).toContain("record-anamnesis");
|
||||
expect(html).not.toContain("managed-settings");
|
||||
});
|
||||
|
||||
it("stays shut below MANAGE", () => {
|
||||
authRef.isLoading = false;
|
||||
authRef.active = {
|
||||
accountId: "shared-record",
|
||||
recordKind: "shared",
|
||||
level: "write",
|
||||
sections: null,
|
||||
canWrite: true,
|
||||
};
|
||||
|
||||
const html = render("anamnesis");
|
||||
|
||||
expect(html).not.toContain("record-anamnesis");
|
||||
expect(html).toContain("shared-record-settings-unavailable-title");
|
||||
});
|
||||
|
||||
it("does not lend its page to another destination of the same kind", () => {
|
||||
// `labs` is `adult-shared-unavailable` today, so this passes for the
|
||||
// right reason now; the claim it pins is that the branch asks WHICH
|
||||
// page, not which category. A second `manage-writable` slug added
|
||||
// without an arm falls through to the refusal panel.
|
||||
authRef.isLoading = false;
|
||||
authRef.active = {
|
||||
accountId: "shared-record",
|
||||
recordKind: "shared",
|
||||
level: "manage",
|
||||
sections: null,
|
||||
canWrite: true,
|
||||
};
|
||||
|
||||
const html = render("labs");
|
||||
|
||||
expect(html).not.toContain("record-anamnesis");
|
||||
expect(html).toContain("shared-record-settings-unavailable-title");
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user