From 436576fe1565b5f709c9bd058bf0e097abda9fea Mon Sep 17 00:00:00 2001 From: SnapOtter Date: Mon, 18 May 2026 17:24:36 +0800 Subject: [PATCH] fix: resolve features-store test timeouts and dynamic icon-map test (#151) - Fix installAll tests timing out by returning installed status from refreshBundles mock (prevents infinite retry loop) and increasing waitFor/test timeouts to accommodate the 2s inter-install delay - Fix zustand-stores installAll test with same refreshBundles mock fix - Icon-map test already fixed to derive from shared constants --- tests/unit/web/features-store.test.ts | 34 +++++++++++++++------------ tests/unit/web/zustand-stores.test.ts | 6 +++-- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/tests/unit/web/features-store.test.ts b/tests/unit/web/features-store.test.ts index 54c1dd02..c735b858 100644 --- a/tests/unit/web/features-store.test.ts +++ b/tests/unit/web/features-store.test.ts @@ -374,7 +374,9 @@ describe("useFeaturesStore", () => { } return Promise.resolve({}); }); - apiGetMock.mockResolvedValue({ bundles }); + apiGetMock.mockResolvedValue({ + bundles: bundles.map((b) => ({ ...b, status: "installed" })), + }); const promise = useFeaturesStore.getState().installAll(); @@ -382,13 +384,18 @@ describe("useFeaturesStore", () => { expect(useFeaturesStore.getState().installAllActive).toBe(true); }); + const completeAllOpen = () => { + for (const es of FakeEventSource.instances) { + if (!es.closed) { + es.onmessage?.({ data: JSON.stringify({ phase: "complete" }) }); + } + } + }; + await vi.waitFor(() => { expect(FakeEventSource.instances.length).toBeGreaterThan(0); }); - - for (const es of FakeEventSource.instances) { - es.onmessage?.({ data: JSON.stringify({ phase: "complete" }) }); - } + completeAllOpen(); await vi .waitFor( @@ -397,22 +404,17 @@ describe("useFeaturesStore", () => { throw new Error("waiting for second EventSource"); } }, - { timeout: 2000 }, + { timeout: 5000 }, ) .catch(() => {}); - - for (const es of FakeEventSource.instances) { - if (!es.closed) { - es.onmessage?.({ data: JSON.stringify({ phase: "complete" }) }); - } - } + completeAllOpen(); await promise; const state = useFeaturesStore.getState(); expect(state.installAllActive).toBe(false); expect(state.queued).toEqual([]); - }); + }, 15000); it("clears stale errors for pending bundles", async () => { const bundles = [makeBundleState({ id: "err-bundle", status: "error" })]; @@ -423,7 +425,9 @@ describe("useFeaturesStore", () => { }); apiPostMock.mockResolvedValue({ jobId: "job-err" }); - apiGetMock.mockResolvedValue({ bundles }); + apiGetMock.mockResolvedValue({ + bundles: bundles.map((b) => ({ ...b, status: "installed" })), + }); const promise = useFeaturesStore.getState().installAll(); @@ -440,7 +444,7 @@ describe("useFeaturesStore", () => { } await promise; - }); + }, 15000); }); describe("EventSource progress handling", () => { diff --git a/tests/unit/web/zustand-stores.test.ts b/tests/unit/web/zustand-stores.test.ts index bd95b2af..04274d0e 100644 --- a/tests/unit/web/zustand-stores.test.ts +++ b/tests/unit/web/zustand-stores.test.ts @@ -2677,13 +2677,15 @@ describe("useFeaturesStore", () => { ); mockApiPost.mockResolvedValueOnce({ jobId: "job-clear" }); - mockApiGet.mockResolvedValue({ bundles }); + mockApiGet.mockResolvedValue({ + bundles: bundles.map((b) => ({ ...b, status: "installed" as const })), + }); await useFeaturesStore.getState().installAll(); // Error should have been cleared at the start of installAll expect(useFeaturesStore.getState().errors["ai-rembg"]).toBeUndefined(); - }); + }, 15000); }); // ==========================================================================