Files
ftb-project-management/apps/web/lib/work-activity-factory.test.ts
Script Generator 04520bd8c5 feat(版本): 记录计划需求进展活动
关键改动:

- 记录产品/UI 计划需求覆盖进展,并写入工作活动与实体日志

- 日报和小宝预警补充需求进展活动证据

- 调整版本列表与需求覆盖面板展示,并补充测试

Co-Authored-By: Codex GPT-5 <codex@openai.com>
2026-06-30 15:35:36 +08:00

158 lines
5.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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,
makeTestCaseStatusActivity,
makeVersionPlanCompletedActivity,
makeVersionPlanRequirementProgressActivity,
} from './work-activity-factory';
function devTask(patch: Partial<DevTask> = {}): 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> = {}): 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> = {}): 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> = {}): 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: '安全设置入口',
});
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, '安全设置入口');
});
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, '测试通过:验证登录流程');
});