feat(小宝预警): 调整风险列表布局和导航徽标
This commit is contained in:
@@ -1,7 +1,14 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import type { VersionWithContext } from './derive';
|
||||
import { filterXiaobaoWarningVersions, formatRemainingWork, sanitizeRiskInsight } from './xiaobao-warning-view';
|
||||
import type { XiaobaoVersionRisk } from './xiaobao-risk';
|
||||
import {
|
||||
filterXiaobaoRiskWarnings,
|
||||
filterXiaobaoWarningVersions,
|
||||
formatRemainingWork,
|
||||
getXiaobaoWarningRiskCount,
|
||||
sanitizeRiskInsight,
|
||||
} from './xiaobao-warning-view';
|
||||
|
||||
function version(patch: Partial<VersionWithContext> = {}): VersionWithContext {
|
||||
return {
|
||||
@@ -20,6 +27,49 @@ function version(patch: Partial<VersionWithContext> = {}): VersionWithContext {
|
||||
};
|
||||
}
|
||||
|
||||
function risk(patch: Partial<XiaobaoVersionRisk> = {}): XiaobaoVersionRisk {
|
||||
return {
|
||||
versionId: 'ver-1',
|
||||
versionName: 'V1.0',
|
||||
productId: 'prod-1',
|
||||
productName: 'Product A',
|
||||
projectId: 'proj-1',
|
||||
projectName: 'Project A',
|
||||
riskScore: 68,
|
||||
riskLevel: 'attention',
|
||||
expectedReleaseDate: '2026-07-05',
|
||||
confidence: 80,
|
||||
confidenceLevel: 'high',
|
||||
delayDays: 0,
|
||||
remainingWorkHours: 8,
|
||||
reasons: [],
|
||||
silentRisks: [],
|
||||
signals: {
|
||||
unfinishedCount: 1,
|
||||
openBugCount: 0,
|
||||
criticalBugCount: 0,
|
||||
failedTestCount: 0,
|
||||
blockedCount: 0,
|
||||
silentRiskCount: 0,
|
||||
},
|
||||
currentSnapshot: {
|
||||
versionId: 'ver-1',
|
||||
date: '2026-06-30',
|
||||
riskScore: 68,
|
||||
riskLevel: 'attention',
|
||||
openBugCount: 0,
|
||||
criticalBugCount: 0,
|
||||
failedTestCount: 0,
|
||||
blockedCount: 0,
|
||||
silentRiskCount: 0,
|
||||
confidence: 80,
|
||||
createdAt: '2026-06-30T10:00:00.000Z',
|
||||
},
|
||||
trend: { direction: 'flat', delta: 0, summary: 'Risk is stable.', pattern: 'stable' },
|
||||
...patch,
|
||||
} as XiaobaoVersionRisk;
|
||||
}
|
||||
|
||||
test('filterXiaobaoWarningVersions lets managers see every unfinished version', () => {
|
||||
const result = filterXiaobaoWarningVersions(
|
||||
[
|
||||
@@ -46,6 +96,38 @@ test('filterXiaobaoWarningVersions limits non-managers to versions where they ar
|
||||
assert.deepEqual(result.map((item) => item.id), ['ver-1']);
|
||||
});
|
||||
|
||||
test('filterXiaobaoRiskWarnings hides on_track risks and badge count follows visible risks', () => {
|
||||
const risks = [
|
||||
risk({ versionId: 'ver-1', riskLevel: 'on_track', riskScore: 10 }),
|
||||
risk({ versionId: 'ver-2', riskLevel: 'attention', riskScore: 38 }),
|
||||
risk({ versionId: 'ver-3', riskLevel: 'blocked', riskScore: 100 }),
|
||||
];
|
||||
|
||||
assert.deepEqual(filterXiaobaoRiskWarnings(risks).map((item) => item.versionId), ['ver-2', 'ver-3']);
|
||||
assert.equal(getXiaobaoWarningRiskCount(risks), 2);
|
||||
});
|
||||
|
||||
test('filterXiaobaoRiskWarnings filters by product project and risk tier', () => {
|
||||
const risks = [
|
||||
risk({ versionId: 'ver-1', productId: 'prod-1', projectId: 'proj-1', riskLevel: 'attention', riskScore: 38 }),
|
||||
risk({ versionId: 'ver-2', productId: 'prod-1', projectId: 'proj-2', riskLevel: 'likely_delayed', riskScore: 88 }),
|
||||
risk({ versionId: 'ver-3', productId: 'prod-2', projectId: 'proj-3', riskLevel: 'blocked', riskScore: 100 }),
|
||||
];
|
||||
|
||||
assert.deepEqual(
|
||||
filterXiaobaoRiskWarnings(risks, { productId: 'prod-1' }).map((item) => item.versionId),
|
||||
['ver-1', 'ver-2'],
|
||||
);
|
||||
assert.deepEqual(
|
||||
filterXiaobaoRiskWarnings(risks, { productId: 'prod-1', projectId: 'proj-2' }).map((item) => item.versionId),
|
||||
['ver-2'],
|
||||
);
|
||||
assert.deepEqual(
|
||||
filterXiaobaoRiskWarnings(risks, { riskFilter: 'high' }).map((item) => item.versionId),
|
||||
['ver-2', 'ver-3'],
|
||||
);
|
||||
});
|
||||
|
||||
test('formatRemainingWork keeps hours and adds work-day conversion', () => {
|
||||
assert.equal(formatRemainingWork(0), '0h / 0天');
|
||||
assert.equal(formatRemainingWork(8), '8h / 1天');
|
||||
|
||||
Reference in New Issue
Block a user