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 { return { report: { matched: [], reqOnly: [], prototypeOnly: [], 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: '实现拖拽排序', description: '实现范围:支持列表拖拽调整顺序。验收点:拖拽后顺序保持一致。', taskTypeName: '前端交互', 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: '拖拽后顺序保存', taskTypeName: '功能测试', 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: '保存拖拽排序结果', description: '实现范围:保存拖拽后的排序结果。验收点:刷新后顺序不丢失。', taskTypeName: '前端交互', 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); }); test('filters adopted drafts by AI task type name even when categoryCode is unknown', () => { const customCategories: TaskCategory[] = [ ...categories, { id: 'cat-ai-name-card', code: '人员名片交互', name: '人员名片交互', group: 'development', sortOrder: 3, isSystem: false, }, ]; const existingDevTasks = [ { id: 'task-1', title: '实现同名员工名片入口', categoryId: 'cat-ai-name-card', references: [{ type: 'prototype_note', id: 'QY0019', label: 'QY0019' }], }, ] as DevTask[]; const result = filterDuplicateDecomposeDrafts( makeResult({ devTaskDrafts: [ { title: '实现同名员工名片入口', description: '实现范围:姓名后展示名片入口。验收点:点击后展示组织详情。', taskTypeName: '人员名片交互', categoryCode: 'ai_unknown', priority: 'P2', aiEstimateHours: 0.5, references: [{ type: 'prototype_note', id: 'QY0019', label: 'QY0019' }], }, ], }), { existingDevTasks, existingTestCases: [], categories: customCategories, requirements }, ); assert.equal(result.removedDevTaskCount, 1); assert.equal(result.result.devTaskDrafts.length, 0); });