diff --git a/src/components/admin/__tests__/backups-section-empty.test.tsx b/src/components/admin/__tests__/backups-section-empty.test.tsx new file mode 100644 index 000000000..0d34070b3 --- /dev/null +++ b/src/components/admin/__tests__/backups-section-empty.test.tsx @@ -0,0 +1,81 @@ +import { describe, expect, it, vi } from "vitest"; +import { renderToStaticMarkup } from "react-dom/server"; + +/** + * v1.4.15 phase-C5 — `/admin/backups` empty state. + * + * The previous build rendered a single-line `
No backups recorded + * yet.
` inside the card. Brand-new admins didn't realise the "Run + * backup now" CTA in the header was the way to create one, so the page + * felt inert. The new EmptyState primitive duplicates the header CTA + * inside the card so the action is right next to the explanation. + */ + +vi.mock("next/navigation", () => ({ + useRouter: () => ({ push: vi.fn(), replace: vi.fn() }), + usePathname: () => "/admin/backups", +})); + +vi.mock("@tanstack/react-query", () => ({ + useQuery: () => ({ + data: { rows: [], retentionDays: 30 }, + isLoading: false, + isError: false, + }), + useQueryClient: () => ({ invalidateQueries: vi.fn() }), + useMutation: () => ({ + mutate: vi.fn(), + mutateAsync: vi.fn(), + isPending: false, + isError: false, + error: null, + variables: undefined, + }), +})); + +vi.mock("@/hooks/use-auth", () => ({ + useAuth: () => ({ + user: { id: "u1", username: "marc", role: "ADMIN" }, + isAuthenticated: true, + isLoading: false, + refetch: vi.fn(), + }), +})); + +import { I18nProvider } from "@/lib/i18n/context"; +import { BackupsSection } from "../backups-section"; + +function render() { + return renderToStaticMarkup( +- {t("admin.noTokens")} -
+ // v1.4.15 phase-C5: empty state explains where tokens come + // from (native client sign-in / Settings → Account) so a + // fresh admin doesn't think they need to create them here. +- {t("admin.feedback.noEntries")} -
+ // v1.4.15 phase-C5: per-tab empty state. Compact size so + // it sits naturally under the tab strip without dwarfing + // a typical 1-2-row inbox once entries arrive. +