← back to Dw Signup Fulfillment
verification/tk11285/commit-rows-test.js
66 lines
'use strict';
// Focused tests for commitRows() in scripts/recover-stuck-apps.js — the merge that
// stops this out-of-process writer from clobbering the live service's writes.
const fs = require('fs');
const path = require('path');
const ROOT = path.join(__dirname, '..', '..');
const trade = require(path.join(ROOT, 'lib', 'trade'));
const { commitRows } = require(path.join(ROOT, 'scripts', 'recover-stuck-apps.js'));
const APPS = trade.APPS_PATH;
const write = rows => fs.writeFileSync(APPS, rows.map(r => JSON.stringify(r)).join('\n') + (rows.length ? '\n' : ''));
const read = () => fs.readFileSync(APPS, 'utf8').split('\n').filter(Boolean).map(l => JSON.parse(l));
const row = (o) => ({ id: o.id, email: o.id + '@e.com', status: 'pending', created_at: '2026-09-01T00:00:00.000Z', shopify_customer_id: null, ...o });
const results = [];
const check = (name, pass, detail) => { results.push({ name, verdict: pass ? 'PASS' : 'FAIL', detail }); };
// 1. a row that arrived after our snapshot is preserved
write([row({ id: 'A' })]);
const snapshotA = read();
write([row({ id: 'A' }), row({ id: 'NEW' })]); // service appended concurrently
snapshotA[0].shopify_customer_id = '111'; snapshotA[0].link_status = 'linked';
commitRows(snapshotA);
check('new intake appended during the window survives', read().some(r => r.id === 'NEW'), read().map(r => r.id).join(','));
check('our linkage still applied', read().find(r => r.id === 'A').shopify_customer_id === '111');
// 2. a decision made during the window is not overwritten
write([row({ id: 'B' })]);
const snapB = read();
write([row({ id: 'B', status: 'approved', decision: 'approved', shopify_customer_id: '222' })]);
snapB[0].shopify_customer_id = '999'; snapB[0].link_status = 'linked'; snapB[0].recovery_emailed = true;
commitRows(snapB);
const b = read().find(r => r.id === 'B');
check('service decision preserved', b.status === 'approved', 'status=' + b.status);
check('service customer id preserved (not clobbered by our stale link)', b.shopify_customer_id === '222', 'cust=' + b.shopify_customer_id);
check('email receipt still recorded (no duplicate letter later)', b.recovery_emailed === true);
// 3. customer_id conflict must NOT erase the id the service resolved
// (regression: `patch.x = undefined` still spreads and deletes the key)
write([row({ id: 'C' })]);
const snapC = read();
write([row({ id: 'C', shopify_customer_id: '333' })]); // service resolved it first
snapC[0].shopify_customer_id = '444'; // we resolved a different one
commitRows(snapC);
const c = read().find(r => r.id === 'C');
check('conflicting customer id: service value kept', c.shopify_customer_id === '333', 'cust=' + c.shopify_customer_id);
check('conflicting customer id: key not erased', 'shopify_customer_id' in c && c.shopify_customer_id != null, JSON.stringify(c));
// 4. a row we touched that has since vanished is not resurrected
write([row({ id: 'D' })]);
const snapD = read();
write([]); // row gone
commitRows(snapD);
check('vanished row is not resurrected', read().length === 0, 'rows=' + read().length);
// 5. rows we never touched are left byte-identical
write([row({ id: 'E' }), row({ id: 'UNTOUCHED', business_name: 'keep me' })]);
const snapE = read();
commitRows([snapE[0]]);
const u = read().find(r => r.id === 'UNTOUCHED');
check('untouched rows preserved verbatim', JSON.stringify(u) === JSON.stringify(snapE[1]));
const failures = results.filter(r => r.verdict === 'FAIL');
console.log(JSON.stringify({ suite: 'commitRows', total: results.length, passed: results.length - failures.length, failed: failures.length, results }, null, 2));
process.exit(failures.length ? 1 : 0);