diff --git a/src/components/Componentes/auth-data-boundary.test.tsx b/src/components/Componentes/auth-data-boundary.test.tsx new file mode 100644 index 0000000..fda280f --- /dev/null +++ b/src/components/Componentes/auth-data-boundary.test.tsx @@ -0,0 +1,77 @@ +import { render, waitFor } from "@testing-library/react"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { describe, expect, it, vi, beforeEach } from "vitest"; +import AuthDataBoundary from "./auth-data-boundary"; +import { marriageQueryKeys } from "@/hooks/marriage/query-keys"; +import { HABIB_AUTH_TOKEN_CHANGED_EVENT } from "@/lib/auth-bridge"; + +describe("AuthDataBoundary", () => { + let queryClient: QueryClient; + + beforeEach(() => { + window.localStorage.clear(); + queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: false }, + }, + }); + }); + + it("purges user-specific caches on habib:auth-token-changed while preserving config", async () => { + // Populate query cache with user data + config + queryClient.setQueryData(marriageQueryKeys.profile(), { id: 100, can_edit_profile: true }); + queryClient.setQueryData(marriageQueryKeys.formOverview("profile", "en"), { form_id: "profile", sections: [] }); + queryClient.setQueryData(marriageQueryKeys.formSection("profile", "job", "en"), { form_id: "profile", section: { id: "job" } }); + queryClient.setQueryData(marriageQueryKeys.cattellQuestions("en"), { questions: [] }); + queryClient.setQueryData(marriageQueryKeys.glasserQuestions("en"), { questions: [] }); + queryClient.setQueryData(marriageQueryKeys.config(), { min_age: 18 }); + + render( + + +
Child Content
+
+
, + ); + + // Verify initial cached data is present + expect(queryClient.getQueryData(marriageQueryKeys.profile())).toBeDefined(); + expect(queryClient.getQueryData(marriageQueryKeys.formOverview("profile", "en"))).toBeDefined(); + expect(queryClient.getQueryData(marriageQueryKeys.formSection("profile", "job", "en"))).toBeDefined(); + expect(queryClient.getQueryData(marriageQueryKeys.cattellQuestions("en"))).toBeDefined(); + expect(queryClient.getQueryData(marriageQueryKeys.config())).toBeDefined(); + + // Fire auth identity change (e.g. Account A logs out or switches to Account B) + window.dispatchEvent(new CustomEvent(HABIB_AUTH_TOKEN_CHANGED_EVENT, { detail: { token: "new-token" } })); + + // All user-owned queries should be removed from the cache + await waitFor(() => { + expect(queryClient.getQueryData(marriageQueryKeys.profile())).toBeUndefined(); + }); + expect(queryClient.getQueryData(marriageQueryKeys.formOverview("profile", "en"))).toBeUndefined(); + expect(queryClient.getQueryData(marriageQueryKeys.formSection("profile", "job", "en"))).toBeUndefined(); + expect(queryClient.getQueryData(marriageQueryKeys.cattellQuestions("en"))).toBeUndefined(); + expect(queryClient.getQueryData(marriageQueryKeys.glasserQuestions("en"))).toBeUndefined(); + + // Config query MUST be preserved (public/global) + expect(queryClient.getQueryData(marriageQueryKeys.config())).toEqual({ min_age: 18 }); + }); + + it("runs legacy V3 migration once on mount", async () => { + window.localStorage.setItem("marriage:sections:old_slug:answers:v2", JSON.stringify({ pending_sync: true })); + expect(window.localStorage.getItem("marriage:storage-migration:v3")).toBeNull(); + + render( + + +
Mounted
+
+
, + ); + + await waitFor(() => { + expect(window.localStorage.getItem("marriage:storage-migration:v3")).toBe("done"); + }); + expect(window.localStorage.getItem("marriage:sections:old_slug:answers:v2")).toBeNull(); + }); +}); diff --git a/src/components/Componentes/test-questions-flow.tsx b/src/components/Componentes/test-questions-flow.tsx index d7e674a..9cbd01d 100644 --- a/src/components/Componentes/test-questions-flow.tsx +++ b/src/components/Componentes/test-questions-flow.tsx @@ -44,7 +44,7 @@ type StoredTestDraft = { }; function getStoredDraft( - storageKey: string | undefined, + storageKey: string | null | undefined, totalQuestions: number, ) { if (!storageKey || typeof window === "undefined")