test: add error handling and edge case tests for hooks
useSettings Tests: - Add test for null settings state protection - Returns null immediately without calling APIs - Prevents null pointer errors in save flow - Add test for save mutation failure - Verifies error propagates to caller - Ensures restart flag remains untouched on failure - Validates no side effects when save fails useProviderActions Tests: - Add error propagation tests for CRUD operations - updateProvider: propagates errors to caller - addProvider: propagates errors to caller - deleteProvider: propagates errors to caller - Add switch mutation error handling tests - Claude switch: handles errors silently (no throw) - Codex switch: skips plugin sync when mutation fails - Verifies plugin sync APIs not called on failure - Add loading state verification - Test all mutations pending scenario (existing) - Test all mutations idle scenario (new) - Ensures isLoading flag accuracy useImportExport Edge Case Tests (new file): - Add test for user cancelling file dialog - File dialog returns null (user cancelled) - State remains unchanged (selectedFile: "", status: "idle") - No error toast shown - Add test for resetStatus behavior - Clears error message and status - Preserves selected file path for retry - Resets backupId to null All tests passing: 79/79 (10 new tests)
This commit is contained in:
@@ -275,4 +275,42 @@ describe("useSettings hook", () => {
|
||||
);
|
||||
expect(metadataMock.setRequiresRestart).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it("returns null immediately when settings state is missing", async () => {
|
||||
settingsFormMock = createSettingsFormMock({
|
||||
settings: null,
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => useSettings());
|
||||
|
||||
let resultValue: { requiresRestart: boolean } | null = null;
|
||||
await act(async () => {
|
||||
resultValue = await result.current.saveSettings();
|
||||
});
|
||||
|
||||
expect(resultValue).toBeNull();
|
||||
expect(mutateAsyncMock).not.toHaveBeenCalled();
|
||||
expect(setAppConfigDirOverrideMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("throws when save mutation rejects and keeps restart flag untouched", async () => {
|
||||
settingsFormMock = createSettingsFormMock();
|
||||
directorySettingsMock = createDirectorySettingsMock({
|
||||
appConfigDir: "/override/app",
|
||||
initialAppConfigDir: "/override/app",
|
||||
});
|
||||
const rejection = new Error("save failed");
|
||||
mutateAsyncMock.mockRejectedValueOnce(rejection);
|
||||
|
||||
const { result } = renderHook(() => useSettings());
|
||||
|
||||
await expect(
|
||||
act(async () => {
|
||||
await result.current.saveSettings();
|
||||
}),
|
||||
).rejects.toThrow("save failed");
|
||||
|
||||
expect(setAppConfigDirOverrideMock).not.toHaveBeenCalled();
|
||||
expect(metadataMock.setRequiresRestart).not.toHaveBeenCalledWith(true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user