import test from 'node:test'; import assert from 'node:assert/strict'; import { getPlanCompletionState, hasPlanResult } from './version-plan-workflow'; import type { VersionPlan } from './version-plan'; function plan(patch: Partial): VersionPlan { return { id: 'plan-1', versionId: 'version-1', type: 'product', title: '产品方案', owner: 'PM', startTime: '2026-06-25T09:00', endTime: '2026-06-25T18:00', status: 'in_progress', linkedRequirementIds: ['r1'], completedRequirementIds: [], createdAt: '2026-06-25', addedBy: 'PM', ...patch, }; } test('does not allow research result submission when subtasks are incomplete', () => { const state = getPlanCompletionState(plan({ type: 'research', tasks: [{ id: 'task-1', title: '调研方向', status: 'pending' }], linkedRequirementIds: [], })); assert.equal(state.canSubmitResult, false); assert.ok(state.missingReasons.includes('子任务未全部完成')); }); test('requires product requirement coverage when linked requirements exist', () => { const state = getPlanCompletionState(plan({})); assert.equal(state.canSubmitResult, false); assert.ok(state.missingReasons.includes('关联需求未全部覆盖')); }); test('allows product result submission after coverage is complete without task checklist', () => { const state = getPlanCompletionState(plan({ completedRequirementIds: ['r1'], })); assert.equal(state.canSubmitResult, true); assert.equal(state.canComplete, false); }); test('allows completion only after result exists', () => { const state = getPlanCompletionState(plan({ completedRequirementIds: ['r1'], resultType: 'link', resultTitle: '原型', resultUrl: 'https://example.com/prototype', })); assert.equal(state.canComplete, true); }); test('ui plan does not require task checklist', () => { const state = getPlanCompletionState(plan({ type: 'ui', completedRequirementIds: ['r1'], })); assert.equal(state.canSubmitResult, true); }); test('research requires tasks and result but not requirement coverage', () => { const state = getPlanCompletionState(plan({ type: 'research', tasks: [{ id: 'task-1', title: '调研', status: 'completed' }], linkedRequirementIds: ['r1'], completedRequirementIds: [], resultType: 'file', resultTitle: '调研报告', resultFileName: 'report.pdf', resultFileData: 'data:application/pdf;base64,abc', })); assert.equal(state.canComplete, true); }); test('detects link and file result payloads', () => { assert.equal(hasPlanResult({ resultType: 'link', resultTitle: '原型', resultUrl: 'https://example.com' }), true); assert.equal(hasPlanResult({ resultType: 'file', resultTitle: '文件', resultFileName: 'a.pdf', resultFileData: 'data:pdf' }), true); assert.equal(hasPlanResult({ resultType: 'link', resultTitle: '原型' }), false); });