diff --git a/src/lib/stores/snippets.test.ts b/src/lib/stores/snippets.test.ts index 0f9b082..e6f4db9 100644 --- a/src/lib/stores/snippets.test.ts +++ b/src/lib/stores/snippets.test.ts @@ -285,6 +285,73 @@ describe("snippetsStore", () => { expect(get(snippetsStore.selectedCategory)).toBeNull(); }); }); + + describe("filteredSnippets", () => { + it("returns all snippets when no category selected", async () => { + const mockSnippets: Snippet[] = [ + { + id: "snippet-1", + name: "Git Status", + content: "git status", + category: "Git", + is_default: false, + created_at: "2024-01-01T00:00:00Z", + updated_at: "2024-01-01T00:00:00Z", + }, + { + id: "snippet-2", + name: "Docker PS", + content: "docker ps", + category: "Docker", + is_default: false, + created_at: "2024-01-01T00:00:00Z", + updated_at: "2024-01-01T00:00:00Z", + }, + ]; + + setMockInvokeResult("list_snippets", mockSnippets); + setMockInvokeResult("get_snippet_categories", ["Git", "Docker"]); + + await snippetsStore.loadSnippets(); + snippetsStore.setSelectedCategory(null); + + const filtered = get(snippetsStore.filteredSnippets); + expect(filtered).toHaveLength(2); + }); + + it("filters snippets by selected category", async () => { + const mockSnippets: Snippet[] = [ + { + id: "snippet-1", + name: "Git Status", + content: "git status", + category: "Git", + is_default: false, + created_at: "2024-01-01T00:00:00Z", + updated_at: "2024-01-01T00:00:00Z", + }, + { + id: "snippet-2", + name: "Docker PS", + content: "docker ps", + category: "Docker", + is_default: false, + created_at: "2024-01-01T00:00:00Z", + updated_at: "2024-01-01T00:00:00Z", + }, + ]; + + setMockInvokeResult("list_snippets", mockSnippets); + setMockInvokeResult("get_snippet_categories", ["Git", "Docker"]); + + await snippetsStore.loadSnippets(); + snippetsStore.setSelectedCategory("Git"); + + const filtered = get(snippetsStore.filteredSnippets); + expect(filtered).toHaveLength(1); + expect(filtered[0].category).toBe("Git"); + }); + }); }); describe("snippet ID generation", () => { diff --git a/src/lib/utils/stateMapper.test.ts b/src/lib/utils/stateMapper.test.ts index fd184df..50ca8a1 100644 --- a/src/lib/utils/stateMapper.test.ts +++ b/src/lib/utils/stateMapper.test.ts @@ -135,6 +135,151 @@ describe("stateMapper", () => { }; expect(mapMessageToState(message)).toBeNull(); }); + + it("returns typing for unknown tool", () => { + const message: ClaudeStreamMessage = { + type: "assistant", + message: { + content: [ + { + type: "tool_use", + id: "tool-1", + name: "SomeUnknownTool", + input: {}, + }, + ], + model: "claude-3", + stop_reason: "tool_use", + }, + }; + expect(mapMessageToState(message)).toBe("typing"); + }); + + it("returns thinking for thinking content block", () => { + const message: ClaudeStreamMessage = { + type: "assistant", + message: { + content: [{ type: "thinking", thinking: "Analyzing the problem..." }], + model: "claude-3", + stop_reason: "end_turn", + }, + }; + expect(mapMessageToState(message)).toBe("thinking"); + }); + + it("returns null for assistant message with no recognizable content", () => { + const message: ClaudeStreamMessage = { + type: "assistant", + message: { + content: [], + model: "claude-3", + stop_reason: "end_turn", + }, + }; + expect(mapMessageToState(message)).toBeNull(); + }); + + it("returns thinking for thinking_delta stream event", () => { + const message: ClaudeStreamMessage = { + type: "stream_event", + event: { + type: "content_block_delta", + index: 0, + delta: { + type: "thinking_delta", + thinking: "Thinking...", + }, + }, + }; + expect(mapMessageToState(message)).toBe("thinking"); + }); + + it("returns typing for text_delta stream event", () => { + const message: ClaudeStreamMessage = { + type: "stream_event", + event: { + type: "content_block_delta", + index: 0, + delta: { + type: "text_delta", + text: "Hello", + }, + }, + }; + expect(mapMessageToState(message)).toBe("typing"); + }); + + it("returns thinking for thinking content_block_start", () => { + const message: ClaudeStreamMessage = { + type: "stream_event", + event: { + type: "content_block_start", + index: 0, + content_block: { + type: "thinking", + thinking: "", + }, + }, + }; + expect(mapMessageToState(message)).toBe("thinking"); + }); + + it("returns typing for text content_block_start", () => { + const message: ClaudeStreamMessage = { + type: "stream_event", + event: { + type: "content_block_start", + index: 0, + content_block: { + type: "text", + text: "", + }, + }, + }; + expect(mapMessageToState(message)).toBe("typing"); + }); + + it("returns correct state for tool_use content_block_start", () => { + const message: ClaudeStreamMessage = { + type: "stream_event", + event: { + type: "content_block_start", + index: 0, + content_block: { + type: "tool_use", + id: "tool-1", + name: "Read", + input: {}, + }, + }, + }; + expect(mapMessageToState(message)).toBe("searching"); + }); + + it("returns null for stream_event with unrecognized type", () => { + const message: ClaudeStreamMessage = { + type: "stream_event", + event: { + type: "message_start", + }, + }; + expect(mapMessageToState(message)).toBeNull(); + }); + + it("returns null for result with unknown subtype", () => { + const message: ClaudeStreamMessage = { + type: "result", + subtype: "unknown_type", + }; + expect(mapMessageToState(message)).toBeNull(); + }); + + it("returns null for unknown message type", () => { + const message = { + type: "unknown_type", + } as unknown as ClaudeStreamMessage; + expect(mapMessageToState(message)).toBeNull(); + }); }); describe("extractTextFromMessage", () => { @@ -192,6 +337,36 @@ describe("stateMapper", () => { }; expect(extractTextFromMessage(message)).toBe("Completed successfully"); }); + + it("returns null for result without result field", () => { + const message: ClaudeStreamMessage = { + type: "result", + subtype: "success", + }; + expect(extractTextFromMessage(message)).toBeNull(); + }); + + it("returns null for stream_event without delta text", () => { + const message: ClaudeStreamMessage = { + type: "stream_event", + event: { + type: "content_block_start", + index: 0, + content_block: { + type: "text", + text: "", + }, + }, + }; + expect(extractTextFromMessage(message)).toBeNull(); + }); + + it("returns null for unknown message type", () => { + const message = { + type: "unknown", + } as unknown as ClaudeStreamMessage; + expect(extractTextFromMessage(message)).toBeNull(); + }); }); describe("extractToolInfo", () => {