From 6f6f7155c633a362c075eb387cbb0812a96c81ac Mon Sep 17 00:00:00 2001 From: luvs01 Date: Fri, 7 Aug 2026 17:30:16 +0900 Subject: [PATCH] fix(gui): avoid false empty integrations state --- gui/src/pages/integrations/IntegrationsOverview.tsx | 8 ++++---- gui/tests/integrations-surfaces.test.tsx | 11 +++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/gui/src/pages/integrations/IntegrationsOverview.tsx b/gui/src/pages/integrations/IntegrationsOverview.tsx index cc063bd5a..ad85f1652 100644 --- a/gui/src/pages/integrations/IntegrationsOverview.tsx +++ b/gui/src/pages/integrations/IntegrationsOverview.tsx @@ -260,11 +260,11 @@ export default function IntegrationsOverview({ const installedFileClients = clients.filter(client => client.installed); /* * "Settled" is what separates a client the server omitted from one whose - * list has not answered yet. Only a cold state means we have never had an - * answer; a stale-with-error state still holds real rows. + * list has not answered successfully yet. The resource's data is undefined + * both before its first response and after a cold failure; a stale failure + * still holds the last real rows. */ - const clientsSettled = statesResource.state.kind !== "cold" - && statesResource.state.kind !== "retrying-cold"; + const clientsSettled = statesResource.state.data !== undefined; const native = nativeResource.state.data ?? null; // `readOptional` returns null for a failed probe. Only an actual array is a // settled contract; an empty array is meaningful and removes both switches. diff --git a/gui/tests/integrations-surfaces.test.tsx b/gui/tests/integrations-surfaces.test.tsx index c4090792d..1c0cf7e68 100644 --- a/gui/tests/integrations-surfaces.test.tsx +++ b/gui/tests/integrations-surfaces.test.tsx @@ -400,6 +400,17 @@ test("the overview does not claim nothing is installed while it is still loading expect(container.textContent ?? "").toContain("No installed clients were detected"); }); +test("the overview does not claim nothing is installed when the client list fails to load", async () => { + stateResponse = () => json({ error: "nope" }, 500); + + await mountOverview(); + + const text = container.textContent ?? ""; + expect(text).toContain("Could not load integration state"); + expect(text).not.toContain("No installed clients were detected"); + expect(container.querySelector('[data-client="hermes"]')).not.toBeNull(); +}); + test("bulk disable confirms the result with the server before claiming success", async () => { /* * The resource layer's `refresh()` is fire-and-forget, so awaiting it proves