← back to Sample Followup Sweep
test/coverage-reconcile.test.cjs
109 lines
'use strict';
// TK-12117 coverage-reconciliation negative test (ship-with-a-negative-test doctrine).
// Proves the canary goes RED on an injected fault (an outstanding row in NO bucket = silent skip)
// and GREEN only when the population is fully accounted + actioned.
const assert = require('node:assert');
const { reconcileCoverage, followupWindow, windowCoversActiveBand } = require('../lib/sweep');
// A resolvable vendor (chaseable) + a no-chase vendor as the "known good" contacts.
const contacts = {
fabr: { name: 'Fabricut', sample_email: 'customers@fabricut.com', account_number: 'On File' },
spn: { name: 'Spoonflower', disposition: 'no-chase' },
wat: { name: 'Watts 1874', sample_email: 'sophie@watts1874.co.uk', account_number: 'On File', needs_confirm: true },
};
const row = (vid, sku, entered, wp = '', letter = '') => ({ fieldData: {
vid, 'combo sku': sku, 'today for client': entered, 'Date WP Sample Sent': wp, 'Date Sample Request Letter Sent': letter, 'Mfr Pattern': 'P-' + sku } });
// 1. NEGATIVE — inject an outstanding row with EMPTY vid (the sweep drops it before grouping) → LEAKED → FAIL
{
const recs = [ row('FABR', 'DWFC1', '09/10/2026'), row('', 'DWLEAK1', '09/11/2026') ];
const r = reconcileCoverage(recs, { contacts });
assert.equal(r.verdict, 'FAIL', `1 injected empty-vid leak must FAIL, got ${r.verdict}`);
assert.ok(r.leaked.length >= 1, '1 leaked row must be reported');
assert.equal(r.population, 2, '1 population must count both outstanding rows');
console.log(`(1) PASS — injected empty-vid leak -> FAIL (leaked=${r.leaked.length}, pop=${r.population})`);
}
// 2. CLEAN — a single resolvable, not-recently-emailed, not-needs-confirm row → PASS
{
const recs = [ row('FABR', 'DWFC2', '09/10/2026') ];
const r = reconcileCoverage(recs, { contacts, recentSet: new Set() });
assert.equal(r.verdict, 'PASS', `2 clean must PASS, got ${r.verdict}`);
assert.equal(r.counts.chaseable, 1, '2 must be chaseable');
assert.equal(r.leaked.length, 0, '2 no leak');
console.log(`(2) PASS — clean chaseable row -> PASS (chaseable=${r.counts.chaseable})`);
}
// 3. UNCOVERED — an outstanding row whose vid has NO contact (no-vendor-map) → accounted but not chased → WARN
{
const recs = [ row('NOSUCHVID', 'DWX3', '09/10/2026') ];
const r = reconcileCoverage(recs, { contacts });
assert.equal(r.verdict, 'WARN', `3 no-vendor-map must WARN, got ${r.verdict}`);
assert.equal(r.counts.noVendorMap, 1, '3 must be noVendorMap');
assert.equal(r.leaked.length, 0, '3 accounted, not leaked');
console.log(`(3) PASS — no-vendor-map row -> WARN (uncovered=${r.uncovered})`);
}
// 4. RUN-STALE — clean population but the scheduled run did not fire on a run-day → WARN
{
const recs = [ row('FABR', 'DWFC4', '09/10/2026') ];
const r = reconcileCoverage(recs, { contacts, runStale: true });
assert.equal(r.verdict, 'WARN', `4 run-stale must WARN, got ${r.verdict}`);
console.log('(4) PASS — clean population but run missed on run-day -> WARN');
}
// 5. GUARD/RECENT reconcile — arrived-dup guard + FRESH recipient-busy deferral (<=24d) both count as ACTIONED (covered) → PASS
{
const today = new Date(2026, 8, 24); // 2026-09-24, deterministic (Sep = month 8)
const recs = [
row('FABR', 'DWFC5', '09/08/2026'), // outstanding, resolvable, not recently emailed -> chaseable
row('FABR', 'DWFC5', '09/08/2026', '09/14/2026'), // arrived same-date twin -> guard suppress
row('WAT', 'DWW5', '09/12/2026'), // recently emailed, 12d old (fresh) -> recipientBusy14d (covered batching)
];
const r = reconcileCoverage(recs, { contacts, recentSet: new Set(['sophie@watts1874.co.uk']), today });
assert.equal(r.counts.guardSuppressed, 1, '5 arrived twin -> guardSuppressed');
assert.equal(r.counts.recipientBusy14d, 1, '5 fresh recipient-busy -> recipientBusy14d (covered, not WARN)');
assert.equal(r.verdict, 'PASS', `5 all actioned must PASS, got ${r.verdict}`);
console.log('(5) PASS — guard-suppressed + fresh recipient-busy deferral both actioned -> PASS');
}
// 6. NEGATIVE (TK-12119) — a recipient-busy deferral aged PAST the batching window (>24d) must NOT hide
// as covered. Before this fix it was suppressed14d=covered=PASS (a false green for a never-chased sku
// of a perpetually-recontacted vendor); now it escalates to recipientBusyStale -> uncovered -> WARN.
{
const today = new Date(2026, 8, 24); // 2026-09-24
const recs = [ row('WAT', 'DWW6', '08/01/2026') ]; // recently-emailed vendor, but THIS sku entered 54d ago, never chased
const r = reconcileCoverage(recs, { contacts, recentSet: new Set(['sophie@watts1874.co.uk']), today });
assert.equal(r.counts.recipientBusy14d, 0, '6 stale deferral must NOT count as fresh/covered');
assert.equal(r.counts.recipientBusyStale, 1, '6 stale deferral -> recipientBusyStale');
assert.ok(r.uncovered >= 1, '6 stale deferral counts as uncovered');
assert.equal(r.verdict, 'WARN', `6 stale deferral must WARN (was a false-green PASS), got ${r.verdict}`);
console.log(`(6) PASS — recipient-busy aged >24d -> WARN not covered (recipientBusyStale=${r.counts.recipientBusyStale}, was suppressed14d/PASS)`);
}
// 7. WINDOW-BAND TRIPWIRE — POSITIVE: the default production window covers the full [10..60] active band.
{
const today = new Date(2026, 8, 24);
const band = windowCoversActiveBand(today, { minAge: 10, maxAge: 60 });
assert.equal(band.covers, true, '7 default full window must cover the active band');
assert.equal(band.gapDays, 0, '7 default window floor == today-60 (no gap)');
assert.ok(/07\/26\/2026\.\.\.09\/14\/2026/.test(followupWindow(today, { minAge: 10, maxAge: 60 })), '7 window is the full [today-60..today-10] band');
console.log('(7) PASS — default production window covers the full active band (gapDays=0)');
}
// 8. NEGATIVE (TK-12091 regression tripwire) — inject a NARROWED production window (a re-narrowing like
// TK-12091) and prove the canary tripwire goes RED: windowCoversActiveBand must return covers=false.
{
const today = new Date(2026, 8, 24);
const prev = process.env.WIN;
process.env.WIN = '09/13/2026...09/14/2026'; // a 1-day band = the TK-12091-class narrowing
try {
const band = windowCoversActiveBand(today, { minAge: 10, maxAge: 60 });
assert.equal(band.covers, false, '8 a narrowed production window MUST fail the tripwire (covers=false)');
assert.ok(band.gapDays > 0, '8 gapDays must report how far short the floor is');
console.log(`(8) PASS — injected narrow window -> tripwire RED (covers=false, gapDays=${band.gapDays})`);
} finally { if (prev === undefined) delete process.env.WIN; else process.env.WIN = prev; }
}
console.log('\nALL COVERAGE-RECONCILE ASSERTIONS PASSED');