mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
refactor(admin): split the backups section
The section becomes a composer over backups/: the restore dialog with its preview, the refusal, skip and schedule notices, the restore jobs and their request, the upload flow, the run and download actions, and the two row layouts sharing one action pair. The upload total is a pure function and tested as one. The read-failure guard's 250-character window had stopped reaching the restore preview's own failure lines; the preview now sits in a smaller component, the guard sees it, and it is listed as a deliberate exception with its reason.
This commit is contained in:
1 parent
c9917d2de0
commit
5eafed8dd5
19 files changed
+1533
-1348
No files matched your search
@@ -84,13 +84,16 @@ vi.mock("@/hooks/use-auth", () => ({
|
||||
}));
|
||||
|
||||
import { I18nProvider } from "@/lib/i18n/context";
|
||||
import { BackupsSection, restorePreviewFailure } from "../backups-section";
|
||||
import {
|
||||
RestorePreview,
|
||||
restorePreviewFailure,
|
||||
} from "../backups/restore-dialog";
|
||||
|
||||
describe("restore preview query", () => {
|
||||
it("is never retried and waits a bounded time", async () => {
|
||||
renderToStaticMarkup(
|
||||
<I18nProvider initialLocale="en">
|
||||
<BackupsSection />
|
||||
<RestorePreview backupId="b1" open />
|
||||
</I18nProvider>,
|
||||
);
|
||||
const key = JSON.stringify(queryKeys.adminBackupSummary("b1"));
|
||||
|
||||
@@ -29,7 +29,7 @@ import { I18nProvider } from "@/lib/i18n/context";
|
||||
import {
|
||||
RestoreRefusalNotice,
|
||||
missingSectionsOf,
|
||||
} from "@/components/admin/backups-section";
|
||||
} from "@/components/admin/backups/restore-notices";
|
||||
import type { MissingBackupSection } from "@/lib/export/restore-skips";
|
||||
import { primeLocales } from "@/__tests__/helpers/prime-locales";
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import { describe, expect, it, vi } from "vitest";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
|
||||
import { I18nProvider } from "@/lib/i18n/context";
|
||||
import { RestoreSkipReport } from "@/components/admin/backups-section";
|
||||
import { RestoreSkipReport } from "@/components/admin/backups/restore-notices";
|
||||
import type { RestoreSkipSummary } from "@/lib/export/restore-skips";
|
||||
import { primeLocales } from "@/__tests__/helpers/prime-locales";
|
||||
|
||||
|
||||
@@ -17,10 +17,6 @@ const healthySchedule = {
|
||||
};
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
mutationOptions: [] as Array<{
|
||||
onSuccess?: (data: { summary: Record<string, number> }) => void;
|
||||
}>,
|
||||
toastSuccess: vi.fn(),
|
||||
// Mutable so one file can render both a healthy schedule and a broken one;
|
||||
// the query mock reads it on every render.
|
||||
queryData: { rows: [], retentionDays: 30 } as Record<string, unknown>,
|
||||
@@ -43,7 +39,7 @@ vi.mock("next/navigation", () => ({
|
||||
|
||||
vi.mock("sonner", () => ({
|
||||
toast: {
|
||||
success: mocks.toastSuccess,
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
},
|
||||
}));
|
||||
@@ -55,21 +51,14 @@ vi.mock("@tanstack/react-query", () => ({
|
||||
isError: false,
|
||||
}),
|
||||
useQueryClient: () => ({ invalidateQueries: vi.fn() }),
|
||||
useMutation: (options: unknown) => {
|
||||
mocks.mutationOptions.push(
|
||||
options as {
|
||||
onSuccess?: (data: { summary: Record<string, number> }) => void;
|
||||
},
|
||||
);
|
||||
return {
|
||||
mutate: vi.fn(),
|
||||
mutateAsync: vi.fn(),
|
||||
isPending: false,
|
||||
isError: false,
|
||||
error: null,
|
||||
variables: undefined,
|
||||
};
|
||||
},
|
||||
useMutation: () => ({
|
||||
mutate: vi.fn(),
|
||||
mutateAsync: vi.fn(),
|
||||
isPending: false,
|
||||
isError: false,
|
||||
error: null,
|
||||
variables: undefined,
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock("@/hooks/use-auth", () => ({
|
||||
@@ -83,6 +72,7 @@ vi.mock("@/hooks/use-auth", () => ({
|
||||
|
||||
import { I18nProvider } from "@/lib/i18n/context";
|
||||
import { BackupsSection } from "../backups-section";
|
||||
import { uploadedRecordCount } from "../backups/use-backup-upload";
|
||||
import { primeLocales } from "@/__tests__/helpers/prime-locales";
|
||||
|
||||
primeLocales("de");
|
||||
@@ -224,26 +214,16 @@ describe("BackupsSection — schedule health", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("BackupsSection — upload outcome", () => {
|
||||
describe("backup upload outcome", () => {
|
||||
it("includes health profile fact revisions in the restored record total", () => {
|
||||
mocks.toastSuccess.mockClear();
|
||||
const firstMutation = mocks.mutationOptions.length;
|
||||
render();
|
||||
const uploadOutcome = mocks.mutationOptions[firstMutation + 1]?.onSuccess;
|
||||
expect(uploadOutcome).toBeTypeOf("function");
|
||||
|
||||
uploadOutcome!({
|
||||
summary: {
|
||||
expect(
|
||||
uploadedRecordCount({
|
||||
measurements: 1,
|
||||
medications: 2,
|
||||
intakeEvents: 3,
|
||||
moodEntries: 4,
|
||||
healthProfileFactRevisions: 5,
|
||||
},
|
||||
});
|
||||
|
||||
expect(mocks.toastSuccess).toHaveBeenCalledWith(
|
||||
expect.stringContaining("15"),
|
||||
);
|
||||
}),
|
||||
).toBe(15);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user