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 { TaskWorklog } from './task-worklog'; import type { VersionPlan } from './version-plan'; import type { WorkActivity } from './work-activity'; import { buildVersionDailyEvidence, buildXiaobaoWorkItems } from './xiaobao-risk-evidence'; function plan(patch: Partial = {}): VersionPlan { return { id: 'plan-1', versionId: 'ver-1', type: 'product', title: 'Product plan', owner: 'pm-1', startTime: '2026-06-20T01:00:00.000Z', endTime: '2026-06-25T10:00:00.000Z', status: 'in_progress', actualStartAt: '2026-06-20T01:00:00.000Z', createdAt: '2026-06-20T01:00:00.000Z', addedBy: 'pm-1', ...patch, }; } function devTask(patch: Partial = {}): DevTask { return { id: 'dev-1', taskNo: 'DEV-001', requirementId: 'req-1', title: 'Build warning panel', categoryId: 'frontend', assigneeId: 'dev-other', priority: 'P1', expectedStartAt: '2026-06-20T01:00:00.000Z', expectedEndAt: '2026-06-26T10:00:00.000Z', status: 'in_progress', isBlocked: false, actualStartAt: '2026-06-20T01:00:00.000Z', createdBy: 'pm-1', createdAt: '2026-06-20T01:00:00.000Z', updatedAt: '2026-06-24T02:00:00.000Z', ...patch, }; } function testCase(patch: Partial = {}): TestCase { return { id: 'tc-1', caseNo: 'TC-001', versionId: 'ver-1', title: 'Verify warning panel', categoryId: 'ui-interaction', priority: 'P2', assigneeId: 'qa-other', status: 'running', startedAt: '2026-06-20T03:00:00.000Z', createdBy: 'qa-other', createdAt: '2026-06-20T01:00:00.000Z', updatedAt: '2026-06-24T02:00:00.000Z', ...patch, }; } function bug(patch: Partial = {}): Bug { return { id: 'bug-1', bugNo: 'BUG-001', versionId: 'ver-1', testCaseId: 'tc-1', title: 'Warning count mismatch', description: 'The count is wrong.', severity: 'major', priority: 'P1', reportedBy: 'qa-other', assigneeId: 'dev-other', status: 'open', createdAt: '2026-06-20T01:00:00.000Z', updatedAt: '2026-06-24T02:00:00.000Z', ...patch, }; } test('buildVersionDailyEvidence groups version activity and detects no activity/no update', () => { const workItems = buildXiaobaoWorkItems({ plans: [plan()], devTasks: [devTask()], testCases: [testCase()], bugs: [bug()], versions: [{ id: 'ver-1', name: 'V1.0', productName: 'FTB', projectName: 'PM' }], requirementVersionMap: new Map([['req-1', 'ver-1']]), }); const activities: WorkActivity[] = [ { id: 'act-delivery', actorId: 'dev-other', date: '2026-06-29', occurredAt: '2026-06-29T02:00:00.000Z', sourceType: 'dev_task', sourceId: 'dev-1', action: 'dev_task_submitted', category: 'delivery', title: 'Build warning panel', summary: 'Submitted development task', }, { id: 'act-risk', actorId: 'qa-other', date: '2026-06-29', occurredAt: '2026-06-29T03:00:00.000Z', sourceType: 'bug', sourceId: 'bug-1', action: 'bug_blocked', category: 'risk', title: 'Warning count mismatch', summary: 'Blocked by missing data', }, ]; const worklogs: TaskWorklog[] = [ { id: 'wl-note', taskId: 'tc-1', userId: 'qa-other', date: '2026-06-29', hours: 1, workContent: 'Continued regression testing.', createdAt: '2026-06-29T04:00:00.000Z', }, ]; const evidence = buildVersionDailyEvidence({ versionId: 'ver-1', workItems, activities, worklogs, now: new Date('2026-06-29T08:00:00.000Z'), }); assert.deepEqual(evidence.todayDeliveries.map((item) => item.id), ['act-delivery']); assert.deepEqual(evidence.todayRisks.map((item) => item.id), ['act-risk']); assert.deepEqual(evidence.progressNotes.map((item) => item.id), ['wl-note']); assert.equal(evidence.recentActivityCount, 3); assert.equal(evidence.lastActivityAt, '2026-06-29T04:00:00.000Z'); assert.ok(evidence.silentRisks?.some((risk) => risk.key === 'no_update' && risk.itemId === 'plan-1')); assert.ok(evidence.silentRisks?.some((risk) => risk.key === 'no_activity' && risk.itemId === 'plan-1')); }); test('buildXiaobaoWorkItems keeps all version work without current-user filtering', () => { const items = buildXiaobaoWorkItems({ plans: [plan({ owner: 'pm-other' })], devTasks: [devTask({ assigneeId: 'dev-other' })], testCases: [testCase({ assigneeId: 'qa-other' })], bugs: [bug({ assigneeId: 'dev-other' })], versions: [{ id: 'ver-1', name: 'V1.0', productName: 'FTB', projectName: 'PM' }], requirementVersionMap: new Map([['req-1', 'ver-1']]), }); assert.deepEqual(items.map((item) => item.id), ['plan-1', 'dev-1', 'tc-1', 'bug-1']); assert.deepEqual(items.map((item) => item.versionId), ['ver-1', 'ver-1', 'ver-1', 'ver-1']); });