feat(版本): 优化概览与只读状态
关键改动: - 增加需求排序和版本只读状态规则及测试 - 完善版本概览阶段耗时、项目页和工作台展示 - 优化小宝预警请求节流、建议状态和风险过滤 Co-Authored-By: Codex GPT-5 <codex@openai.com>
This commit is contained in:
@@ -6,6 +6,10 @@ import {
|
||||
calcPersonalEffortRanking,
|
||||
calcStageEffortMetrics,
|
||||
calcVersionOverviewEffortTotals,
|
||||
buildVersionTimelineSummary,
|
||||
formatVersionOverviewDateTime,
|
||||
getVersionCardDefaultExpanded,
|
||||
mergeStageProgressWithEffort,
|
||||
} from './version-overview';
|
||||
import type { VersionPlan } from './version-plan';
|
||||
import type { DevTask } from './dev-task';
|
||||
@@ -131,6 +135,60 @@ test('calcStageEffortMetrics returns actual hours and AI estimates per stage', (
|
||||
assert.equal(metrics.bug.actualHours, 0.5);
|
||||
});
|
||||
|
||||
test('mergeStageProgressWithEffort keeps progress state and adds stage effort fields', () => {
|
||||
const metrics = calcStageEffortMetrics({
|
||||
plans: [],
|
||||
devTasks: [
|
||||
devTask({
|
||||
actualStartAt: '2026-06-24T09:00:00',
|
||||
actualEndAt: '2026-06-24T14:00:00',
|
||||
estimateHours: 4.5,
|
||||
aiEstimateHours: 3.25,
|
||||
}),
|
||||
],
|
||||
testCases: [
|
||||
testCase({
|
||||
startedAt: '2026-06-25T09:00:00',
|
||||
completedAt: '2026-06-25T11:00:00',
|
||||
estimateHours: 2.25,
|
||||
aiEstimateHours: 1.5,
|
||||
}),
|
||||
],
|
||||
bugs: [],
|
||||
});
|
||||
|
||||
const merged = mergeStageProgressWithEffort(
|
||||
{
|
||||
dev: { percent: 50, status: 'active' },
|
||||
testing: { percent: 100, status: 'done' },
|
||||
},
|
||||
metrics,
|
||||
);
|
||||
|
||||
assert.equal(merged.dev.percent, 50);
|
||||
assert.equal(merged.dev.status, 'active');
|
||||
assert.equal(merged.dev.actualHours, 4);
|
||||
assert.equal(merged.dev.estimateHours, 4.5);
|
||||
assert.equal(merged.dev.aiEstimateHours, 3.25);
|
||||
assert.equal(merged.dev.showEstimates, true);
|
||||
assert.equal(merged.testing.percent, 100);
|
||||
assert.equal(merged.testing.status, 'done');
|
||||
assert.equal(merged.testing.actualHours, 2);
|
||||
assert.equal(merged.testing.estimateHours, 2.25);
|
||||
assert.equal(merged.testing.aiEstimateHours, 1.5);
|
||||
assert.equal(merged.requirement.percent, 0);
|
||||
assert.equal(merged.requirement.status, 'idle');
|
||||
assert.equal(merged.requirement.actualHours, 0);
|
||||
});
|
||||
|
||||
test('getVersionCardDefaultExpanded expands only in-progress versions by default', () => {
|
||||
assert.equal(getVersionCardDefaultExpanded('developing'), true);
|
||||
assert.equal(getVersionCardDefaultExpanded('released'), false);
|
||||
assert.equal(getVersionCardDefaultExpanded('closed'), false);
|
||||
assert.equal(getVersionCardDefaultExpanded('paused'), false);
|
||||
assert.equal(getVersionCardDefaultExpanded('planned'), false);
|
||||
});
|
||||
|
||||
test('calcStageEffortMetrics uses updatedAt for terminal test cases missing completedAt', () => {
|
||||
const metrics = calcStageEffortMetrics({
|
||||
plans: [],
|
||||
@@ -188,6 +246,58 @@ test('calcVersionOverviewEffortTotals sums actual hours and overtime records sep
|
||||
assert.equal(totals.overtimeHours, 3.3);
|
||||
});
|
||||
|
||||
test('buildVersionTimelineSummary uses the same timing sources as version detail', () => {
|
||||
const summary = buildVersionTimelineSummary({
|
||||
status: 'closed',
|
||||
startDate: '2026-06-20',
|
||||
expectedReleaseDate: '2026-06-27',
|
||||
releaseDate: '2026-06-30T10:00:00',
|
||||
plans: [
|
||||
plan({
|
||||
type: 'research',
|
||||
actualStartAt: '2026-06-22T09:00:00',
|
||||
completedAt: '2026-06-22T18:00:00',
|
||||
}),
|
||||
],
|
||||
devTasks: [
|
||||
devTask({
|
||||
actualStartAt: '2026-06-23T09:00:00',
|
||||
actualEndAt: '2026-06-23T12:00:00',
|
||||
}),
|
||||
],
|
||||
testCases: [
|
||||
testCase({
|
||||
startedAt: '2026-06-24T09:00:00',
|
||||
completedAt: '2026-06-24T11:00:00',
|
||||
}),
|
||||
],
|
||||
bugs: [
|
||||
bug({
|
||||
status: 'closed',
|
||||
createdAt: '2026-06-25T10:00:00',
|
||||
resolvedAt: '2026-06-25T16:00:00',
|
||||
closedAt: undefined,
|
||||
updatedAt: '2026-06-25T17:00:00',
|
||||
}),
|
||||
],
|
||||
now: new Date('2026-06-26T18:00:00'),
|
||||
});
|
||||
|
||||
assert.equal(summary.actualStartIso, '2026-06-22T09:00:00');
|
||||
assert.equal(summary.expectedReleaseIso, '2026-06-27');
|
||||
assert.equal(summary.actualReleaseIso, '2026-06-30T10:00:00');
|
||||
assert.equal(summary.actualEndIso, '2026-06-25T16:00:00');
|
||||
assert.equal(summary.isTerminalVersion, true);
|
||||
assert.equal(summary.actualHours, 30);
|
||||
assert.equal(summary.overdueDays, 3);
|
||||
});
|
||||
|
||||
test('formatVersionOverviewDateTime matches the version detail display format', () => {
|
||||
assert.equal(formatVersionOverviewDateTime('2026-06-22T09:30:00'), '2026-06-22 09:30');
|
||||
assert.equal(formatVersionOverviewDateTime('2026-06-27'), '2026-06-27');
|
||||
assert.equal(formatVersionOverviewDateTime(null), '-');
|
||||
});
|
||||
|
||||
test('calcPersonalEffortRanking includes bug work and sorts by total hours', () => {
|
||||
const overtimeRecords: OvertimeRecord[] = [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user