mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 13:22:14 +00:00
Settings now reads as nine groups: Account, Tracking, Arrangement, Notifications, Health profile, AI, Connections, Data and System. On a phone one button names the current section and opens the grouped list, replacing the strip of every section. What moved, every old address still working: - Sessions, trusted devices and security activity sit under Security; the privacy page anchors forward there. - Notifications holds every reminder kind: the Coach nudges and the checkup reminder switches joined, and a card names the reminders set where their subject lives (dose times, cycle reminders). - Arrangement holds order and view only. Mood tags, the labs biomarker catalog and on-device text recognition, and the injection sites live on module pages under /settings/modules/<id>, linked from each Modules row and from the module's own wrench. /settings/layout/mood redirects. - The timezone saves on change in the Display card, with a one-tap offer of the device zone. - Screening hints sit beside the life circumstances they come from. - System gains Preview features with the Topics switch. Duplicates: the Coach and MCP pages show their state and link to the one switch in Modules (turning MCP off keeps tokens), the Coach overlay shows the provider and model with a link to Settings > AI instead of a second set of selects, and the privacy page drops its copy of the export links. A guard walks every historical /settings address through the redirects and every forwarded anchor to a page that renders.
88 lines
3.4 KiB
TypeScript
88 lines
3.4 KiB
TypeScript
/**
|
|
* v1.25.11 (#148) — the shared Appearance group registry.
|
|
*
|
|
* `layout-groups` is the single source of truth consumed by BOTH the client
|
|
* hub (`layout-section.tsx`) and the server subpage route
|
|
* (`app/settings/layout/[module]/page.tsx`, via `LAYOUT_GROUP_IDS` in
|
|
* `generateStaticParams()`). These tests pin the param → section mapping: the
|
|
* id list (the statically-generated subpage params), the guard, the per-module
|
|
* gate expectations, and that each group resolves a distinct section body.
|
|
*/
|
|
import { describe, expect, it, vi } from "vitest";
|
|
|
|
// Stub the section components at the import boundary — each has its own test;
|
|
// here we only assert the registry's metadata + identity mapping, and we keep
|
|
// the heavy section trees out of the unit import graph.
|
|
vi.mock("../dashboard-section", () => ({ DashboardSection: () => null }));
|
|
vi.mock("../insights-section", () => ({ InsightsSection: () => null }));
|
|
vi.mock("../medications-section", () => ({ MedicationsSection: () => null }));
|
|
vi.mock("../labs-section", () => ({ LabsSection: () => null }));
|
|
vi.mock("../illness-section", () => ({ IllnessSection: () => null }));
|
|
vi.mock("../vorsorge-section", () => ({ VorsorgeSection: () => null }));
|
|
|
|
import {
|
|
LAYOUT_GROUPS,
|
|
LAYOUT_GROUP_IDS,
|
|
isLayoutGroupId,
|
|
layoutGroupModule,
|
|
} from "../layout-groups";
|
|
|
|
describe("layout-groups registry", () => {
|
|
it("exposes the seven Arrangement modules as statically-generated subpage params", () => {
|
|
// v1.44 — mood left: its page was tag management, which lives under
|
|
// Settings > Modules > Mood now (`/settings/layout/mood` redirects).
|
|
expect(LAYOUT_GROUP_IDS).toEqual([
|
|
"dashboard",
|
|
"insights",
|
|
"medications",
|
|
"labs",
|
|
"illness",
|
|
"documents",
|
|
"vorsorge",
|
|
]);
|
|
// generateStaticParams() shape.
|
|
expect(LAYOUT_GROUP_IDS.map((module) => ({ module }))).toEqual([
|
|
{ module: "dashboard" },
|
|
{ module: "insights" },
|
|
{ module: "medications" },
|
|
{ module: "labs" },
|
|
{ module: "illness" },
|
|
{ module: "documents" },
|
|
{ module: "vorsorge" },
|
|
]);
|
|
});
|
|
|
|
it("guards unknown segments", () => {
|
|
expect(isLayoutGroupId("medications")).toBe(true);
|
|
expect(isLayoutGroupId("vorsorge")).toBe(true);
|
|
expect(isLayoutGroupId("nope")).toBe(false);
|
|
expect(isLayoutGroupId("")).toBe(false);
|
|
});
|
|
|
|
it("gates the toggleable tracking modules and leaves the rest always-on", () => {
|
|
const gate = (id: string) =>
|
|
LAYOUT_GROUPS.some((group) => group.id === id)
|
|
? layoutGroupModule(id)
|
|
: "not-a-group";
|
|
expect(gate("medications")).toBe("medications");
|
|
expect(gate("mood")).toBe("not-a-group");
|
|
expect(gate("labs")).toBe("labs");
|
|
expect(gate("illness")).toBe("illness");
|
|
// dashboard / insights / vorsorge are never gated.
|
|
expect(gate("dashboard")).toBeUndefined();
|
|
expect(gate("insights")).toBeUndefined();
|
|
expect(gate("vorsorge")).toBeUndefined();
|
|
});
|
|
|
|
it("maps every id to a distinct section body and the canonical i18n keys", () => {
|
|
const bodies = new Set(LAYOUT_GROUPS.map((group) => group.Body));
|
|
expect(bodies.size).toBe(LAYOUT_GROUPS.length);
|
|
for (const group of LAYOUT_GROUPS) {
|
|
expect(group.titleKey).toBe(`settings.sections.layout.${group.id}.title`);
|
|
expect(group.descriptionKey).toBe(
|
|
`settings.sections.layout.${group.id}.description`,
|
|
);
|
|
}
|
|
});
|
|
});
|