diff --git a/src/app/(app)/settings/__tests__/page.test.tsx b/src/app/(app)/settings/__tests__/page.test.tsx new file mode 100644 index 0000000..ae0f035 --- /dev/null +++ b/src/app/(app)/settings/__tests__/page.test.tsx @@ -0,0 +1,59 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import { render, screen, cleanup, waitFor } from "@testing-library/react"; +import SettingsPage from "../page"; + +vi.mock("next/navigation", () => ({ useRouter: () => ({ refresh: vi.fn() }) })); +vi.mock("sonner", () => ({ toast: { success: vi.fn(), error: vi.fn() } })); +vi.mock("@/components/providers/theme-provider", () => ({ + useTheme: () => ({ + preferences: { + accentTheme: "amber", + fontStyle: "sans", + layoutDensity: "default", + currency: "USD", + weekStart: "monday", + dateFormat: "MMM d, yyyy", + timeFormat: "24h", + colorMode: "system", + }, + updatePreferences: vi.fn(), + }), +})); +vi.mock("@/components/providers/sections-provider", () => ({ + useSections: () => ({ + enabledSections: [], + customSections: [], + updateSections: vi.fn(), + updateCustomSections: vi.fn(), + }), +})); + +import { toast } from "sonner"; + +describe("SettingsPage", () => { + beforeEach(() => { + global.fetch = vi.fn((url: string) => { + if (url === "/api/user/preferences") { + return Promise.reject(new Error("network error")); + } + return Promise.resolve({ ok: true, json: async () => ({ shares: [] }) }); + }) as unknown as typeof fetch; + }); + + afterEach(() => { + cleanup(); + vi.restoreAllMocks(); + }); + + it("clears the loading skeleton and surfaces an error when the preferences fetch fails", async () => { + render(); + + // Loaded-branch-only content must not be present while loading. + expect(screen.queryByText("Personalize your planner")).not.toBeInTheDocument(); + + await waitFor(() => + expect(screen.getByText("Personalize your planner")).toBeInTheDocument() + ); + expect(toast.error).toHaveBeenCalledWith("Failed to load settings"); + }); +}); diff --git a/src/app/(app)/settings/page.tsx b/src/app/(app)/settings/page.tsx index 8e3fc15..a134af8 100644 --- a/src/app/(app)/settings/page.tsx +++ b/src/app/(app)/settings/page.tsx @@ -123,8 +123,11 @@ export default function SettingsPage() { setTargetDaysPerWeek(data.gymConfig?.targetDaysPerWeek ?? 3); setAiProviderSetting(data.aiProvider || ""); setHasAiKey(data.hasAiKey || false); - setLoading(false); - }); + }) + .catch(() => { + toast.error("Failed to load settings"); + }) + .finally(() => setLoading(false)); }, []); useEffect(() => {