fix: complete managed record settings

- Expose canonical defaults and reject invalid settings families\n- Localize Guardian controls and refresh dependent caches
This commit is contained in:
Marc-André Bombeck committed 2026-08-06 03:40:13 +02:00
1 parent e788675b82
commit 247ac8494c
16 files changed
+759 -91

No files matched your search

@@ -1,9 +1,13 @@
import { describe, expect, it } from "vitest";
import {
isManagedRecordSettingsFamily,
MANAGED_RECORD_SETTINGS_FIELD_ALLOWLIST,
MANAGED_RECORD_SETTINGS_MODULE_DEFAULTS,
managedModulePreferencesFrom,
parseManagedRecordSettingsPatch,
} from "@/lib/record-settings/configuration";
import { WRITABLE_MODULE_KEYS } from "@/lib/validations/modules";
describe("managed record settings configuration contract", () => {
it("enumerates the only target-record fields each settings DTO may write", () => {
@@ -95,4 +99,29 @@ describe("managed record settings configuration contract", () => {
] as const)("accepts a typed %s patch", (family, patch) => {
expect(() => parseManagedRecordSettingsPatch(family, patch)).not.toThrow();
});
it("uses the complete canonical module inventory for a fresh record", () => {
expect(Object.keys(MANAGED_RECORD_SETTINGS_MODULE_DEFAULTS)).toEqual(
WRITABLE_MODULE_KEYS,
);
expect(managedModulePreferencesFrom(null)).toEqual(
MANAGED_RECORD_SETTINGS_MODULE_DEFAULTS,
);
});
it("accepts only the canonical profile gender enum", () => {
expect(() =>
parseManagedRecordSettingsPatch("profile", { gender: "MALE" }),
).not.toThrow();
expect(() =>
parseManagedRecordSettingsPatch("profile", { gender: "UNKNOWN" }),
).toThrow();
});
it.each(["toString", "constructor", "__proto__", "hasOwnProperty"])(
"rejects inherited family name %s",
(family) => {
expect(isManagedRecordSettingsFamily(family)).toBe(false);
},
);
});
@@ -57,5 +57,10 @@ describe("record settings route guard", () => {
for (const family of families) {
expect(source).toContain(`case \"${family}\"`);
}
expect(source).toContain("if (!isManagedRecordSettingsFamily(rawFamily))");
expect(source).toContain('apiError("Settings family not found", 404)');
expect(
source.indexOf("isManagedRecordSettingsFamily(rawFamily)"),
).toBeLessThan(source.indexOf("const context = await requireGuardianAuth"));
});
});
+45 -3
View File
@@ -5,6 +5,27 @@ import { describe, expect, it } from "vitest";
const fromRoot = (...segments: string[]) => resolve(process.cwd(), ...segments);
function expectMatchingMessageKeys(expected: unknown, actual: unknown): void {
if (
expected === null ||
typeof expected !== "object" ||
actual === null ||
typeof actual !== "object"
) {
expect(typeof actual).toBe(typeof expected);
return;
}
const expectedRecord = expected as Record<string, unknown>;
const actualRecord = actual as Record<string, unknown>;
expect(Object.keys(actualRecord).sort()).toEqual(
Object.keys(expectedRecord).sort(),
);
for (const key of Object.keys(expectedRecord)) {
expectMatchingMessageKeys(expectedRecord[key], actualRecord[key]);
}
}
describe("managed record settings UI", () => {
it("gates shared deep links and renders integration status without controls", async () => {
const [
@@ -54,10 +75,31 @@ describe("managed record settings UI", () => {
expect(managedSettingsView).not.toContain("/api/auth/");
expect(managedSettingsView).not.toContain("/api/user/");
expect(managedSettingsView).not.toContain("<textarea");
expect(managedSettingsView).not.toContain("Display name");
expect(managedSettingsView).not.toContain("Enable mood reminder");
const referenceMessages = JSON.parse(localeBundles[0]).settings.sharedRecord
.managedSettings;
for (const bundle of localeBundles) {
expect(bundle).toContain('"sharedRecord"');
expect(bundle).toContain('"unavailableTitle"');
expect(bundle).toContain('"integrationStatusDescription"');
const sharedRecord = JSON.parse(bundle).settings.sharedRecord;
expect(sharedRecord).toMatchObject({
unavailableTitle: expect.any(String),
integrationStatusDescription: expect.any(String),
managedSettings: {
profile: {
title: expect.any(String),
displayName: expect.any(String),
},
modules: { title: expect.any(String) },
notifications: { title: expect.any(String) },
thresholds: { title: expect.any(String) },
coach: { title: expect.any(String) },
insights: { title: expect.any(String) },
},
});
expectMatchingMessageKeys(
referenceMessages,
sharedRecord.managedSettings,
);
}
});
});