merge: 合并小宝预警到 master
# Conflicts: # apps/web/lib/xiaobao-risk-trend.test.ts # apps/web/lib/xiaobao-risk.ts # docs/decisions.md
This commit is contained in:
@@ -3,7 +3,7 @@ import assert from 'node:assert/strict';
|
||||
|
||||
import type { Bug } from './bug';
|
||||
import { calcXiaobaoVersionRisk } from './xiaobao-risk';
|
||||
import { buildRiskSignature, summarizeRiskTrend } from './xiaobao-risk-trend';
|
||||
import { buildRiskSignature, findLatestDailySnapshot, shouldSaveRiskSnapshot, summarizeRiskTrend } from './xiaobao-risk-trend';
|
||||
import type { XiaobaoRiskSnapshot } from './xiaobao-risk-trend';
|
||||
|
||||
function snapshot(patch: Partial<XiaobaoRiskSnapshot>): XiaobaoRiskSnapshot {
|
||||
@@ -41,6 +41,45 @@ test('buildRiskSignature changes when score and bug counts change', () => {
|
||||
assert.notEqual(base, changed);
|
||||
});
|
||||
|
||||
test('buildRiskSignature changes when critical bug count changes without open bug count change', () => {
|
||||
const base = buildRiskSignature(snapshot({ openBugCount: 2, criticalBugCount: 0 }));
|
||||
const changed = buildRiskSignature(snapshot({ openBugCount: 2, criticalBugCount: 1 }));
|
||||
|
||||
assert.notEqual(base, changed);
|
||||
});
|
||||
|
||||
test('findLatestDailySnapshot returns latest same-day snapshot for a version', () => {
|
||||
const latest = findLatestDailySnapshot([
|
||||
snapshot({ versionId: 'ver-1', date: '2026-06-29', riskScore: 40, createdAt: '2026-06-29T09:00:00.000Z' }),
|
||||
snapshot({ versionId: 'ver-1', date: '2026-06-29', riskScore: 45, createdAt: '2026-06-29T10:00:00.000Z' }),
|
||||
snapshot({ versionId: 'ver-1', date: '2026-06-28', riskScore: 70, createdAt: '2026-06-28T10:00:00.000Z' }),
|
||||
snapshot({ versionId: 'ver-2', date: '2026-06-29', riskScore: 90, createdAt: '2026-06-29T11:00:00.000Z' }),
|
||||
], 'ver-1', '2026-06-29');
|
||||
|
||||
assert.equal(latest?.riskScore, 45);
|
||||
});
|
||||
|
||||
test('shouldSaveRiskSnapshot skips small same-day changes inside throttle window', () => {
|
||||
const previous = snapshot({ date: '2026-06-29', riskScore: 40, createdAt: '2026-06-29T10:00:00.000Z' });
|
||||
const current = snapshot({ date: '2026-06-29', riskScore: 43, createdAt: '2026-06-29T10:03:00.000Z' });
|
||||
|
||||
assert.equal(shouldSaveRiskSnapshot(current, previous, new Date('2026-06-29T10:03:00.000Z')), false);
|
||||
});
|
||||
|
||||
test('shouldSaveRiskSnapshot saves material signal changes immediately', () => {
|
||||
const previous = snapshot({ date: '2026-06-29', riskScore: 40, criticalBugCount: 0, createdAt: '2026-06-29T10:00:00.000Z' });
|
||||
const current = snapshot({ date: '2026-06-29', riskScore: 41, criticalBugCount: 1, createdAt: '2026-06-29T10:02:00.000Z' });
|
||||
|
||||
assert.equal(shouldSaveRiskSnapshot(current, previous, new Date('2026-06-29T10:02:00.000Z')), true);
|
||||
});
|
||||
|
||||
test('shouldSaveRiskSnapshot saves minor signature changes after throttle window', () => {
|
||||
const previous = snapshot({ date: '2026-06-29', riskScore: 40, createdAt: '2026-06-29T10:00:00.000Z' });
|
||||
const current = snapshot({ date: '2026-06-29', riskScore: 43, createdAt: '2026-06-29T10:12:00.000Z' });
|
||||
|
||||
assert.equal(shouldSaveRiskSnapshot(current, previous, new Date('2026-06-29T10:12:00.000Z')), true);
|
||||
});
|
||||
|
||||
test('calcXiaobaoVersionRisk uses all open bugs in the current trend snapshot signature', () => {
|
||||
const now = new Date('2026-07-02T01:00:00.000Z');
|
||||
const risk = calcXiaobaoVersionRisk({
|
||||
@@ -59,19 +98,10 @@ test('calcXiaobaoVersionRisk uses all open bugs in the current trend snapshot si
|
||||
|
||||
assert.equal(risk.signals.openBugCount, 1);
|
||||
assert.equal(risk.signals.criticalBugCount, 0);
|
||||
assert.equal(currentSignature, buildRiskSignature({
|
||||
versionId: risk.versionId,
|
||||
date: now.toISOString().slice(0, 10),
|
||||
riskScore: risk.riskScore,
|
||||
riskLevel: risk.riskLevel,
|
||||
forecastReleaseDate: risk.forecastReleaseDate,
|
||||
openBugCount: 1,
|
||||
failedTestCount: 0,
|
||||
blockedCount: 0,
|
||||
silentRiskCount: 0,
|
||||
confidence: risk.confidence,
|
||||
createdAt: now.toISOString(),
|
||||
}));
|
||||
assert.equal(risk.currentSnapshot.openBugCount, 1);
|
||||
assert.equal(risk.currentSnapshot.criticalBugCount, 0);
|
||||
assert.equal(currentSignature, buildRiskSignature(risk.currentSnapshot));
|
||||
assert.equal(buildRiskSignature(risk.currentSnapshot).split('|')[5], '1');
|
||||
});
|
||||
|
||||
function bug(patch: Partial<Bug> = {}): Bug {
|
||||
|
||||
Reference in New Issue
Block a user