const fs = require("fs"); const path = require("path"); const vm = require("vm"); const assert = require("assert"); const rootDir = path.resolve(__dirname, "..", ".."); const createFakeDate = (isoString) => { const RealDate = Date; function FakeDate(...args) { if (!(this instanceof FakeDate)) { return new RealDate(...args); } if (args.length === 0) { return new RealDate(isoString); } return new RealDate(...args); } FakeDate.UTC = RealDate.UTC; FakeDate.parse = RealDate.parse; FakeDate.now = () => new RealDate(isoString).getTime(); FakeDate.prototype = RealDate.prototype; return FakeDate; }; const loadCpoRuleModule = () => { const filePath = path.join( rootDir, "lib", "domain", "representation-policy", "canStartCpoRepresentation.js" ); let source = fs.readFileSync(filePath, "utf8"); source = source.replace( /import\s+\{\s*isRepresentationWindowOpen\s*\}\s+from\s+"\.\/resolveRepresentationWindow";/, 'const { isRepresentationWindowOpen } = require("./resolveRepresentationWindow.cjs");' ); source = source.replace( /export function\s+canStartCpoRepresentation/, "function canStartCpoRepresentation" ); source += ` module.exports = { canStartCpoRepresentation }; `; const windowFilePath = path.join( rootDir, "lib", "domain", "representation-policy", "resolveRepresentationWindow.js" ); let windowSource = fs.readFileSync(windowFilePath, "utf8"); windowSource = windowSource.replace( /export function\s+isRepresentationWindowOpen/, "function isRepresentationWindowOpen" ); windowSource = windowSource.replace( /export function\s+isRepresentationWindowClosed/, "function isRepresentationWindowClosed" ); windowSource = windowSource.replace( /export function\s+resolveRepresentationWindow/, "function resolveRepresentationWindow" ); windowSource += ` module.exports = { isRepresentationWindowOpen, isRepresentationWindowClosed, resolveRepresentationWindow }; `; const windowModule = { exports: {} }; vm.runInNewContext( windowSource, { module: windowModule, exports: windowModule.exports, require, Date }, { filename: windowFilePath } ); const localRequire = (modulePath) => { if (modulePath === "./resolveRepresentationWindow.cjs") { return windowModule.exports; } return require(modulePath); }; const context = { module: { exports: {} }, exports: {}, require: localRequire, Number, Date }; vm.runInNewContext(source, context, { filename: filePath }); return context.module.exports; }; const tests = []; const test = (name, fn) => tests.push({ name, fn }); const { canStartCpoRepresentation } = loadCpoRuleModule(); test("CPO open window returns allowed behaviour", () => { const FakeDate = createFakeDate("2026-04-15T10:00:00.000Z"); assert.strictEqual( canStartCpoRepresentation( 846040019, { pinswg_startdate: "2026-04-01T00:00:00.000Z", pinswg_statementduedate: "2026-04-30T00:00:00.000Z" }, FakeDate ), true ); }); test("CPO expired window returns blocked behaviour", () => { const FakeDate = createFakeDate("2026-05-01T10:00:00.000Z"); assert.strictEqual( canStartCpoRepresentation( 846040019, { pinswg_startdate: "2026-04-01T00:00:00.000Z", pinswg_statementduedate: "2026-04-30T00:00:00.000Z" }, FakeDate ), false ); }); test("CPO future window preserves current blocked behaviour", () => { const FakeDate = createFakeDate("2026-03-31T10:00:00.000Z"); assert.strictEqual( canStartCpoRepresentation( 846040019, { pinswg_startdate: "2026-04-01T00:00:00.000Z", pinswg_statementduedate: "2026-04-30T00:00:00.000Z" }, FakeDate ), false ); }); test("CPO missing dates preserve current blocked behaviour", () => { const FakeDate = createFakeDate("2026-04-15T10:00:00.000Z"); assert.strictEqual( canStartCpoRepresentation( 846040019, { pinswg_statementduedate: "2026-04-30T00:00:00.000Z" }, FakeDate ), false ); assert.strictEqual( canStartCpoRepresentation( 846040019, { pinswg_startdate: "2026-04-01T00:00:00.000Z" }, FakeDate ), false ); assert.strictEqual( canStartCpoRepresentation(846040019, {}, FakeDate), false ); }); test("CPO helper does not broaden to fallback start fields", () => { const FakeDate = createFakeDate("2026-04-15T10:00:00.000Z"); assert.strictEqual( canStartCpoRepresentation( 846040019, { pinswg_startdates: "2026-04-01T00:00:00.000Z", pinswg_applicationacceptedasvalid: "2026-04-01T00:00:00.000Z", pinswg_statementduedate: "2026-04-30T00:00:00.000Z" }, FakeDate ), false ); }); test("string and number CPO appeal type values behave consistently", () => { const FakeDate = createFakeDate("2026-04-15T10:00:00.000Z"); const caseDetails = { pinswg_startdate: "2026-04-01T00:00:00.000Z", pinswg_statementduedate: "2026-04-30T00:00:00.000Z" }; assert.strictEqual( canStartCpoRepresentation(846040019, caseDetails, FakeDate), true ); assert.strictEqual( canStartCpoRepresentation("846040019", caseDetails, FakeDate), true ); }); test("non-CPO appeal types preserve permissive passthrough behaviour", () => { const FakeDate = createFakeDate("2026-05-01T10:00:00.000Z"); assert.strictEqual( canStartCpoRepresentation( 846040002, { pinswg_startdate: "2026-04-01T00:00:00.000Z", pinswg_statementduedate: "2026-04-30T00:00:00.000Z" }, FakeDate ), true ); }); const run = async () => { let passed = 0; for (const currentTest of tests) { await currentTest.fn(); passed += 1; } console.log( `Phase 22 representation-cpo-entry-rule tests passed (${passed}/${tests.length}).` ); }; module.exports = run; if (require.main === module) { run().catch((error) => { console.error(error); process.exit(1); }); }