mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-30 06:12:03 +00:00
- Created git-test-repo helper for managing test git repositories - Added 13 integration tests covering: - Worktree operations (create, error handling, non-worktree mode) - Feature execution (status updates, model selection, duplicate prevention) - Auto loop (start/stop, pending features, max concurrency, events) - Error handling (provider errors, continue after failures) - Integration tests use real git operations with temporary repos - All 416 tests passing with 72.65% overall coverage - Service coverage improved: agent-service 58%, auto-mode-service 44%, feature-loader 66% 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
227 lines
7.6 KiB
TypeScript
227 lines
7.6 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import {
|
|
extractTextFromContent,
|
|
normalizeContentBlocks,
|
|
formatHistoryAsText,
|
|
convertHistoryToMessages,
|
|
} from "@/lib/conversation-utils.js";
|
|
import { conversationHistoryFixture } from "../../fixtures/messages.js";
|
|
|
|
describe("conversation-utils.ts", () => {
|
|
describe("extractTextFromContent", () => {
|
|
it("should return string content as-is", () => {
|
|
const result = extractTextFromContent("Hello world");
|
|
expect(result).toBe("Hello world");
|
|
});
|
|
|
|
it("should extract text from single text block", () => {
|
|
const content = [{ type: "text", text: "Hello" }];
|
|
const result = extractTextFromContent(content);
|
|
expect(result).toBe("Hello");
|
|
});
|
|
|
|
it("should extract and join multiple text blocks with newlines", () => {
|
|
const content = [
|
|
{ type: "text", text: "First block" },
|
|
{ type: "text", text: "Second block" },
|
|
{ type: "text", text: "Third block" },
|
|
];
|
|
const result = extractTextFromContent(content);
|
|
expect(result).toBe("First block\nSecond block\nThird block");
|
|
});
|
|
|
|
it("should ignore non-text blocks", () => {
|
|
const content = [
|
|
{ type: "text", text: "Text content" },
|
|
{ type: "image", source: { type: "base64", data: "abc" } },
|
|
{ type: "text", text: "More text" },
|
|
{ type: "tool_use", name: "bash", input: {} },
|
|
];
|
|
const result = extractTextFromContent(content);
|
|
expect(result).toBe("Text content\nMore text");
|
|
});
|
|
|
|
it("should handle blocks without text property", () => {
|
|
const content = [
|
|
{ type: "text", text: "Valid" },
|
|
{ type: "text" } as any,
|
|
{ type: "text", text: "Also valid" },
|
|
];
|
|
const result = extractTextFromContent(content);
|
|
expect(result).toBe("Valid\n\nAlso valid");
|
|
});
|
|
|
|
it("should handle empty array", () => {
|
|
const result = extractTextFromContent([]);
|
|
expect(result).toBe("");
|
|
});
|
|
|
|
it("should handle array with only non-text blocks", () => {
|
|
const content = [
|
|
{ type: "image", source: {} },
|
|
{ type: "tool_use", name: "test" },
|
|
];
|
|
const result = extractTextFromContent(content);
|
|
expect(result).toBe("");
|
|
});
|
|
});
|
|
|
|
describe("normalizeContentBlocks", () => {
|
|
it("should convert string to content block array", () => {
|
|
const result = normalizeContentBlocks("Hello");
|
|
expect(result).toEqual([{ type: "text", text: "Hello" }]);
|
|
});
|
|
|
|
it("should return array content as-is", () => {
|
|
const content = [
|
|
{ type: "text", text: "Hello" },
|
|
{ type: "image", source: {} },
|
|
];
|
|
const result = normalizeContentBlocks(content);
|
|
expect(result).toBe(content);
|
|
expect(result).toHaveLength(2);
|
|
});
|
|
|
|
it("should handle empty string", () => {
|
|
const result = normalizeContentBlocks("");
|
|
expect(result).toEqual([{ type: "text", text: "" }]);
|
|
});
|
|
});
|
|
|
|
describe("formatHistoryAsText", () => {
|
|
it("should return empty string for empty history", () => {
|
|
const result = formatHistoryAsText([]);
|
|
expect(result).toBe("");
|
|
});
|
|
|
|
it("should format single user message", () => {
|
|
const history = [{ role: "user" as const, content: "Hello" }];
|
|
const result = formatHistoryAsText(history);
|
|
|
|
expect(result).toContain("Previous conversation:");
|
|
expect(result).toContain("User: Hello");
|
|
expect(result).toContain("---");
|
|
});
|
|
|
|
it("should format single assistant message", () => {
|
|
const history = [{ role: "assistant" as const, content: "Hi there" }];
|
|
const result = formatHistoryAsText(history);
|
|
|
|
expect(result).toContain("Assistant: Hi there");
|
|
});
|
|
|
|
it("should format multiple messages with correct roles", () => {
|
|
const history = conversationHistoryFixture.slice(0, 2);
|
|
const result = formatHistoryAsText(history);
|
|
|
|
expect(result).toContain("User: Hello, can you help me?");
|
|
expect(result).toContain("Assistant: Of course! How can I assist you today?");
|
|
expect(result).toContain("---");
|
|
});
|
|
|
|
it("should handle messages with array content (multipart)", () => {
|
|
const history = [conversationHistoryFixture[2]]; // Has text + image
|
|
const result = formatHistoryAsText(history);
|
|
|
|
expect(result).toContain("What is in this image?");
|
|
expect(result).not.toContain("base64"); // Should not include image data
|
|
});
|
|
|
|
it("should format all messages from fixture", () => {
|
|
const result = formatHistoryAsText(conversationHistoryFixture);
|
|
|
|
expect(result).toContain("Previous conversation:");
|
|
expect(result).toContain("User: Hello, can you help me?");
|
|
expect(result).toContain("Assistant: Of course!");
|
|
expect(result).toContain("User: What is in this image?");
|
|
expect(result).toContain("---");
|
|
});
|
|
|
|
it("should separate messages with double newlines", () => {
|
|
const history = [
|
|
{ role: "user" as const, content: "First" },
|
|
{ role: "assistant" as const, content: "Second" },
|
|
];
|
|
const result = formatHistoryAsText(history);
|
|
|
|
expect(result).toMatch(/User: First\n\nAssistant: Second/);
|
|
});
|
|
});
|
|
|
|
describe("convertHistoryToMessages", () => {
|
|
it("should convert empty history", () => {
|
|
const result = convertHistoryToMessages([]);
|
|
expect(result).toEqual([]);
|
|
});
|
|
|
|
it("should convert single message to SDK format", () => {
|
|
const history = [{ role: "user" as const, content: "Hello" }];
|
|
const result = convertHistoryToMessages(history);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0]).toMatchObject({
|
|
type: "user",
|
|
session_id: "",
|
|
message: {
|
|
role: "user",
|
|
content: [{ type: "text", text: "Hello" }],
|
|
},
|
|
parent_tool_use_id: null,
|
|
});
|
|
});
|
|
|
|
it("should normalize string content to array", () => {
|
|
const history = [{ role: "assistant" as const, content: "Response" }];
|
|
const result = convertHistoryToMessages(history);
|
|
|
|
expect(result[0].message.content).toEqual([
|
|
{ type: "text", text: "Response" },
|
|
]);
|
|
});
|
|
|
|
it("should preserve array content", () => {
|
|
const history = [
|
|
{
|
|
role: "user" as const,
|
|
content: [
|
|
{ type: "text", text: "Hello" },
|
|
{ type: "image", source: {} },
|
|
],
|
|
},
|
|
];
|
|
const result = convertHistoryToMessages(history);
|
|
|
|
expect(result[0].message.content).toHaveLength(2);
|
|
expect(result[0].message.content[0]).toEqual({ type: "text", text: "Hello" });
|
|
});
|
|
|
|
it("should convert multiple messages", () => {
|
|
const history = conversationHistoryFixture.slice(0, 2);
|
|
const result = convertHistoryToMessages(history);
|
|
|
|
expect(result).toHaveLength(2);
|
|
expect(result[0].type).toBe("user");
|
|
expect(result[1].type).toBe("assistant");
|
|
});
|
|
|
|
it("should set correct fields for SDK format", () => {
|
|
const history = [{ role: "user" as const, content: "Test" }];
|
|
const result = convertHistoryToMessages(history);
|
|
|
|
expect(result[0].session_id).toBe("");
|
|
expect(result[0].parent_tool_use_id).toBeNull();
|
|
expect(result[0].type).toBe("user");
|
|
expect(result[0].message.role).toBe("user");
|
|
});
|
|
|
|
it("should handle all messages from fixture", () => {
|
|
const result = convertHistoryToMessages(conversationHistoryFixture);
|
|
|
|
expect(result).toHaveLength(3);
|
|
expect(result[0].message.content).toBeInstanceOf(Array);
|
|
expect(result[1].message.content).toBeInstanceOf(Array);
|
|
expect(result[2].message.content).toBeInstanceOf(Array);
|
|
});
|
|
});
|
|
});
|