refactor(data): 收口关系表运行时数据源
Some checks failed
Deploy Production / Build, push, deploy, verify (push) Has been cancelled
Some checks failed
Deploy Production / Build, push, deploy, verify (push) Has been cancelled
- 移除已迁移业务 AppData 运行时 fallback,改走领域 API 和关系表快读 - 补齐需求产品负责人、版本计划任务 JSON 和成员 username 回填迁移 - 统一治理字典入口,并补充 AI provider、数据源契约和领域服务测试 Co-Authored-By: Codex GPT-5 <codex@openai.com>
This commit is contained in:
@@ -36,6 +36,22 @@ test('sortPlansNewestFirst places newly created plans before older plans', () =>
|
||||
assert.deepEqual(plans.map((item) => item.id), ['plan-100', 'manual-old', 'plan-300']);
|
||||
});
|
||||
|
||||
test('calcTotalDuration follows overview actual-duration display for short plans', () => {
|
||||
const calcTotalDuration = (versionPlan as any).calcTotalDuration as undefined | ((plans: VersionPlan[]) => string);
|
||||
assert.equal(typeof calcTotalDuration, 'function');
|
||||
|
||||
assert.equal(calcTotalDuration!([
|
||||
plan({
|
||||
type: 'product',
|
||||
startTime: '2026-06-22T09:00:00',
|
||||
endTime: '2026-06-22T10:00:00',
|
||||
status: 'completed',
|
||||
actualStartAt: '2026-06-22T09:00:00',
|
||||
completedAt: '2026-06-22T10:00:00',
|
||||
}),
|
||||
]), '1h(0.04天)');
|
||||
});
|
||||
|
||||
test('collects logs across plans with plan context and newest first', () => {
|
||||
const getPlanLogsForPlans = (versionPlan as any).getPlanLogsForPlans as undefined | ((plans: VersionPlan[]) => Array<{
|
||||
id: string;
|
||||
@@ -210,6 +226,112 @@ test('starts requirement coverage work while preserving existing progress', () =
|
||||
assert.equal(next.requirementCoverage?.[0]?.updatedBy, 'PM');
|
||||
});
|
||||
|
||||
test('merges stale requirement coverage patches without dropping current sessions', () => {
|
||||
const mergeVersionPlanPatch = (versionPlan as any).mergeVersionPlanPatch as undefined | ((
|
||||
current: VersionPlan,
|
||||
patch: Partial<VersionPlan>,
|
||||
) => Partial<VersionPlan>);
|
||||
assert.equal(typeof mergeVersionPlanPatch, 'function');
|
||||
|
||||
const current = plan({
|
||||
requirementCoverage: [
|
||||
{
|
||||
requirementId: 'r1',
|
||||
status: 'not_started',
|
||||
currentWorkStartedAt: '2026-06-29T09:30:00.000Z',
|
||||
updatedAt: '2026-06-29T09:30:00.000Z',
|
||||
updatedBy: 'PM',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const merged = mergeVersionPlanPatch!(current, {
|
||||
requirementCoverage: [
|
||||
{
|
||||
requirementId: 'r2',
|
||||
status: 'not_started',
|
||||
currentWorkStartedAt: '2026-06-29T10:00:00.000Z',
|
||||
updatedAt: '2026-06-29T10:00:00.000Z',
|
||||
updatedBy: 'PM',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
merged.requirementCoverage?.map((item) => [item.requirementId, item.currentWorkStartedAt]),
|
||||
[
|
||||
['r2', '2026-06-29T10:00:00.000Z'],
|
||||
['r1', '2026-06-29T09:30:00.000Z'],
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
test('merged requirement coverage patches preserve legacy completed ids outside the patch', () => {
|
||||
const mergeVersionPlanPatch = (versionPlan as any).mergeVersionPlanPatch as undefined | ((
|
||||
current: VersionPlan,
|
||||
patch: Partial<VersionPlan>,
|
||||
) => Partial<VersionPlan>);
|
||||
assert.equal(typeof mergeVersionPlanPatch, 'function');
|
||||
|
||||
const merged = mergeVersionPlanPatch!(plan({
|
||||
linkedRequirementIds: ['r1', 'r2'],
|
||||
completedRequirementIds: ['r1'],
|
||||
}), {
|
||||
requirementCoverage: [
|
||||
{
|
||||
requirementId: 'r2',
|
||||
status: 'not_started',
|
||||
currentWorkStartedAt: '2026-06-29T10:00:00.000Z',
|
||||
updatedAt: '2026-06-29T10:00:00.000Z',
|
||||
updatedBy: 'PM',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
assert.deepEqual(merged.completedRequirementIds?.sort(), ['r1']);
|
||||
});
|
||||
|
||||
test('merges stale research direction patches without dropping current sessions', () => {
|
||||
const mergeVersionPlanPatch = (versionPlan as any).mergeVersionPlanPatch as undefined | ((
|
||||
current: VersionPlan,
|
||||
patch: Partial<VersionPlan>,
|
||||
) => Partial<VersionPlan>);
|
||||
assert.equal(typeof mergeVersionPlanPatch, 'function');
|
||||
|
||||
const current = plan({
|
||||
type: 'research',
|
||||
tasks: [
|
||||
{
|
||||
id: 'task-1',
|
||||
title: '竞品分析',
|
||||
status: 'in_progress',
|
||||
currentWorkStartedAt: '2026-06-29T09:30:00.000Z',
|
||||
},
|
||||
{ id: 'task-2', title: '用户访谈', status: 'pending' },
|
||||
],
|
||||
});
|
||||
|
||||
const merged = mergeVersionPlanPatch!(current, {
|
||||
tasks: [
|
||||
{ id: 'task-1', title: '竞品分析', status: 'pending' },
|
||||
{
|
||||
id: 'task-2',
|
||||
title: '用户访谈',
|
||||
status: 'in_progress',
|
||||
currentWorkStartedAt: '2026-06-29T10:00:00.000Z',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
merged.tasks?.map((item) => [item.id, item.status, item.currentWorkStartedAt]),
|
||||
[
|
||||
['task-1', 'in_progress', '2026-06-29T09:30:00.000Z'],
|
||||
['task-2', 'in_progress', '2026-06-29T10:00:00.000Z'],
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
test('validates requirement coverage record drafts by started work session', () => {
|
||||
const canSaveRequirementCoverageDraft = (versionPlan as any).canSaveRequirementCoverageDraft as undefined | ((
|
||||
status: string,
|
||||
|
||||
Reference in New Issue
Block a user