feat(版本详情): 完善流程日志与需求覆盖

This commit is contained in:
Script Generator
2026-06-30 11:00:07 +08:00
parent d754585fe0
commit 1cd595c42e
38 changed files with 4123 additions and 237 deletions

View File

@@ -1,7 +1,7 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import type { DevTask } from './dev-task';
import { canStartDevTask, hasDevTaskPlan, needsDevTaskClaim, type DevTask } from './dev-task';
import { applyDevTaskTransition, normalizeDevTaskOnCreate } from './dev-task-workflow';
function task(patch: Partial<DevTask> = {}): DevTask {
@@ -47,6 +47,44 @@ test('todo to in_progress writes actualStartAt from manual click time', () => {
assert.equal(result.patch?.actualStartAt, '2026-06-25T03:30:00.000Z');
});
test('AI dev task without an assignee must be claimed with a plan before starting', () => {
const draft = task({
assigneeId: '',
expectedStartAt: '',
expectedEndAt: '',
aiDraft: true,
});
assert.equal(needsDevTaskClaim(draft), true);
assert.equal(hasDevTaskPlan(draft), false);
assert.equal(canStartDevTask(draft), false);
const result = applyDevTaskTransition(draft, 'in_progress', {
now: new Date('2026-06-25T03:30:00.000Z'),
});
assert.equal(result.ok, false);
});
test('recommended assignee dev task still needs a plan before starting', () => {
const draft = task({
assigneeId: 'Alice',
expectedStartAt: '',
expectedEndAt: '',
aiDraft: true,
});
assert.equal(needsDevTaskClaim(draft), false);
assert.equal(hasDevTaskPlan(draft), false);
assert.equal(canStartDevTask(draft), false);
const result = applyDevTaskTransition(draft, 'in_progress', {
now: new Date('2026-06-25T03:30:00.000Z'),
});
assert.equal(result.ok, false);
});
test('in_progress to testing does not write actualEndAt', () => {
const result = applyDevTaskTransition(task({
status: 'in_progress',
@@ -71,6 +109,21 @@ test('testing to submitted writes actualEndAt', () => {
assert.equal(result.patch?.actualEndAt, '2026-06-25T05:00:00.000Z');
});
test('blocked task cannot be submitted to test until unblocked', () => {
const result = applyDevTaskTransition(task({
status: 'testing',
actualStartAt: '2026-06-25T03:30:00.000Z',
isBlocked: true,
blockReason: '等待接口联调',
}), 'submitted', {
now: new Date('2026-06-25T05:00:00.000Z'),
});
assert.equal(result.ok, false);
assert.equal(result.patch, undefined);
assert.match(result.message || '', /\u963b\u585e/);
});
test('invalid transition is rejected', () => {
const result = applyDevTaskTransition(task(), 'submitted', {
now: new Date('2026-06-25T05:00:00.000Z'),