Files
automaker/libs/utils/tests/conversation-utils.test.ts
SuperComboGamer 584f5a3426 Merge main into massive-terminal-upgrade
Resolves merge conflicts:
- apps/server/src/routes/terminal/common.ts: Keep randomBytes import, use @automaker/utils for createLogger
- apps/ui/eslint.config.mjs: Use main's explicit globals list with XMLHttpRequest and MediaQueryListEvent additions
- apps/ui/src/components/views/terminal-view.tsx: Keep our terminal improvements (killAllSessions, beforeunload, better error handling)
- apps/ui/src/config/terminal-themes.ts: Keep our search highlight colors for all themes
- apps/ui/src/store/app-store.ts: Keep our terminal settings persistence improvements (merge function)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 20:27:44 -05:00

242 lines
8.1 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import type { ConversationMessage } from '@automaker/types';
import {
extractTextFromContent,
normalizeContentBlocks,
formatHistoryAsText,
convertHistoryToMessages,
} from '../src/conversation-utils';
describe('conversation-utils.ts', () => {
describe('extractTextFromContent', () => {
it('should extract text from string content', () => {
const content = 'Hello, world!';
const result = extractTextFromContent(content);
expect(result).toBe('Hello, world!');
});
it('should extract text from array content with text blocks', () => {
const content = [
{ type: 'text', text: 'First block' },
{ type: 'text', text: 'Second block' },
];
const result = extractTextFromContent(content);
expect(result).toBe('First block\nSecond block');
});
it('should filter out non-text blocks', () => {
const content = [
{ type: 'text', text: 'Text block' },
{ type: 'image', source: { data: '...' } },
{ type: 'text', text: 'Another text' },
];
const result = extractTextFromContent(content);
expect(result).toBe('Text block\nAnother text');
});
it('should handle empty text blocks', () => {
const content = [
{ type: 'text', text: 'First' },
{ type: 'text' },
{ type: 'text', text: 'Third' },
];
const result = extractTextFromContent(content);
expect(result).toBe('First\n\nThird');
});
it('should return empty string for array with only non-text blocks', () => {
const content = [
{ type: 'image', source: {} },
{ type: 'tool_use', source: {} },
];
const result = extractTextFromContent(content);
expect(result).toBe('');
});
it('should return empty string for empty array', () => {
const content: Array<{ type: string; text?: string }> = [];
const result = extractTextFromContent(content);
expect(result).toBe('');
});
});
describe('normalizeContentBlocks', () => {
it('should convert string to array of text blocks', () => {
const content = 'Simple text';
const result = normalizeContentBlocks(content);
expect(result).toEqual([{ type: 'text', text: 'Simple text' }]);
});
it('should return array as-is', () => {
const content = [
{ type: 'text', text: 'First' },
{ type: 'image', source: {} },
];
const result = normalizeContentBlocks(content);
expect(result).toBe(content);
expect(result).toEqual(content);
});
it('should handle empty string', () => {
const content = '';
const result = normalizeContentBlocks(content);
expect(result).toEqual([{ type: 'text', text: '' }]);
});
it('should handle multiline string', () => {
const content = 'Line 1\nLine 2\nLine 3';
const result = normalizeContentBlocks(content);
expect(result).toEqual([{ type: 'text', text: 'Line 1\nLine 2\nLine 3' }]);
});
});
describe('formatHistoryAsText', () => {
it('should format empty history as empty string', () => {
const history: ConversationMessage[] = [];
const result = formatHistoryAsText(history);
expect(result).toBe('');
});
it('should format single user message', () => {
const history: ConversationMessage[] = [{ role: 'user', content: 'Hello!' }];
const result = formatHistoryAsText(history);
expect(result).toBe('Previous conversation:\n\nUser: Hello!\n\n---\n\n');
});
it('should format single assistant message', () => {
const history: ConversationMessage[] = [{ role: 'assistant', content: 'Hi there!' }];
const result = formatHistoryAsText(history);
expect(result).toBe('Previous conversation:\n\nAssistant: Hi there!\n\n---\n\n');
});
it('should format conversation with multiple messages', () => {
const history: ConversationMessage[] = [
{ role: 'user', content: "What's 2+2?" },
{ role: 'assistant', content: 'The answer is 4.' },
{ role: 'user', content: 'Thanks!' },
];
const result = formatHistoryAsText(history);
expect(result).toBe(
'Previous conversation:\n\n' +
"User: What's 2+2?\n\n" +
'Assistant: The answer is 4.\n\n' +
'User: Thanks!\n\n' +
'---\n\n'
);
});
it('should handle array content by extracting text', () => {
const history: ConversationMessage[] = [
{
role: 'user',
content: [
{ type: 'text', text: 'First part' },
{ type: 'text', text: 'Second part' },
],
},
];
const result = formatHistoryAsText(history);
expect(result).toBe('Previous conversation:\n\nUser: First part\nSecond part\n\n---\n\n');
});
it('should handle mixed string and array content', () => {
const history: ConversationMessage[] = [
{ role: 'user', content: 'String message' },
{
role: 'assistant',
content: [{ type: 'text', text: 'Array message' }],
},
];
const result = formatHistoryAsText(history);
expect(result).toContain('User: String message');
expect(result).toContain('Assistant: Array message');
});
});
describe('convertHistoryToMessages', () => {
it('should convert empty history', () => {
const history: ConversationMessage[] = [];
const result = convertHistoryToMessages(history);
expect(result).toEqual([]);
});
it('should convert single user message', () => {
const history: ConversationMessage[] = [{ role: 'user', 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 convert single assistant message', () => {
const history: ConversationMessage[] = [{ role: 'assistant', content: 'Hi there!' }];
const result = convertHistoryToMessages(history);
expect(result).toHaveLength(1);
expect(result[0]).toMatchObject({
type: 'assistant',
session_id: '',
message: {
role: 'assistant',
content: [{ type: 'text', text: 'Hi there!' }],
},
parent_tool_use_id: null,
});
});
it('should preserve array content as-is', () => {
const content = [
{ type: 'text', text: 'Text' },
{ type: 'image', source: { data: '...' } },
];
const history: ConversationMessage[] = [{ role: 'user', content }];
const result = convertHistoryToMessages(history);
expect(result[0].message.content).toEqual(content);
});
it('should convert multiple messages', () => {
const history: ConversationMessage[] = [
{ role: 'user', content: 'First' },
{ role: 'assistant', content: 'Second' },
{ role: 'user', content: 'Third' },
];
const result = convertHistoryToMessages(history);
expect(result).toHaveLength(3);
expect(result[0].type).toBe('user');
expect(result[1].type).toBe('assistant');
expect(result[2].type).toBe('user');
});
it('should set session_id to empty string', () => {
const history: ConversationMessage[] = [{ role: 'user', content: 'Test' }];
const result = convertHistoryToMessages(history);
expect(result[0].session_id).toBe('');
});
it('should set parent_tool_use_id to null', () => {
const history: ConversationMessage[] = [{ role: 'user', content: 'Test' }];
const result = convertHistoryToMessages(history);
expect(result[0].parent_tool_use_id).toBeNull();
});
it('should normalize string content to blocks', () => {
const history: ConversationMessage[] = [{ role: 'user', content: 'String content' }];
const result = convertHistoryToMessages(history);
expect(result[0].message.content).toEqual([{ type: 'text', text: 'String content' }]);
});
});
});