feat: start setting up CI
Security Scan and Upload / Security & DefectDojo Upload (pull_request) Successful in 49s
CI / Lint & Test (pull_request) Failing after 4m58s
CI / Build Linux (pull_request) Has been skipped
CI / Build Windows (cross-compile) (pull_request) Has been skipped

This commit is contained in:
2026-01-15 10:38:04 -08:00
parent bd04328e40
commit 1698735c47
11 changed files with 2600 additions and 16 deletions
+275
View File
@@ -0,0 +1,275 @@
import { describe, it, expect } from "vitest";
import { mapMessageToState, extractTextFromMessage, extractToolInfo } from "./stateMapper";
import type { ClaudeStreamMessage, AssistantMessage } from "$lib/types/messages";
describe("stateMapper", () => {
describe("mapMessageToState", () => {
it("returns idle for system init message", () => {
const message: ClaudeStreamMessage = {
type: "system",
subtype: "init",
session_id: "test-session",
};
expect(mapMessageToState(message)).toBe("idle");
});
it("returns null for non-init system messages", () => {
const message: ClaudeStreamMessage = {
type: "system",
subtype: "other",
session_id: "test-session",
};
expect(mapMessageToState(message)).toBeNull();
});
it("returns searching for Read tool", () => {
const message: ClaudeStreamMessage = {
type: "assistant",
message: {
id: "test",
type: "message",
role: "assistant",
content: [
{
type: "tool_use",
id: "tool-1",
name: "Read",
input: { file_path: "/test/file.txt" },
},
],
model: "claude-3",
stop_reason: "tool_use",
usage: { input_tokens: 100, output_tokens: 50 },
},
};
expect(mapMessageToState(message)).toBe("searching");
});
it("returns coding for Edit tool", () => {
const message: ClaudeStreamMessage = {
type: "assistant",
message: {
id: "test",
type: "message",
role: "assistant",
content: [
{
type: "tool_use",
id: "tool-1",
name: "Edit",
input: { file_path: "/test/file.txt", old_string: "foo", new_string: "bar" },
},
],
model: "claude-3",
stop_reason: "tool_use",
usage: { input_tokens: 100, output_tokens: 50 },
},
};
expect(mapMessageToState(message)).toBe("coding");
});
it("returns mcp for mcp__ prefixed tools", () => {
const message: ClaudeStreamMessage = {
type: "assistant",
message: {
id: "test",
type: "message",
role: "assistant",
content: [
{
type: "tool_use",
id: "tool-1",
name: "mcp__github__list_repos",
input: {},
},
],
model: "claude-3",
stop_reason: "tool_use",
usage: { input_tokens: 100, output_tokens: 50 },
},
};
expect(mapMessageToState(message)).toBe("mcp");
});
it("returns thinking for Task tool", () => {
const message: ClaudeStreamMessage = {
type: "assistant",
message: {
id: "test",
type: "message",
role: "assistant",
content: [
{
type: "tool_use",
id: "tool-1",
name: "Task",
input: { prompt: "test task" },
},
],
model: "claude-3",
stop_reason: "tool_use",
usage: { input_tokens: 100, output_tokens: 50 },
},
};
expect(mapMessageToState(message)).toBe("thinking");
});
it("returns typing for text content", () => {
const message: ClaudeStreamMessage = {
type: "assistant",
message: {
id: "test",
type: "message",
role: "assistant",
content: [{ type: "text", text: "Hello, Naomi!" }],
model: "claude-3",
stop_reason: "end_turn",
usage: { input_tokens: 100, output_tokens: 50 },
},
};
expect(mapMessageToState(message)).toBe("typing");
});
it("returns success for result success message", () => {
const message: ClaudeStreamMessage = {
type: "result",
subtype: "success",
result: "Task completed",
session_id: "test-session",
};
expect(mapMessageToState(message)).toBe("success");
});
it("returns error for result error message", () => {
const message: ClaudeStreamMessage = {
type: "result",
subtype: "error_max_turns",
error: "Max turns exceeded",
session_id: "test-session",
};
expect(mapMessageToState(message)).toBe("error");
});
it("returns null for user messages", () => {
const message: ClaudeStreamMessage = {
type: "user",
message: { role: "user", content: "Hello" },
};
expect(mapMessageToState(message)).toBeNull();
});
});
describe("extractTextFromMessage", () => {
it("extracts text from assistant message", () => {
const message: ClaudeStreamMessage = {
type: "assistant",
message: {
id: "test",
type: "message",
role: "assistant",
content: [
{ type: "text", text: "Hello!" },
{ type: "text", text: "How are you?" },
],
model: "claude-3",
stop_reason: "end_turn",
usage: { input_tokens: 100, output_tokens: 50 },
},
};
expect(extractTextFromMessage(message)).toBe("Hello!\nHow are you?");
});
it("returns null for assistant message without text", () => {
const message: ClaudeStreamMessage = {
type: "assistant",
message: {
id: "test",
type: "message",
role: "assistant",
content: [
{
type: "tool_use",
id: "tool-1",
name: "Read",
input: { file_path: "/test/file.txt" },
},
],
model: "claude-3",
stop_reason: "tool_use",
usage: { input_tokens: 100, output_tokens: 50 },
},
};
expect(extractTextFromMessage(message)).toBeNull();
});
it("extracts text from stream_event delta", () => {
const message: ClaudeStreamMessage = {
type: "stream_event",
event: {
type: "content_block_delta",
index: 0,
delta: { type: "text_delta", text: "streaming text" },
},
};
expect(extractTextFromMessage(message)).toBe("streaming text");
});
it("extracts result from result message", () => {
const message: ClaudeStreamMessage = {
type: "result",
subtype: "success",
result: "Completed successfully",
session_id: "test-session",
};
expect(extractTextFromMessage(message)).toBe("Completed successfully");
});
});
describe("extractToolInfo", () => {
it("extracts tool info from assistant message", () => {
const message: ClaudeStreamMessage = {
type: "assistant",
message: {
id: "test",
type: "message",
role: "assistant",
content: [
{
type: "tool_use",
id: "tool-1",
name: "Read",
input: { file_path: "/test/file.txt" },
},
{
type: "tool_use",
id: "tool-2",
name: "Edit",
input: { file_path: "/test/file.txt", old_string: "a", new_string: "b" },
},
],
model: "claude-3",
stop_reason: "tool_use",
usage: { input_tokens: 100, output_tokens: 50 },
},
};
const tools = extractToolInfo(message);
expect(tools).toHaveLength(2);
expect(tools[0]).toEqual({
name: "Read",
input: { file_path: "/test/file.txt" },
});
expect(tools[1]).toEqual({
name: "Edit",
input: { file_path: "/test/file.txt", old_string: "a", new_string: "b" },
});
});
it("returns empty array for non-assistant messages", () => {
const message: ClaudeStreamMessage = {
type: "user",
message: { role: "user", content: "Hello" },
};
expect(extractToolInfo(message)).toEqual([]);
});
});
});