takt/src/__tests__/interactive-summary.test.ts
2026-02-19 13:16:47 +09:00

156 lines
4.6 KiB
TypeScript

/**
* Tests for task history context formatting in interactive summary.
*/
import { describe, expect, it } from 'vitest';
import {
buildSummaryPrompt,
buildSummaryActionOptions,
formatTaskHistorySummary,
type PieceContext,
type SummaryActionLabels,
type TaskHistorySummaryItem,
} from '../features/interactive/interactive.js';
describe('formatTaskHistorySummary', () => {
it('returns empty string when history is empty', () => {
expect(formatTaskHistorySummary([], 'en')).toBe('');
});
it('formats task history with required fields', () => {
const history: TaskHistorySummaryItem[] = [
{
worktreeId: 'wt-1',
status: 'interrupted',
startedAt: '2026-02-18T00:00:00.000Z',
completedAt: 'N/A',
finalResult: 'interrupted',
failureSummary: undefined,
logKey: 'log-1',
},
{
worktreeId: 'wt-2',
status: 'failed',
startedAt: '2026-02-17T00:00:00.000Z',
completedAt: '2026-02-17T00:01:00.000Z',
finalResult: 'failed',
failureSummary: 'Syntax error in test',
logKey: 'log-2',
},
];
const result = formatTaskHistorySummary(history, 'en');
expect(result).toContain('## Task execution history');
expect(result).toContain('Worktree ID: wt-1');
expect(result).toContain('Status: interrupted');
expect(result).toContain('Failure summary: Syntax error in test');
expect(result).toContain('Log key: log-2');
});
it('normalizes empty start/end timestamps to N/A', () => {
const history: TaskHistorySummaryItem[] = [
{
worktreeId: 'wt-3',
status: 'interrupted',
startedAt: '',
completedAt: '',
finalResult: 'interrupted',
failureSummary: undefined,
logKey: 'log-3',
},
];
const result = formatTaskHistorySummary(history, 'en');
expect(result).toContain('Start/End: N/A / N/A');
});
});
describe('buildSummaryPrompt', () => {
it('includes taskHistory context when provided', () => {
const history: TaskHistorySummaryItem[] = [
{
worktreeId: 'wt-1',
status: 'completed',
startedAt: '2026-02-10T00:00:00.000Z',
completedAt: '2026-02-10T00:00:30.000Z',
finalResult: 'completed',
failureSummary: undefined,
logKey: 'log-1',
},
];
const pieceContext: PieceContext = {
name: 'my-piece',
description: 'desc',
pieceStructure: '',
movementPreviews: [],
taskHistory: history,
};
const summary = buildSummaryPrompt(
[{ role: 'user', content: 'Improve parser' }],
false,
'en',
'No transcript',
'Conversation:',
pieceContext,
);
expect(summary).toContain('## Task execution history');
expect(summary).toContain('Worktree ID: wt-1');
expect(summary).toContain('Conversation:');
expect(summary).toContain('User: Improve parser');
});
});
describe('buildSummaryActionOptions', () => {
const labels: SummaryActionLabels = {
execute: 'Execute now',
saveTask: 'Save as Task',
continue: 'Continue editing',
};
it('should include all base actions when no exclude is given', () => {
const options = buildSummaryActionOptions(labels);
const values = options.map((o) => o.value);
expect(values).toEqual(['execute', 'save_task', 'continue']);
});
it('should exclude specified actions', () => {
const options = buildSummaryActionOptions(labels, [], ['execute']);
const values = options.map((o) => o.value);
expect(values).toEqual(['save_task', 'continue']);
expect(values).not.toContain('execute');
});
it('should exclude multiple actions', () => {
const options = buildSummaryActionOptions(labels, [], ['execute', 'continue']);
const values = options.map((o) => o.value);
expect(values).toEqual(['save_task']);
});
it('should handle append and exclude together', () => {
const labelsWithIssue: SummaryActionLabels = {
...labels,
createIssue: 'Create Issue',
};
const options = buildSummaryActionOptions(labelsWithIssue, ['create_issue'], ['execute']);
const values = options.map((o) => o.value);
expect(values).toEqual(['save_task', 'continue', 'create_issue']);
expect(values).not.toContain('execute');
});
it('should return empty exclude by default (backward compatible)', () => {
const options = buildSummaryActionOptions(labels, []);
const values = options.map((o) => o.value);
expect(values).toContain('execute');
expect(values).toContain('save_task');
expect(values).toContain('continue');
});
});