mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 06:40:50 +00:00
feat: show managed integration status
- Render a record-keyed status view for managed profiles\n- Refuse shared Settings links before actor controls mount\n- Localize intentional unavailable states
This commit is contained in:
1 parent
54cd3e3959
commit
03ee01ba56
17 files changed
+343
-32
No files matched your search
@@ -10,6 +10,7 @@ import {
|
||||
SETTINGS_DESTINATION_INVENTORY,
|
||||
} from "@/lib/record-settings/classification";
|
||||
import { toRecordSettingsDto } from "@/lib/record-settings/dto";
|
||||
import { resolveManagedIntegrationState } from "@/lib/record-settings/integrations";
|
||||
import { recordSettingsKeys } from "@/lib/query-keys";
|
||||
|
||||
describe("record settings contract", () => {
|
||||
@@ -36,6 +37,11 @@ describe("record settings contract", () => {
|
||||
"record-1",
|
||||
"detail",
|
||||
]);
|
||||
expect(recordSettingsKeys.recordSettingsIntegrations("record-1")).toEqual([
|
||||
"record-settings",
|
||||
"record-1",
|
||||
"integrations",
|
||||
]);
|
||||
});
|
||||
|
||||
it("does not let an adult MANAGE grant use Guardian-only configuration", () => {
|
||||
@@ -66,4 +72,28 @@ describe("record settings contract", () => {
|
||||
expect(isGuardianSettingsWriteAllowed("integrations")).toBe(false);
|
||||
expect(isGuardianSettingsWriteAllowed("ai")).toBe(false);
|
||||
});
|
||||
|
||||
it("does not report a synthetic ledger row as a managed connection", () => {
|
||||
const connected = {
|
||||
withings: false,
|
||||
whoop: false,
|
||||
fitbit: false,
|
||||
nightscout: false,
|
||||
polar: false,
|
||||
oura: false,
|
||||
"google-health": false,
|
||||
strava: false,
|
||||
} as const;
|
||||
|
||||
expect(
|
||||
resolveManagedIntegrationState("connected", connected, "withings"),
|
||||
).toBe("disconnected");
|
||||
expect(
|
||||
resolveManagedIntegrationState(
|
||||
"error_reauth",
|
||||
{ ...connected, oura: true },
|
||||
"oura",
|
||||
),
|
||||
).toBe("error_reauth");
|
||||
});
|
||||
});
|
||||
@@ -6,19 +6,34 @@ import { describe, expect, it } from "vitest";
|
||||
const fromRoot = (...segments: string[]) => resolve(process.cwd(), ...segments);
|
||||
|
||||
describe("managed record settings UI", () => {
|
||||
it("renders integration status without connection controls", async () => {
|
||||
const [statusView, settingsPage] = await Promise.all([
|
||||
readFile(
|
||||
fromRoot("src/components/settings/managed-integration-status.tsx"),
|
||||
"utf8",
|
||||
),
|
||||
readFile(fromRoot("src/app/settings/[section]/page.tsx"), "utf8"),
|
||||
]);
|
||||
it("gates shared deep links and renders integration status without controls", async () => {
|
||||
const [statusView, settingsPage, sectionGate, ...localeBundles] =
|
||||
await Promise.all([
|
||||
readFile(
|
||||
fromRoot("src/components/settings/managed-integration-status.tsx"),
|
||||
"utf8",
|
||||
),
|
||||
readFile(fromRoot("src/app/settings/[section]/page.tsx"), "utf8"),
|
||||
readFile(
|
||||
fromRoot("src/components/settings/record-settings-section-gate.tsx"),
|
||||
"utf8",
|
||||
),
|
||||
...["de", "en", "es", "fr", "it", "pl"].map((locale) =>
|
||||
readFile(fromRoot(`messages/${locale}.json`), "utf8"),
|
||||
),
|
||||
]);
|
||||
|
||||
expect(statusView).toContain("recordSettingsIntegrations");
|
||||
expect(statusView).toContain("/api/record-settings/integrations");
|
||||
expect(statusView).not.toContain("<Button");
|
||||
expect(statusView).not.toContain("<Link");
|
||||
expect(settingsPage).toContain("RecordSettingsSectionGate");
|
||||
expect(sectionGate).toContain("if (!inSharedRecord) return children");
|
||||
expect(sectionGate).toContain("ManagedIntegrationStatus");
|
||||
for (const bundle of localeBundles) {
|
||||
expect(bundle).toContain('"sharedRecord"');
|
||||
expect(bundle).toContain('"unavailableTitle"');
|
||||
expect(bundle).toContain('"integrationStatusDescription"');
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user