From 0bf3e840dc5c995942aa44082d7b43a64f4e5e26 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Sat, 27 Jun 2026 23:13:31 +0900 Subject: feat(workspace-active-indicator): show loading dots on workspace cards with active chats --- src/app/store.test.ts | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) (limited to 'src/app/store.test.ts') diff --git a/src/app/store.test.ts b/src/app/store.test.ts index 2cf473c..7fb1469 100644 --- a/src/app/store.test.ts +++ b/src/app/store.test.ts @@ -1730,6 +1730,122 @@ describe("createAppStore", () => { expect(store.tabs.some((t) => t.conversationId === "other-device-conv")).toBe(true); store.dispose(); }); + + // ── workspaceHasActiveConversations (workspace-card active indicator) ───── + + it("workspaceHasActiveConversations is false when no conversation is active", () => { + const ws = fakeSocket(); + const store = createAppStore({ + socketFactory: () => ws, + fetchImpl: fakeFetchImpl(), + localStorage: createFakeStorage(), + }); + ws.resolveOpen(); + store.send("hello"); + const convId = activeConversationId(store); + + // The conversation is freshly created — the backend hasn't reported it as + // active yet, so the workspace has no active conversation. + expect(store.conversationStatus(convId)).toBeUndefined(); + expect(store.workspaceHasActiveConversations("default")).toBe(false); + store.dispose(); + }); + + it("workspaceHasActiveConversations is true when a conversation in the workspace is active", () => { + const ws = fakeSocket(); + const store = createAppStore({ + socketFactory: () => ws, + fetchImpl: fakeFetchImpl(), + localStorage: createFakeStorage(), + }); + ws.resolveOpen(); + store.send("hello"); + const convId = activeConversationId(store); + + ws.feedServerMessage({ + type: "conversation.statusChanged", + conversationId: convId, + status: "active", + workspaceId: "default", + }); + + expect(store.workspaceHasActiveConversations("default")).toBe(true); + store.dispose(); + }); + + it("workspaceHasActiveConversations is true when a conversation is queued (waiting for a slot)", () => { + const ws = fakeSocket(); + const store = createAppStore({ + socketFactory: () => ws, + fetchImpl: fakeFetchImpl(), + localStorage: createFakeStorage(), + }); + ws.resolveOpen(); + store.send("hello"); + const convId = activeConversationId(store); + + ws.feedServerMessage({ + type: "conversation.statusChanged", + conversationId: convId, + status: "queued", + workspaceId: "default", + }); + + expect(store.workspaceHasActiveConversations("default")).toBe(true); + store.dispose(); + }); + + it("workspaceHasActiveConversations goes back to false when the conversation goes idle", () => { + const ws = fakeSocket(); + const store = createAppStore({ + socketFactory: () => ws, + fetchImpl: fakeFetchImpl(), + localStorage: createFakeStorage(), + }); + ws.resolveOpen(); + store.send("hello"); + const convId = activeConversationId(store); + + ws.feedServerMessage({ + type: "conversation.statusChanged", + conversationId: convId, + status: "active", + workspaceId: "default", + }); + expect(store.workspaceHasActiveConversations("default")).toBe(true); + + ws.feedServerMessage({ + type: "conversation.statusChanged", + conversationId: convId, + status: "idle", + workspaceId: "default", + }); + expect(store.workspaceHasActiveConversations("default")).toBe(false); + store.dispose(); + }); + + it("workspaceHasActiveConversations scopes to the given workspace (ignores other workspaces)", () => { + const ws = fakeSocket(); + const store = createAppStore({ + socketFactory: () => ws, + fetchImpl: fakeFetchImpl(), + localStorage: createFakeStorage(), + }); + ws.resolveOpen(); + + // A cross-device active conversation in workspace "proj-a". + ws.feedServerMessage({ + type: "conversation.statusChanged", + conversationId: "proj-a-conv", + status: "active", + workspaceId: "proj-a", + }); + + // proj-a is active; proj-b is not (no active conversation there). + expect(store.workspaceHasActiveConversations("proj-a")).toBe(true); + expect(store.workspaceHasActiveConversations("proj-b")).toBe(false); + store.dispose(); + }); }); describe("createAppStore — vision settings (global)", () => { -- cgit v1.2.3