172 lines
5.8 KiB
TypeScript
172 lines
5.8 KiB
TypeScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
|
|
import { buildVersionDataScope, buildVersionDataScopeMap } from './version-data-scope';
|
|
import type { Bug } from './bug';
|
|
import type { DevTask } from './dev-task';
|
|
import type { OvertimeRecord } from './overtime';
|
|
import type { Requirement } from './requirement';
|
|
import type { TestCase } from './test-case';
|
|
import type { VersionPlan } from './version-plan';
|
|
|
|
function requirement(id: string, versionId: string | undefined): Requirement {
|
|
return {
|
|
id,
|
|
code: id.toUpperCase(),
|
|
title: `Requirement ${id}`,
|
|
description: '',
|
|
productId: 'product-1',
|
|
projectId: 'project-1',
|
|
versionId,
|
|
sourceType: 'internal',
|
|
sourceTarget: 'product',
|
|
platforms: ['web'],
|
|
typeId: 'type-1',
|
|
status: 'planned',
|
|
priority: 'P1',
|
|
effort: 'M',
|
|
creator: 'PM',
|
|
createdAt: '2026-07-02T09:00:00.000Z',
|
|
};
|
|
}
|
|
|
|
function plan(id: string, versionId: string, type: VersionPlan['type']): VersionPlan {
|
|
return {
|
|
id,
|
|
versionId,
|
|
type,
|
|
title: `Plan ${id}`,
|
|
owner: 'PM',
|
|
startTime: '2026-07-02T09:00:00.000Z',
|
|
endTime: '2026-07-02T18:00:00.000Z',
|
|
status: 'pending',
|
|
createdAt: '2026-07-02T09:00:00.000Z',
|
|
addedBy: 'PM',
|
|
};
|
|
}
|
|
|
|
function devTask(id: string, patch: Partial<DevTask>): DevTask {
|
|
return {
|
|
id,
|
|
taskNo: id.toUpperCase(),
|
|
versionId: undefined,
|
|
requirementId: '',
|
|
title: `Task ${id}`,
|
|
categoryId: 'frontend',
|
|
assigneeId: 'Alice',
|
|
priority: 'P1',
|
|
expectedStartAt: '',
|
|
expectedEndAt: '',
|
|
status: 'todo',
|
|
isBlocked: false,
|
|
createdBy: 'PM',
|
|
createdAt: '2026-07-02T09:00:00.000Z',
|
|
updatedAt: '2026-07-02T09:00:00.000Z',
|
|
...patch,
|
|
};
|
|
}
|
|
|
|
function testCase(id: string, versionId: string): TestCase {
|
|
return {
|
|
id,
|
|
caseNo: id.toUpperCase(),
|
|
versionId,
|
|
title: `Case ${id}`,
|
|
categoryId: 'testing',
|
|
priority: 'P1',
|
|
status: 'pending',
|
|
createdBy: 'QA',
|
|
createdAt: '2026-07-02T09:00:00.000Z',
|
|
updatedAt: '2026-07-02T09:00:00.000Z',
|
|
};
|
|
}
|
|
|
|
function bug(id: string, versionId: string): Bug {
|
|
return {
|
|
id,
|
|
bugNo: id.toUpperCase(),
|
|
versionId,
|
|
testCaseId: 'tc-1',
|
|
title: `Bug ${id}`,
|
|
description: '',
|
|
severity: 'major',
|
|
priority: 'P1',
|
|
reportedBy: 'QA',
|
|
assigneeId: 'Bob',
|
|
status: 'open',
|
|
createdAt: '2026-07-02T09:00:00.000Z',
|
|
updatedAt: '2026-07-02T09:00:00.000Z',
|
|
};
|
|
}
|
|
|
|
function overtime(id: string, versionId: string): OvertimeRecord {
|
|
return {
|
|
id,
|
|
projectId: 'project-1',
|
|
versionId,
|
|
person: 'Alice',
|
|
startTime: '2026-07-02T19:00:00.000Z',
|
|
endTime: '2026-07-02T21:00:00.000Z',
|
|
duration: 2,
|
|
reasonId: 'reason-4',
|
|
createdAt: '2026-07-02T21:00:00.000Z',
|
|
};
|
|
}
|
|
|
|
test('buildVersionDataScope scopes version detail data once', () => {
|
|
const scope = buildVersionDataScope({
|
|
versionId: 'version-1',
|
|
requirements: [requirement('req-1', 'version-1'), requirement('req-2', 'version-2')],
|
|
plans: [plan('plan-1', 'version-1', 'research'), plan('plan-2', 'version-1', 'product'), plan('plan-3', 'version-2', 'ui')],
|
|
devTasks: [
|
|
devTask('dev-direct', { versionId: 'version-1', requirementId: '' }),
|
|
devTask('dev-legacy', { requirementId: 'req-1' }),
|
|
devTask('dev-other', { versionId: 'version-2', requirementId: 'req-2' }),
|
|
],
|
|
testCases: [testCase('tc-1', 'version-1'), testCase('tc-2', 'version-2')],
|
|
bugs: [bug('bug-1', 'version-1'), bug('bug-2', 'version-2')],
|
|
overtimeRecords: [overtime('ot-1', 'version-1'), overtime('ot-2', 'version-2')],
|
|
});
|
|
|
|
assert.deepEqual(scope.requirementIds, ['req-1']);
|
|
assert.deepEqual(scope.plans.map((item) => item.id), ['plan-1', 'plan-2']);
|
|
assert.deepEqual(scope.plansByType.research.map((item) => item.id), ['plan-1']);
|
|
assert.deepEqual(scope.plansByType.product.map((item) => item.id), ['plan-2']);
|
|
assert.deepEqual(scope.devTasks.map((item) => item.id), ['dev-direct', 'dev-legacy']);
|
|
assert.deepEqual(scope.testCases.map((item) => item.id), ['tc-1']);
|
|
assert.deepEqual(scope.bugs.map((item) => item.id), ['bug-1']);
|
|
assert.deepEqual(scope.overtimeRecords.map((item) => item.id), ['ot-1']);
|
|
});
|
|
|
|
test('buildVersionDataScopeMap indexes many versions in one pass', () => {
|
|
const scopeMap = buildVersionDataScopeMap({
|
|
versionIds: ['version-1', 'version-2', 'version-empty'],
|
|
requirements: [
|
|
requirement('req-1', 'version-1'),
|
|
requirement('req-2', 'version-2'),
|
|
requirement('req-outside', 'version-3'),
|
|
],
|
|
plans: [
|
|
plan('plan-1', 'version-1', 'research'),
|
|
plan('plan-2', 'version-2', 'ui'),
|
|
plan('plan-outside', 'version-3', 'product'),
|
|
],
|
|
devTasks: [
|
|
devTask('dev-direct', { versionId: 'version-2', requirementId: 'req-1' }),
|
|
devTask('dev-legacy', { requirementId: 'req-1' }),
|
|
devTask('dev-outside', { requirementId: 'req-outside' }),
|
|
],
|
|
testCases: [testCase('tc-1', 'version-1'), testCase('tc-2', 'version-2'), testCase('tc-outside', 'version-3')],
|
|
bugs: [bug('bug-1', 'version-1'), bug('bug-2', 'version-2'), bug('bug-outside', 'version-3')],
|
|
overtimeRecords: [overtime('ot-1', 'version-1'), overtime('ot-2', 'version-2'), overtime('ot-outside', 'version-3')],
|
|
});
|
|
|
|
assert.deepEqual(scopeMap['version-1'].requirements.map((item) => item.id), ['req-1']);
|
|
assert.deepEqual(scopeMap['version-1'].devTasks.map((item) => item.id), ['dev-legacy']);
|
|
assert.deepEqual(scopeMap['version-2'].requirements.map((item) => item.id), ['req-2']);
|
|
assert.deepEqual(scopeMap['version-2'].devTasks.map((item) => item.id), ['dev-direct']);
|
|
assert.deepEqual(scopeMap['version-2'].plansByType.ui.map((item) => item.id), ['plan-2']);
|
|
assert.deepEqual(scopeMap['version-empty'].requirements, []);
|
|
assert.deepEqual(Object.keys(scopeMap).sort(), ['version-1', 'version-2', 'version-empty']);
|
|
});
|