Files
HealthLog/src/components/settings/__tests__/privacy-section.test.tsx
T
Marc-André Bombeck f564cdeef7 revert(settings): restore the flat settings navigation
Revert the nine-group consolidation and the card relocations back to the
flat sidebar: sessions, trusted devices, and login activity return to
Privacy, and account deletion returns inline under Advanced. Drop the
/settings/layout redirect and the now-unused group and sign-in cross-link
i18n keys across all six locales.

Keep the collapse-by-default sessions and activity cards, the medical-history
cross-link from "About me", and the chronic-conditions consolidation.
2026-06-29 07:12:10 +02:00

97 lines
3.8 KiB
TypeScript

import { describe, it, expect, vi } from "vitest";
import { renderToStaticMarkup } from "react-dom/server";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
vi.mock("@/hooks/use-auth", () => ({
useAuth: () => ({ isAuthenticated: true, isLoading: false }),
}));
import { I18nProvider } from "@/lib/i18n/context";
import { queryKeys } from "@/lib/query-keys";
import { PrivacySection } from "../privacy-section";
function render(node: React.ReactNode, locale: "en" | "de" = "en") {
const client = new QueryClient({
defaultOptions: {
queries: {
retry: false,
staleTime: Number.POSITIVE_INFINITY,
refetchOnMount: false,
},
},
});
// Seed the privacy summary so the encryption + retention blocks paint inline.
client.setQueryData(queryKeys.privacySummary(), {
retention: {
coachMessagesDays: 365,
auditLogDays: 365,
deliveryLogDays: 90,
},
encryption: { algorithm: "AES-256-GCM", columnCount: 74, modelCount: 21 },
});
// Seed the embedded session + trusted-device + activity reads so the
// assembled cards paint without firing network.
client.setQueryData(queryKeys.sessions(), { sessions: [] });
client.setQueryData(queryKeys.securityActivity(), { events: [] });
// Seed a trusted device so the card paints (it hides itself when empty).
client.setQueryData(queryKeys.trustedDevices(), {
devices: [
{
id: "td-1",
label: "Firefox on macOS",
isCurrent: true,
expiresAt: "2099-01-01T00:00:00.000Z",
},
],
});
return renderToStaticMarkup(
<I18nProvider initialLocale={locale}>
<QueryClientProvider client={client}>{node}</QueryClientProvider>
</I18nProvider>,
);
}
describe("<PrivacySection> — assembled Data & Privacy dashboard", () => {
it("renders the assembled sections (encryption, retention, export, delete, sessions, activity)", () => {
const html = render(<PrivacySection />);
// Encryption-at-rest block driven from the seeded summary.
expect(html).toContain("AES-256-GCM");
// Retention numbers surfaced from the summary.
expect(html).toContain("365");
// The honest backup↔deletion lag disclosure is present.
expect(html.toLowerCase()).toContain("backup");
// Links to the existing export + destructive surfaces (assembly, not rebuild).
expect(html).toContain('href="/settings/export"');
expect(html).toContain('href="/settings/gesundheitsakte"');
expect(html).toContain('href="/settings/advanced"');
// Embedded active-session + security-activity cards.
expect(html).toContain("settings-security-sessions-card");
// Trusted devices now lives here (and only here) — its single home is the
// Privacy dashboard, not the Security section.
expect(html).toContain("settings-trusted-devices-card");
});
it("shows a loading placeholder for the retention block before the summary resolves", () => {
// Render WITHOUT seeding the privacy summary: the query is pending, so the
// retention block must paint a skeleton rather than an empty list.
const client = new QueryClient({
defaultOptions: {
queries: { retry: false, refetchOnMount: false },
},
});
client.setQueryData(queryKeys.sessions(), { sessions: [] });
client.setQueryData(queryKeys.securityActivity(), { events: [] });
client.setQueryData(queryKeys.trustedDevices(), { devices: [] });
const html = renderToStaticMarkup(
<I18nProvider initialLocale="en">
<QueryClientProvider client={client}>
<PrivacySection />
</QueryClientProvider>
</I18nProvider>,
);
// Skeleton rows render while the summary is loading; no retention day-count.
expect(html).toContain('data-slot="skeleton"');
expect(html).not.toContain("365");
});
});