import { createAppSettings } from "@shared/testing/factories.js"; import { act, waitFor } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import * as api from "../api"; import { renderHookWithQueryClient } from "../test/renderWithQueryClient"; import { _resetSettingsCache, useSettings } from "./useSettings"; vi.mock("../api", () => ({ getSettings: vi.fn(), })); describe("useSettings", () => { beforeEach(() => { vi.clearAllMocks(); _resetSettingsCache(); }); it("fetches settings on mount if not already cached", async () => { const mockSettings = createAppSettings({ showSponsorInfo: { value: false, default: true, override: false }, renderMarkdownInJobDescriptions: { value: false, default: true, override: false, }, }); vi.mocked(api.getSettings).mockResolvedValue(mockSettings); const { result } = renderHookWithQueryClient(() => useSettings()); // Should start in loading state expect(result.current.settings).toBeNull(); await waitFor(() => { expect(result.current.settings).toEqual(mockSettings); }); expect(result.current.showSponsorInfo).toBe(false); expect(result.current.renderMarkdownInJobDescriptions).toBe(false); expect(api.getSettings).toHaveBeenCalledTimes(1); }); it("uses default values when settings are null", async () => { vi.mocked(api.getSettings).mockResolvedValue(null as any); const { result } = renderHookWithQueryClient(() => useSettings()); await waitFor(() => { // settings is null, so showSponsorInfo should default to true expect(result.current.showSponsorInfo).toBe(true); expect(result.current.renderMarkdownInJobDescriptions).toBe(true); }); }); it("provides a refresh function that updates settings", async () => { const initialSettings = createAppSettings(); const updatedSettings = createAppSettings({ showSponsorInfo: { value: false, default: true, override: false }, renderMarkdownInJobDescriptions: { value: false, default: true, override: false, }, }); vi.mocked(api.getSettings).mockResolvedValueOnce(initialSettings); vi.mocked(api.getSettings).mockResolvedValueOnce(updatedSettings); const { result } = renderHookWithQueryClient(() => useSettings()); await waitFor(() => { expect(result.current.settings).toEqual(initialSettings); }); let refreshed: any; await act(async () => { refreshed = await result.current.refreshSettings(); }); await waitFor(() => { expect(result.current.settings).toEqual(updatedSettings); }); expect(refreshed).toEqual(updatedSettings); expect(result.current.showSponsorInfo).toBe(false); expect(result.current.renderMarkdownInJobDescriptions).toBe(false); }); it("handles errors when fetching settings", async () => { const mockError = new Error("Failed to fetch"); vi.mocked(api.getSettings).mockRejectedValue(mockError); const { result } = renderHookWithQueryClient(() => useSettings()); await waitFor(() => { expect(result.current.error).toEqual(mockError); }); expect(result.current.isLoading).toBe(false); expect(result.current.settings).toBeNull(); }); });