Skip to content

Commit 8457e39

Browse files
committed
test: cover EBUSY retry exhaustion for both persist paths
Review follow-up: the previous failure case used a code-less error, which exercises only the non-retryable single-attempt path. That case is now named accurately and pins attempt count = 1; two new cases drive persistent EBUSY through all four queued-retry attempts for the dashboard and backend persists before the warn + fallback. https://claude.ai/code/session_01XNtnkLbBiXZxfQQYLMpucB
1 parent 2fdd5bd commit 8457e39

1 file changed

Lines changed: 33 additions & 1 deletion

File tree

test/settings-hub-shared.test.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ describe("settings hub shared helpers", () => {
142142
expect(result.menuShowLastUsed).toBe(false);
143143
});
144144

145-
it("warns and returns the selection as fallback when the write keeps failing", async () => {
145+
it("gives up immediately on a non-retryable error, warning with the fallback", async () => {
146146
saveDashboardDisplaySettingsMock.mockRejectedValue(
147147
new Error("disk gone"),
148148
);
@@ -161,6 +161,23 @@ describe("settings hub shared helpers", () => {
161161
expect(result).toStrictEqual(cloneDashboardSettings(selected));
162162
expect(result.menuShowLastUsed).toBe(false);
163163
expect(result).not.toBe(selected);
164+
// Non-retryable: the write must fail on the first attempt, no retries.
165+
expect(saveDashboardDisplaySettingsMock).toHaveBeenCalledTimes(1);
166+
});
167+
168+
it("exhausts all four attempts on persistent EBUSY before falling back", async () => {
169+
saveDashboardDisplaySettingsMock.mockRejectedValue(busyError());
170+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
171+
const result = await persistDashboardSettingsSelectionForTests(
172+
{ menuShowLastUsed: false },
173+
["menuShowLastUsed"],
174+
"dashboard",
175+
);
176+
expect(saveDashboardDisplaySettingsMock).toHaveBeenCalledTimes(4);
177+
expect(warnSpy).toHaveBeenCalledWith(
178+
"Settings save failed (dashboard) after retries: locked",
179+
);
180+
expect(result.menuShowLastUsed).toBe(false);
164181
});
165182
});
166183

@@ -194,6 +211,21 @@ describe("settings hub shared helpers", () => {
194211
);
195212
expect(backendSettingsEqual(result, selected)).toBe(true);
196213
});
214+
215+
it("exhausts all four attempts on persistent EBUSY for the backend path too", async () => {
216+
savePluginConfigMock.mockRejectedValue(busyError());
217+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
218+
const selected = {} as PluginConfig;
219+
const result = await persistBackendConfigSelectionForTests(
220+
selected,
221+
"backend",
222+
);
223+
expect(savePluginConfigMock).toHaveBeenCalledTimes(4);
224+
expect(warnSpy).toHaveBeenCalledWith(
225+
"Settings save failed (backend) after retries: locked",
226+
);
227+
expect(backendSettingsEqual(result, selected)).toBe(true);
228+
});
197229
});
198230

199231
describe("clampBackendNumber", () => {

0 commit comments

Comments
 (0)