Files
knowledge-governance/web/src/qaQuality.test.ts
T
姚章浩 828c2c5fa0
build / build (push) Successful in 1m6s
feat(qa-ops): 按确认口径补齐质量比例与分母明细
使用完整筛选范围的当前有效结论计算覆盖率和正确率,人工优先,失效与对应待确认/未评估/不计入排除;零分母返回null,界面展示原始分子分母和排除构成,前端拒绝不守恒或比例不一致的响应。

验证:make verify退出码0,Go658及前端257通过,91项声明可选集成跳过;隔离PG、三包竞态及合成/真实只读源浏览器验证通过。无新增迁移,不接AI模型,不改绩效,不写源库;本批未推送或部署,8088运行版保持0.1.21。
2026-10-18 02:00:31 +08:00

75 lines
3.1 KiB
TypeScript

import { describe, it, expect } from 'vitest'
import { parseQAQuality, parseQualitySummary, parseQualityHistory } from './qaQuality'
import { qualityFixture, summaryFixture, check, review } from './qaQuality.fixture'
import { parseQARecord, qaCellValue } from './qaOps'
describe('quality evidence contracts', () => {
it('renders effective manual labels in agreed columns without changing the rule result', () => {
const record = parseQARecord({
id: 'fixture',
status: 'succeeded',
question: '示例',
answer: '暂无已发布',
asked_at: '2026-10-17T12:00:00Z',
time_source: 'request_message.created_at',
asker: '',
trigger_person: '',
department: '',
region: '',
references: [],
media: [],
source_coverage: check.source,
feedback: { asker_value: '', up: 0, down: 0 },
coverage: check.result,
quality: qualityFixture,
})
expect(qaCellValue(record, 'coverage')).toBe('是')
expect(qaCellValue(record, 'is_correct')).toBe('是')
expect(qaCellValue(record, 'product_category')).toBe('MG400')
expect(record.coverage.verdict).toBe('uncovered')
})
it('separates immutable rule/source results and explicit human outcomes', () => {
const v = parseQAQuality(qualityFixture)
expect(v.effective.coverage).toBe('covered')
expect(v.automatic.result.verdict).toBe('uncovered')
})
it('rejects stale conclusions kept effective and forged revisions', () => {
expect(() =>
parseQAQuality({ ...qualityFixture, state: 'stale', input_epoch: 2, automatic: { ...check, input_epoch: 2 } })
).toThrow()
expect(() => parseQAQuality({ ...qualityFixture, revision: 2 })).toThrow()
})
it('keeps scope counts whole and conservative without made-up rates', () => {
expect(parseQualitySummary(summaryFixture).summary.total).toBe(3)
expect(() => parseQualitySummary({ ...summaryFixture, summary: { ...summaryFixture.summary, total: 4 } })).toThrow()
})
it('retains pageable human and automatic history independently', () => {
expect(
parseQualityHistory({ reviews: [review], checks: [check], next_review: 0, next_check: 0 }).reviews
).toHaveLength(1)
})
})
describe('confirmed quality rate contract', () => {
it('retains raw counts, null rates, scope breakdown and policy version', () => {
const result = parseQualitySummary(summaryFixture)
expect(result.summary.rates.coverage.numerator).toBe(1)
expect(result.summary.rates.coverage.denominator).toBe(2)
expect(result.summary.rates.correctness.percent).toBe(100)
})
it('rejects invalid or inconsistent numerator, denominator, percent and category sums', () => {
for (const change of [
(r: any) => (r.coverage.numerator = 3),
(r: any) => (r.coverage.denominator = 3),
(r: any) => (r.coverage.percent = 99),
(r: any) => (r.breakdown.stale = 0),
(r: any) => (r.correctness.percent = null),
(r: any) => (r.policy_version = 'unknown'),
]) {
const v = structuredClone(summaryFixture)
change(v.summary.rates)
expect(() => parseQualitySummary(v)).toThrow()
}
})
})