import test from 'node:test'; import assert from 'node:assert/strict'; import type { Bug } from './bug'; import type { DevTask } from './dev-task'; import type { TestCase } from './test-case'; import type { VersionPlan } from './version-plan'; import { makeBugStatusActivity, makeDevTaskStatusActivity, makeProgressNoteActivity, makeTestCaseStatusActivity, makeVersionPlanCompletedActivity, makeVersionPlanRequirementProgressActivity, } from './work-activity-factory'; function devTask(patch: Partial = {}): DevTask { return { id: 'task-1', taskNo: 'DEV-001', requirementId: 'req-1', title: '实现登录接口', categoryId: 'cat-1', assigneeId: '张三', priority: 'P2', expectedStartAt: '2026-06-26T01:00', expectedEndAt: '2026-06-26T09:00', status: 'todo', isBlocked: false, createdBy: '张三', createdAt: '2026-06-26T01:00:00.000Z', updatedAt: '2026-06-26T01:00:00.000Z', ...patch, }; } function plan(patch: Partial = {}): VersionPlan { return { id: 'plan-1', versionId: 'version-1', type: 'product', title: '提交产品方案', owner: '张三', startTime: '2026-06-26T01:00', endTime: '2026-06-26T09:00', status: 'in_progress', createdAt: '2026-06-26', addedBy: '张三', ...patch, }; } function bug(patch: Partial = {}): Bug { return { id: 'bug-1', bugNo: 'BUG-001', versionId: 'version-1', testCaseId: 'case-1', title: '修复菜单错位', description: '菜单在窄屏错位', severity: 'major', priority: 'P1', reportedBy: '李四', assigneeId: '张三', status: 'fixing', createdAt: '2026-06-26T01:00:00.000Z', updatedAt: '2026-06-26T01:00:00.000Z', ...patch, }; } function testCase(patch: Partial = {}): TestCase { return { id: 'tc-1', caseNo: 'TC-001', versionId: 'version-1', title: '验证登录流程', categoryId: 'cat-test', priority: 'P2', assigneeId: '张三', status: 'pending', createdBy: '张三', createdAt: '2026-06-26T01:00:00.000Z', updatedAt: '2026-06-26T01:00:00.000Z', ...patch, }; } test('makeDevTaskStatusActivity maps started and submitted actions', () => { const started = makeDevTaskStatusActivity(devTask(), 'todo', 'in_progress', '张三'); const submitted = makeDevTaskStatusActivity(devTask({ status: 'testing' }), 'testing', 'submitted', '张三'); assert.equal(started?.action, 'dev_task_started'); assert.equal(started?.category, 'progress'); assert.equal(started?.summary, '开始开发:实现登录接口'); assert.equal(submitted?.action, 'dev_task_submitted'); assert.equal(submitted?.category, 'delivery'); assert.equal(submitted?.summary, '已提测开发任务:实现登录接口'); }); test('makeVersionPlanCompletedActivity marks product plan completion as delivery', () => { const activity = makeVersionPlanCompletedActivity(plan(), '张三'); assert.equal(activity.action, 'version_plan_completed'); assert.equal(activity.category, 'delivery'); assert.equal(activity.sourceType, 'version_plan'); assert.equal(activity.summary, '完成产品方案:提交产品方案'); }); test('makeVersionPlanRequirementProgressActivity records partial requirement coverage details', () => { const activity = makeVersionPlanRequirementProgressActivity(plan({ type: 'ui', title: '绘制个人中心' }), { id: 'log-1', type: 'requirement_progress', createdAt: '2026-06-30T03:00:00.000Z', actor: '张三', title: 'QY-001 个人中心更新为部分完成', detail: '已完成:头像和基本信息\n剩余:安全设置入口', requirementId: 'req-1', requirementCode: 'QY-001', requirementTitle: '个人中心', coverageStatus: 'partial', completedContent: '头像和基本信息', remainingContent: '安全设置入口', workStartedAt: '2026-06-30T01:30:00.000Z', }); assert.equal(activity?.action, 'version_plan_requirement_progress'); assert.equal(activity?.category, 'progress'); assert.equal(activity?.sourceType, 'version_plan'); assert.equal(activity?.sourceId, 'plan-1'); assert.equal(activity?.occurredAt, '2026-06-30T03:00:00.000Z'); assert.equal(activity?.summary, '推进UI设计需求:QY-001 个人中心(部分完成)'); assert.equal(activity?.metadata?.completedContent, '头像和基本信息'); assert.equal(activity?.metadata?.remainingContent, '安全设置入口'); assert.equal(activity?.metadata?.workStartedAt, '2026-06-30T01:30:00.000Z'); }); test('makeProgressNoteActivity records required next start time', () => { const activity = makeProgressNoteActivity({ actorId: '张三', sourceType: 'dev_task', sourceId: 'task-1', title: '实现登录接口', note: '完成登录接口联调', blocker: '等待安全评审', helperId: '李四', delayRisk: '可能延期半天', nextStartAt: '2026-07-02T01:30:00.000Z', }); assert.equal(activity.action, 'progress_note_added'); assert.equal(activity.category, 'risk'); assert.equal(activity.metadata?.note, '完成登录接口联调'); assert.equal(activity.metadata?.blocker, '等待安全评审'); assert.equal(activity.metadata?.helperId, '李四'); assert.equal(activity.metadata?.delayRisk, '可能延期半天'); assert.equal(activity.metadata?.nextStartAt, '2026-07-02T01:30:00.000Z'); }); test('makeBugStatusActivity maps fixing and fixed actions', () => { const fixing = makeBugStatusActivity(bug({ status: 'open' }), 'open', 'fixing', '张三'); const fixed = makeBugStatusActivity(bug(), 'fixing', 'fixed', '张三'); assert.equal(fixing?.action, 'bug_fixing'); assert.equal(fixing?.category, 'progress'); assert.equal(fixing?.summary, '开始修复 Bug:修复菜单错位'); assert.equal(fixed?.action, 'bug_fixed'); assert.equal(fixed?.category, 'delivery'); assert.equal(fixed?.summary, '已修复 Bug:修复菜单错位'); }); test('makeTestCaseStatusActivity maps running and passed actions', () => { const running = makeTestCaseStatusActivity(testCase(), 'pending', 'running', '张三'); const passed = makeTestCaseStatusActivity(testCase({ status: 'running' }), 'running', 'passed', '张三'); assert.equal(running?.action, 'test_case_started'); assert.equal(running?.category, 'progress'); assert.equal(running?.summary, '开始测试:验证登录流程'); assert.equal(passed?.action, 'test_case_passed'); assert.equal(passed?.category, 'delivery'); assert.equal(passed?.summary, '测试通过:验证登录流程'); });