← back to Dw Photo Capture
test: cover mfrToHouseSku resolver (cycle 21)
2e6d31c5b7b2a223a424ac9e4535c8cfe0900d24 · 2026-06-26 09:05:52 -0700 · Steve Abrams
mfrToHouseSku — the core 'scanned vendor code → DW house SKU' resolver (exact normalized
lookup + bounded ±1-trailing-char fuzzy + length guards) — was untested; a regression
there would silently break scan resolution. Added 7 guards via an injected controlled
MFR_INDEX fixture (not the real 225k file, so deterministic): exact match, case/dash/space
normalization, <4-char→null, no-match→null, +1-trailing-char fuzzy recovery (WDW23107
matches WDW2310), and the fuzzy length guard (5-char code won't fuzzy-match).
Behavior verified empirically before asserting — my initial expectations were wrong and
the code was right (e.g. WDW23106 matches WDW2310 by prefix, not WDW23105). 54→61 tests,
lint clean. $0 (local).
Files touched
M OVERNIGHT_LEDGER.mdM test-analyze-ocr.js
Diff
commit 2e6d31c5b7b2a223a424ac9e4535c8cfe0900d24
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Jun 26 09:05:52 2026 -0700
test: cover mfrToHouseSku resolver (cycle 21)
mfrToHouseSku — the core 'scanned vendor code → DW house SKU' resolver (exact normalized
lookup + bounded ±1-trailing-char fuzzy + length guards) — was untested; a regression
there would silently break scan resolution. Added 7 guards via an injected controlled
MFR_INDEX fixture (not the real 225k file, so deterministic): exact match, case/dash/space
normalization, <4-char→null, no-match→null, +1-trailing-char fuzzy recovery (WDW23107
matches WDW2310), and the fuzzy length guard (5-char code won't fuzzy-match).
Behavior verified empirically before asserting — my initial expectations were wrong and
the code was right (e.g. WDW23106 matches WDW2310 by prefix, not WDW23105). 54→61 tests,
lint clean. $0 (local).
---
OVERNIGHT_LEDGER.md | 1 +
test-analyze-ocr.js | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/OVERNIGHT_LEDGER.md b/OVERNIGHT_LEDGER.md
index 1b28c33..ee83ebc 100644
--- a/OVERNIGHT_LEDGER.md
+++ b/OVERNIGHT_LEDGER.md
@@ -67,3 +67,4 @@ the single highest-value safe one, the officer executes it, and the loop resched
| 18 | brainstorm #2 (ROBUSTNESS) | atomic saveJSON (temp-file + rename) — a crash/ENOSPC mid-write can no longer truncate vendor_profiles.json (180 learned profiles) or progress/recents/favorites; single shared-primitive fix protects all persistence | df 29G; proved via REAL saveJSON: forced write-failure left original intact, 0 stale temps; learn persists 200; lint+51 tests; selfcheck 200 | $0 |
| 19 | investigate O/0 (real, backlogged) + ship /api/stats | O/0/I/1 ambiguity CONFIRMED real (122 of 1033 codes have letter-O, 47 have both O+0) but touches hot resolve path w/ untestable false-match risk → BACKLOGGED w/ evidence; shipped additive /api/stats (version, vendors, fingerprinted, learn total, last-learn, model) — read-only, auth-gated, zero hot-path risk | df 27G; stats 200 + 401 no-creds; lint+51 tests; selfcheck implied | $0 |
| 20 | collision gate → REJECT O/0 fallback + lock verbatim contract | checked 225,846 real codes: 14 collision groups where different products are pure O/0 or I/1 variants (RI5112≠R15112) → O/0 auto-fallback would mis-resolve → REJECTED w/ evidence; locked the safe behavior (analyzeOcr preserves codes verbatim, no silent O↔0/I↔1) with 3 tests | df 34G; 51→54 tests; lint clean | $0 |
+| 21 | test-coverage (untested core helper) | mfrToHouseSku (scanned vendor code → DW house SKU) was UNTESTED despite real logic; added 7 guards via an injected MFR_INDEX fixture: exact/normalized match, case+dash+space stripping, <4-char→null, no-match→null, ±1-trailing-char fuzzy (WDW23107→WDW2310), 5-char fuzzy length-guard. Behavior verified empirically first (my initial guesses were wrong — code is correct) | df 34G; 54→61 tests; lint clean | $0 |
diff --git a/test-analyze-ocr.js b/test-analyze-ocr.js
index 106e530..0d3b40f 100644
--- a/test-analyze-ocr.js
+++ b/test-analyze-ocr.js
@@ -223,5 +223,25 @@ const bc = (payload, sym = 'Code128') => `BC\t${payload}\t${sym}`;
ok(num && num.pfx.test('5255'), 'profileToLex: numeric_share≥0.3 matches bare numbers');
}
+// ── mfrToHouseSku: scanned vendor code → DW house SKU (cycle 21, was untested) ──
+// Pure given MFR_INDEX — inject a controlled fixture (not the real 225k file) so the
+// exact-match, normalization, length-guard, and bounded ±1-char fuzzy logic are deterministic.
+{
+ const mfrMod = new Function('MFR_INDEX',
+ sliceConst('mfrNorm') + sliceFn('mfrToHouseSku') + 'return mfrToHouseSku;')({
+ 'WDW2310': { sku: 'CHC-217000' },
+ 'GRS26820': { sku: 'GRS-26820' },
+ });
+ eq(mfrMod('WDW2310'), 'CHC-217000', 'mfr: exact normalized match');
+ eq(mfrMod('wdw-2310'), 'CHC-217000', 'mfr: case + dash normalized to exact');
+ eq(mfrMod('GRS 26820'), 'GRS-26820', 'mfr: spaces stripped to exact');
+ eq(mfrMod('ABC'), null, 'mfr: <4 chars → null');
+ eq(mfrMod('ZZ9999'), null, 'mfr: no match anywhere → null');
+ // bounded fuzzy: DW sometimes drops/adds ONE trailing char — n starts with a known key
+ eq(mfrMod('WDW23107'), 'CHC-217000', 'mfr: +1 trailing char (n startsWith key) → fuzzy match');
+ // fuzzy is length-guarded: a 5-char code never fuzzy-matches (needs len ≥ 6)
+ eq(mfrMod('WDW23'), null, 'mfr: 5-char code does not fuzzy-match (length guard)');
+}
+
console.log(`\nanalyzeOcr/vendor tests: ${pass} passed, ${fail} failed`);
process.exit(fail ? 1 : 0);
← 93cd3e4 auto-save: 2026-06-26T08:43:59 (1 files) — data/build.json
·
back to Dw Photo Capture
·
test: cover nmfr + brandRe normalizers (cycle 22) 25e9532 →