Files
ftb-project-management/apps/web/lib/ai-decompose-dedupe.test.ts
2026-06-26 11:01:11 +08:00

139 lines
3.9 KiB
TypeScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { filterDuplicateDecomposeDrafts } from './ai-decompose-dedupe';
import type { AgentDecomposeResult } from '@ftb/shared';
import type { DevTask } from './dev-task';
import type { TestCase } from './test-case';
import type { TaskCategory } from './task-category';
const categories: TaskCategory[] = [
{
id: 'cat-frontend',
code: 'frontend_interaction',
name: '前端交互',
group: 'development',
sortOrder: 1,
isSystem: true,
},
{
id: 'cat-test-functional',
code: 'test_functional',
name: '功能测试',
group: 'testing',
sortOrder: 2,
isSystem: true,
},
];
const requirements = [{ id: 'req-1', code: 'REQ001' }];
function makeResult(patch: Partial<AgentDecomposeResult>): AgentDecomposeResult {
return {
report: { matched: [], reqOnly: [], noteOnly: [], ambiguous: [] },
devTaskDrafts: [],
testCaseDrafts: [],
...patch,
};
}
test('filters dev task drafts already adopted into existing tasks', () => {
const existingDevTasks = [
{
id: 'task-1',
title: '实现拖拽排序',
categoryId: 'cat-frontend',
references: [
{ type: 'requirement', id: 'req-1', label: 'REQ001 拖拽排序' },
{ type: 'prototype_note', id: 'QY0001', label: 'QY0001' },
],
},
] as DevTask[];
const result = filterDuplicateDecomposeDrafts(
makeResult({
devTaskDrafts: [
{
title: '实现拖拽排序',
categoryCode: 'frontend_interaction',
priority: 'P2',
aiEstimateHours: 0.25,
references: [
{ type: 'requirement', id: 'REQ001', label: 'REQ001 拖拽排序' },
{ type: 'prototype_note', id: 'QY0001', label: 'QY0001' },
],
},
],
}),
{ existingDevTasks, existingTestCases: [], categories, requirements },
);
assert.equal(result.removedDevTaskCount, 1);
assert.equal(result.result.devTaskDrafts.length, 0);
});
test('filters test case drafts already adopted into existing test cases', () => {
const existingTestCases = [
{
id: 'tc-1',
title: '验证拖拽排序成功',
categoryId: 'cat-test-functional',
references: [
{ type: 'requirement', id: 'req-1', label: 'REQ001 拖拽排序' },
{ type: 'prototype_note', id: 'QY0001', label: 'QY0001' },
],
},
] as TestCase[];
const result = filterDuplicateDecomposeDrafts(
makeResult({
testCaseDrafts: [
{
title: '验证拖拽排序成功',
description: '拖拽后顺序保存',
categoryCode: 'test_functional',
priority: 'P2',
aiEstimateHours: 0.2,
references: [
{ type: 'requirement', id: 'REQ001', label: 'REQ001 拖拽排序' },
{ type: 'prototype_note', id: 'QY0001', label: 'QY0001' },
],
},
],
}),
{ existingDevTasks: [], existingTestCases, categories, requirements },
);
assert.equal(result.removedTestCaseCount, 1);
assert.equal(result.result.testCaseDrafts.length, 0);
});
test('keeps drafts with same references but different normalized title', () => {
const existingDevTasks = [
{
id: 'task-1',
title: '实现拖拽排序',
categoryId: 'cat-frontend',
references: [{ type: 'prototype_note', id: 'QY0001', label: 'QY0001' }],
},
] as DevTask[];
const result = filterDuplicateDecomposeDrafts(
makeResult({
devTaskDrafts: [
{
title: '保存拖拽排序结果',
categoryCode: 'frontend_interaction',
priority: 'P2',
aiEstimateHours: 0.5,
references: [{ type: 'prototype_note', id: 'QY0001', label: 'QY0001' }],
},
],
}),
{ existingDevTasks, existingTestCases: [], categories, requirements },
);
assert.equal(result.removedDevTaskCount, 0);
assert.equal(result.result.devTaskDrafts.length, 1);
});