mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
- Return effective threshold ranges after managed updates\n- Localize closed Coach and Insights display inventories
95 lines
3.7 KiB
TypeScript
95 lines
3.7 KiB
TypeScript
import { readFile } from "node:fs/promises";
|
|
import { resolve } from "node:path";
|
|
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import { resolveGuardianRecordSettingsAccess } from "@/lib/record-settings/access";
|
|
import {
|
|
classifySettingsDestination,
|
|
SETTINGS_DESTINATION_INVENTORY,
|
|
} from "@/lib/record-settings/classification";
|
|
import { MANAGED_RECORD_SETTINGS_FIELD_ALLOWLIST } from "@/lib/record-settings";
|
|
|
|
const fromRoot = (...segments: string[]) => resolve(process.cwd(), ...segments);
|
|
|
|
describe("record settings authorization", () => {
|
|
it("keeps actor and record separation", async () => {
|
|
const [authMeRoute, recordSettingsRoute] = await Promise.all([
|
|
readFile(fromRoot("src/app/api/auth/me/route.ts"), "utf8"),
|
|
readFile(fromRoot("src/app/api/record-settings/route.ts"), "utf8"),
|
|
]);
|
|
|
|
const access = resolveGuardianRecordSettingsAccess({
|
|
actor: { id: "guardian-1" },
|
|
grantId: "grant-1",
|
|
user: { id: "managed-record-1", managedProfileAt: new Date() },
|
|
});
|
|
|
|
expect(access).toMatchObject({
|
|
actorId: "guardian-1",
|
|
recordId: "managed-record-1",
|
|
recordKind: "managed",
|
|
relationship: "guardian",
|
|
});
|
|
expect(authMeRoute).toContain("requireAuth");
|
|
expect(authMeRoute).not.toContain("requireGuardianAuth");
|
|
expect(authMeRoute).not.toContain("requireRecordAuth");
|
|
expect(recordSettingsRoute).toContain("requireGuardianAuth");
|
|
expect(recordSettingsRoute).toContain("toRecordSettingsDto");
|
|
});
|
|
|
|
it("keeps settings classification exhaustive and fail closed", () => {
|
|
expect(Object.keys(SETTINGS_DESTINATION_INVENTORY)).not.toHaveLength(0);
|
|
expect(classifySettingsDestination("integrations")).toMatchObject({
|
|
kind: "managed-guardian",
|
|
guardianWritable: false,
|
|
});
|
|
expect(classifySettingsDestination("ai").kind).toBe("unavailable");
|
|
expect(classifySettingsDestination("unknown-settings-path").kind).toBe(
|
|
"unavailable",
|
|
);
|
|
});
|
|
|
|
it("uses one guardian-only record resolver for every writable DTO family", async () => {
|
|
const route = await readFile(
|
|
fromRoot("src/app/api/record-settings/[family]/route.ts"),
|
|
"utf8",
|
|
);
|
|
const guardian = resolveGuardianRecordSettingsAccess({
|
|
actor: { id: "guardian-1" },
|
|
grantId: "grant-1",
|
|
user: { id: "managed-record-1", managedProfileAt: new Date() },
|
|
});
|
|
const adultManager = resolveGuardianRecordSettingsAccess({
|
|
actor: { id: "adult-manager" },
|
|
grantId: "grant-1",
|
|
user: { id: "adult-record-1", managedProfileAt: null },
|
|
});
|
|
|
|
expect(guardian?.recordId).toBe("managed-record-1");
|
|
expect(adultManager).toBeNull();
|
|
expect(route).toContain("requireGuardianAuth");
|
|
expect(route).toContain("resolveGuardianRecordSettingsAccess");
|
|
for (const family of Object.keys(MANAGED_RECORD_SETTINGS_FIELD_ALLOWLIST)) {
|
|
expect(route).toContain(`case \"${family}\"`);
|
|
}
|
|
expect(route).toContain("record-settings.${family}.update");
|
|
expect(route).toContain("userId: access.recordId");
|
|
expect(route).toContain("actorUserId: access.actorId");
|
|
expect(route).toContain("details: { changed }");
|
|
expect(route).not.toContain("details: { recordId:");
|
|
expect(route).toContain("invalidateUserMedications(access.recordId, {");
|
|
expect(route).toContain("invalidateUserHealthScore(access.recordId)");
|
|
expect(route).toContain("getAllEffectiveRanges(record, overrides)");
|
|
expect(route).toContain(
|
|
"effective: getAllEffectiveRanges(record, overrides)",
|
|
);
|
|
expect(route).toContain("invalidateUserProfile(access.recordId)");
|
|
expect(
|
|
route.lastIndexOf("invalidateUserProfile(access.recordId)"),
|
|
).toBeGreaterThan(
|
|
route.indexOf("data: { thresholdsJson: toJson(overrides) }"),
|
|
);
|
|
});
|
|
});
|