/* eslint-disable */ /** * Smoke test — exercise the full tiered SKU + description matcher * against live PB. * * Run with: * env PB_ADMIN_EMAIL=… PB_ADMIN_PASSWORD=… NEXT_PUBLIC_POCKETBASE_URL=… * npx tsx scripts/smoke/sku-matcher.ts */ import { findPriceListBySku, findFirstPriceListBySku, classifyMatch, explainMatch, matchTierLabel, normaliseSku, escapeForPbString, } from "../../src/lib/server/price-list-match"; import PocketBase from "pocketbase"; async function main() { const URL = process.env.NEXT_PUBLIC_POCKETBASE_URL; const ADMIN_EMAIL = process.env.PB_ADMIN_EMAIL; const ADMIN_PASSWORD = process.env.PB_ADMIN_PASSWORD; if (!URL || !ADMIN_EMAIL || !ADMIN_PASSWORD) { throw new Error("Set PB_ADMIN_EMAIL, PB_ADMIN_PASSWORD, NEXT_PUBLIC_POCKETBASE_URL."); } const pb = new PocketBase(URL); await pb.collection("_superusers").authWithPassword(ADMIN_EMAIL, ADMIN_PASSWORD); async function tryMatch(label: string, sku: string, opts: { tier3?: boolean } = {}) { const matches = await findPriceListBySku( sku, { enableTier3: opts.tier3 ?? true }, pb as unknown as PocketBase, ); if (matches.length === 0) { console.log(` ${label.padEnd(50)} (input: "${sku}") → no match`); return; } const top = matches[0]; const tier = classifyMatch(sku, top); const why = explainMatch(sku, top); console.log(` ${label.padEnd(50)} (input: "${sku}")`); console.log(` tier ${tier} ${matchTierLabel(tier)} — "${why}"`); console.log(` matched: sku="${top.sku}" desc="${top.description}" cost=${top.cost_price} sell=${top.selling_price} (${top.supplier})`); if (matches.length > 1) { console.log(` ${matches.length - 1} more candidates (top-tier only: full list would be Tier-sorted by picker UI)`); } } console.log("=== Tiered matcher smoke test ==="); console.log("\n--- Tier 1: exact equality ---"); await tryMatch("exact, as stored", "JEITD-06"); await tryMatch("case insensitive", "jeitd-06"); await tryMatch("without dashes", "JEITD06", { tier3: false }); console.log("\n--- Tier 2: SKU substring fallback ---"); await tryMatch("partial prefix", "JEITD", { tier3: false }); await tryMatch("brand prefix in SKU", "TS-DRL", { tier3: false }); console.log("\n--- Tier 3: description / brand fuzzy (Tier 3 enabled) ---"); await tryMatch("brand-only search", "JEISA"); await tryMatch("category-ish fuzzy", "TURBO"); await tryMatch("country-ish fuzzy", "WESTSCOTT"); console.log("\n--- Tier-3 disabled (bulk auto-fill rejects fuzzy) ---"); await tryMatch("no fuzzy — empty", "bosch grinder", { tier3: false }); await tryMatch("no fuzzy — empty", "m20 bolt", { tier3: false }); console.log("\n--- Tier 3 ENABLED (picker surfaces them) ---"); await tryMatch("with fuzzy — candidates", "bosch grinder"); await tryMatch("with fuzzy — candidates", "m20 bolt"); console.log("\n--- Sanity: pure helpers ---"); console.log(` normaliseSku("jeitd-06") = "${normaliseSku("jeitd-06")}"`); console.log(` escapeForPbString('Acme "Pro" line') = "${escapeForPbString('Acme "Pro" line')}"`); console.log(` classifyMatch("JEITD-06", { sku: "JEITD-06", sku_normalised: "JEITD06" }) = ${classifyMatch("JEITD-06", { sku: "JEITD-06", sku_normalised: "JEITD06" })}`); console.log(` classifyMatch("JEITD", { sku: "JEITD-D11", sku_normalised: "JEITDD11" }) = ${classifyMatch("JEITD", { sku: "JEITD-D11", sku_normalised: "JEITDD11" })}`); await tryMatch("empty string skipped", ""); await tryMatch("garbage no match (tier3 ON)", "ZZZGARBAGE-XYZ"); } main().catch((e) => { console.error(e); process.exit(1); });