moving
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled

This commit is contained in:
Oleg Maslov
2026-09-02 10:10:29 +02:00
commit 0c3e2ead3b
3841 changed files with 970576 additions and 0 deletions

View File

@@ -0,0 +1,123 @@
/**
* Sprint 12 Task 1 Blocker #6 — failure distribution aggregator tests.
*
* Acceptance (brief § 2.1 B):
* 1. counts sum equals total
* 2. f_other_rate computation correct
* 3. review_flag at 11% triggers
* 4. review_flag at 10% does NOT trigger (strict greater-than)
* 5. sample captures first 10 F_other rationales in order
* 6. zero-F_other input yields empty sample
*/
import { describe, expect, it } from 'vitest';
import {
computeFailureDistribution,
type FailureRow,
} from '../../src/failure-taxonomy/aggregate.js';
describe('computeFailureDistribution — structural invariants', () => {
it('counts sum equals total', () => {
const rows: FailureRow[] = [
{ failure_code: null },
{ failure_code: null },
{ failure_code: 'F1' },
{ failure_code: 'F3' },
{ failure_code: 'F6' },
];
const dist = computeFailureDistribution(rows);
expect(dist.total).toBe(5);
const summed =
dist.counts.null +
dist.counts.F1 + dist.counts.F2 + dist.counts.F3 +
dist.counts.F4 + dist.counts.F5 + dist.counts.F6 +
dist.counts.F_other;
expect(summed).toBe(dist.total);
});
it('f_other_rate = F_other count / total', () => {
const rows: FailureRow[] = [
{ failure_code: 'F_other', rationale: 'rationale one two three four five six seven eight nine' },
{ failure_code: 'F_other', rationale: 'another rationale two three four five six seven eight nine' },
{ failure_code: null },
{ failure_code: 'F1' },
{ failure_code: null },
];
const dist = computeFailureDistribution(rows);
expect(dist.counts.F_other).toBe(2);
expect(dist.total).toBe(5);
expect(dist.f_other_rate).toBeCloseTo(2 / 5, 10);
});
});
describe('computeFailureDistribution — F_other review flag threshold', () => {
function buildRows(fOtherCount: number, total: number): FailureRow[] {
const rows: FailureRow[] = [];
for (let i = 0; i < fOtherCount; i++) {
rows.push({
failure_code: 'F_other',
rationale: `rationale ${i} padded padded padded padded padded padded padded padded padded`,
});
}
for (let i = 0; i < total - fOtherCount; i++) {
rows.push({ failure_code: null });
}
return rows;
}
it('flag triggers at 11% (11/100 > 10%)', () => {
const dist = computeFailureDistribution(buildRows(11, 100));
expect(dist.f_other_rate).toBeCloseTo(0.11, 10);
expect(dist.f_other_review_flag).toBe(true);
});
it('flag does NOT trigger at 10% (strict greater-than: 10/100 not > 10%)', () => {
const dist = computeFailureDistribution(buildRows(10, 100));
expect(dist.f_other_rate).toBeCloseTo(0.10, 10);
expect(dist.f_other_review_flag).toBe(false);
});
it('flag does not trigger on empty input', () => {
const dist = computeFailureDistribution([]);
expect(dist.total).toBe(0);
expect(dist.f_other_rate).toBe(0);
expect(dist.f_other_review_flag).toBe(false);
});
});
describe('computeFailureDistribution — F_other rationale sample', () => {
it('captures first 10 F_other rationales in input order', () => {
const rows: FailureRow[] = [];
for (let i = 0; i < 15; i++) {
rows.push({
failure_code: 'F_other',
rationale: `rationale-${i} padded padded padded padded padded padded padded padded padded`,
});
}
const dist = computeFailureDistribution(rows);
expect(dist.f_other_rationales_sample).toHaveLength(10);
expect(dist.f_other_rationales_sample[0]).toMatch(/^rationale-0 /);
expect(dist.f_other_rationales_sample[9]).toMatch(/^rationale-9 /);
});
it('zero-F_other input yields empty sample array', () => {
const rows: FailureRow[] = [
{ failure_code: null },
{ failure_code: 'F1' },
{ failure_code: 'F2' },
];
const dist = computeFailureDistribution(rows);
expect(dist.counts.F_other).toBe(0);
expect(dist.f_other_rationales_sample).toEqual([]);
});
it('skips F_other rows without a rationale string in the sample (robustness)', () => {
const rows: FailureRow[] = [
{ failure_code: 'F_other', rationale: null },
{ failure_code: 'F_other', rationale: 'valid rationale one two three four five six seven eight' },
];
const dist = computeFailureDistribution(rows);
expect(dist.counts.F_other).toBe(2);
expect(dist.f_other_rationales_sample).toHaveLength(1);
});
});