useDirectorySettings Tests: - Test directory initialization with overrides and remote defaults - Verify app config override with space trimming - Load Claude/Codex directories from remote API - Calculate resolvedDirs correctly - Test directory browsing functionality - Browse Claude/Codex config directories - Browse app config directory with proper default paths - Update settings callback when selection succeeds - Test error handling scenarios - User cancels directory selection (returns null) - Directory picker throws error (shows toast) - Verify settings not updated on failure - Test directory reset operations - Reset individual directories to computed defaults - Reset app config directory - Batch reset with provided server values - Use vi.hoisted() for proper mock initialization - Factory function for settings creation (reusability) useSettingsMetadata Tests: - Test portable mode flag loading - Verify initial loading state - Load portable flag from API - Handle async state transitions - Test error tolerance when API fails - Silent failure on network errors - Default to non-portable mode - Continue without blocking UI - Test restart flag management - Set restart required flag - Acknowledge restart to clear flag - State updates wrapped in act() All tests passing: 10/10 (7 useDirectorySettings + 3 useSettingsMetadata)
71 lines
1.8 KiB
TypeScript
71 lines
1.8 KiB
TypeScript
import { renderHook, act } from "@testing-library/react";
|
|
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
import { useSettingsMetadata } from "@/hooks/useSettingsMetadata";
|
|
|
|
const isPortableMock = vi.hoisted(() => vi.fn());
|
|
|
|
vi.mock("@/lib/api", () => ({
|
|
settingsApi: {
|
|
isPortable: (...args: unknown[]) => isPortableMock(...args),
|
|
},
|
|
}));
|
|
|
|
describe("useSettingsMetadata", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it("loads portable flag and handles success path", async () => {
|
|
isPortableMock.mockResolvedValue(true);
|
|
|
|
const { result } = renderHook(() => useSettingsMetadata());
|
|
|
|
expect(result.current.isLoading).toBe(true);
|
|
expect(result.current.isPortable).toBe(false);
|
|
|
|
await act(async () => {
|
|
await Promise.resolve();
|
|
});
|
|
|
|
expect(result.current.isPortable).toBe(true);
|
|
expect(result.current.isLoading).toBe(false);
|
|
});
|
|
|
|
it("handles errors from settingsApi and proceeds", async () => {
|
|
isPortableMock.mockRejectedValue(new Error("network failure"));
|
|
|
|
const { result } = renderHook(() => useSettingsMetadata());
|
|
|
|
await act(async () => {
|
|
await Promise.resolve();
|
|
});
|
|
|
|
expect(result.current.isPortable).toBe(false);
|
|
expect(result.current.isLoading).toBe(false);
|
|
});
|
|
|
|
it("allows updating restart flag via setters", async () => {
|
|
isPortableMock.mockResolvedValue(false);
|
|
|
|
const { result } = renderHook(() => useSettingsMetadata());
|
|
|
|
await act(async () => {
|
|
await Promise.resolve();
|
|
});
|
|
|
|
await act(async () => {
|
|
result.current.setRequiresRestart(true);
|
|
await Promise.resolve();
|
|
});
|
|
|
|
expect(result.current.requiresRestart).toBe(true);
|
|
|
|
await act(async () => {
|
|
result.current.acknowledgeRestart();
|
|
await Promise.resolve();
|
|
});
|
|
|
|
expect(result.current.requiresRestart).toBe(false);
|
|
});
|
|
});
|