import { test } from 'node:test'; import assert from 'node:assert/strict'; import { localCandidates, MOBILE_HELPERS, MONTHLY_HELPERS, OPERATIONS_HELPERS, patchFunctions } from '../speed-round3-patch.mjs'; test('only allowlisted function bodies change; handlers, constants and unselected helpers stay exact', () => { const before = 'const tenant="co";\nfunction target(){return 1;}\nfunction retained(){return "same";}\nhandler=retained;'; const candidate = 'const tenant="wrong";function target(){return 2;} function added(){return target();} function retained(){throw Error("wrong");} handler=target;'; const result = patchFunctions(before, candidate, ['target', 'added']); assert.match(result.code, /const tenant="co"/); assert.match(result.code, /function retained\(\)\{return "same";\}/); assert.match(result.code, /handler=retained/); assert.deepEqual(result.audit.functions.map(row => [row.name, row.action]), [['target', 'replace'], ['added', 'add']]); assert.equal(patchFunctions(result.code, candidate, ['target', 'added']).code, result.code); }); test('missing or duplicate declarations fail closed instead of guessing a release target', () => { assert.throws(() => patchFunctions('', '', ['missing']), /Expected unique/); assert.throws(() => patchFunctions('function x(){} function x(){}', 'function x(){}', ['x']), /Expected unique/); assert.throws(() => patchFunctions('function x(){}', 'function x(){} function x(){}', ['x']), /Expected unique/); assert.throws(() => patchFunctions('', 'function x(){}', ['x', 'x']), /Duplicate helper/); }); test('every final local mobile/monthly/operations helper can be selected and calculator exposes monthly date semantics', () => { const candidates = localCandidates(); for (const [scope, names] of [['mobile', [...MOBILE_HELPERS, ...MONTHLY_HELPERS]], ['operations', OPERATIONS_HELPERS]]) { const built = patchFunctions('function handler(){return "unchanged entrypoint";}', candidates[scope], names); assert.equal(built.audit.functions.length, names.length); assert.ok(built.audit.functions.every(row => row.action === 'add')); assert.match(built.code, /function handler\(\)\{return "unchanged entrypoint";\}/); } assert.match(candidates.mobile, /businessDate:payrollBusinessDate/); });