const fs = require("fs"); const path = require("path"); const vm = require("vm"); const assert = require("assert"); const rootDir = path.resolve(__dirname, "..", ".."); const loadMapAppealTypeModule = () => { const filePath = path.join( rootDir, "lib", "domain", "case-lifecycle", "mapAppealType.js" ); let source = fs.readFileSync(filePath, "utf8"); source = source.replace(/export const\s+/g, "const "); source = source.replace( /export function\s+mapAppealType/, "function mapAppealType" ); source += ` module.exports = { caseTypeAliases, caseTypeKeyByAppealTypeId, normaliseCaseType, mapAppealType }; `; const context = { module: { exports: {} }, exports: {}, require }; vm.runInNewContext(source, context, { filename: filePath }); return context.module.exports; }; const loadMapSpecialistProcessStageTypeModule = () => { const filePath = path.join( rootDir, "lib", "domain", "case-lifecycle", "mapSpecialistProcessStageType.js" ); let source = fs.readFileSync(filePath, "utf8"); source = source.replace(/export const\s+/g, "const "); source = source.replace( /export function\s+mapSpecialistProcessStageType/, "function mapSpecialistProcessStageType" ); source += ` module.exports = { specialistProcessStageTypeByCaseType, mapSpecialistProcessStageType }; `; const context = { module: { exports: {} }, exports: {}, require }; vm.runInNewContext(source, context, { filename: filePath }); return context.module.exports; }; const loadGetStageCaseTypeKeyModule = () => { const filePath = path.join( rootDir, "lib", "domain", "case-lifecycle", "getStageCaseTypeKey.js" ); let source = fs.readFileSync(filePath, "utf8"); source = source.replace(/import[\s\S]*?from\s+"[^"]+";\n?/g, ""); source = source.replace( /export function\s+getStageCaseTypeKey/, "function getStageCaseTypeKey" ); source += ` module.exports = { getStageCaseTypeKey }; `; const context = { module: { exports: {} }, exports: {}, require, caseTypeAliases: mapAppealTypeModule.caseTypeAliases, caseTypeKeyByAppealTypeId: mapAppealTypeModule.caseTypeKeyByAppealTypeId, mapAppealType: mapAppealTypeModule.mapAppealType, normaliseCaseType: mapAppealTypeModule.normaliseCaseType, mapSpecialistProcessStageType: mapSpecialistProcessStageTypeModule.mapSpecialistProcessStageType }; vm.runInNewContext(source, context, { filename: filePath }); return context.module.exports; }; const loadStageHelperModule = () => { const filePath = path.join( rootDir, "components", "case", "summary", "utils", "caseStagesByAppealType.js" ); let source = fs.readFileSync(filePath, "utf8"); source = source.replace(/import[\s\S]*?from\s+"[^"]+";\n?/g, ""); source = source.replace(/export const\s+/g, "const "); source += "\nmodule.exports = { getStagesForAppealType };\n"; const context = { module: { exports: {} }, exports: {}, require, getStageCaseTypeKey: getStageCaseTypeKeyModule.getStageCaseTypeKey, getStagesForCaseTypeKey: getStagesForCaseTypeKeyModule.getStagesForCaseTypeKey }; vm.runInNewContext(source, context, { filename: filePath }); return context.module.exports; }; const loadStageCatalogueModule = () => { const filePath = path.join( rootDir, "components", "case", "summary", "utils", "caseStagesByAppealType.js" ); let source = fs.readFileSync(filePath, "utf8"); source = source.replace(/import[\s\S]*?from\s+"[^"]+";\n?/g, ""); source = source.replace(/export const\s+/g, "const "); source += "\nmodule.exports = { stagesByCaseType };\n"; const context = { module: { exports: {} }, exports: {}, require, getStageCaseTypeKey: getStageCaseTypeKeyModule.getStageCaseTypeKey, getStagesForCaseTypeKey: () => [] }; vm.runInNewContext(source, context, { filename: filePath }); return context.module.exports; }; const loadGetStagesForCaseTypeKeyModule = () => { const filePath = path.join( rootDir, "lib", "domain", "case-lifecycle", "getStagesForCaseTypeKey.js" ); let source = fs.readFileSync(filePath, "utf8"); source = source.replace(/import[\s\S]*?from\s+"[^"]+";\n?/g, ""); source = source.replace( /export function\s+getStagesForCaseTypeKey/, "function getStagesForCaseTypeKey" ); source += "\nmodule.exports = { getStagesForCaseTypeKey };\n"; const context = { module: { exports: {} }, exports: {}, require: (modulePath) => { if ( modulePath === "../../../components/case/summary/utils/caseStagesByAppealType" ) { return stageCatalogueModule; } return require(modulePath); } }; vm.runInNewContext(source, context, { filename: filePath }); return context.module.exports; }; const tests = []; const test = (name, fn) => tests.push({ name, fn }); const normalizeForAssertion = (value) => JSON.parse(JSON.stringify(value ?? null)); const mapAppealTypeModule = loadMapAppealTypeModule(); const mapSpecialistProcessStageTypeModule = loadMapSpecialistProcessStageTypeModule(); const getStageCaseTypeKeyModule = loadGetStageCaseTypeKeyModule(); const stageCatalogueModule = loadStageCatalogueModule(); const getStagesForCaseTypeKeyModule = loadGetStagesForCaseTypeKeyModule(); const stageHelperModule = loadStageHelperModule(); const { mapAppealType, caseTypeKeyByAppealTypeId, caseTypeAliases } = mapAppealTypeModule; const { getStagesForAppealType } = stageHelperModule; test("known mappings are preserved for representative appeal types", () => { assert.strictEqual(mapAppealType(846040000), "PLANNING_S78"); assert.strictEqual(mapAppealType(846040011), "DNS"); assert.strictEqual(mapAppealType(846040004), "HAS"); assert.strictEqual(mapAppealType(846040010), "CALL_INS"); assert.strictEqual(mapAppealType(846040015), "RIGHTS_OF_WAY_SCHEDULE_14"); }); test("aliases are preserved exactly", () => { assert.strictEqual(mapAppealType("S78"), "PLANNING_S78"); assert.strictEqual(mapAppealType("PLANNING_78"), "PLANNING_S78"); assert.strictEqual(mapAppealType("CALL_IN"), "CALL_INS"); assert.strictEqual(mapAppealType("DNS"), "DNS"); }); test("unknown appeal types preserve current behaviour", () => { assert.strictEqual(mapAppealType(999999999), "999999999"); assert.strictEqual(mapAppealType("UNKNOWN_CASE_TYPE"), "UNKNOWN_CASE_TYPE"); }); test("null and undefined preserve current behaviour", () => { assert.strictEqual(mapAppealType(null), undefined); assert.strictEqual(mapAppealType(undefined), undefined); }); test("mapping helper remains consistent with extracted mapping tables", () => { for (const [appealTypeId, caseTypeKey] of Object.entries( caseTypeKeyByAppealTypeId )) { assert.strictEqual(mapAppealType(Number(appealTypeId)), caseTypeKey); } for (const [alias, caseTypeKey] of Object.entries(caseTypeAliases)) { assert.strictEqual(mapAppealType(alias), caseTypeKey); } }); test("mapping helper returns keys that resolve to the same stage lists currently used by the source-of-truth helper", () => { const representativeIds = [846040000, 846040011, 846040004, 846040010]; for (const appealTypeId of representativeIds) { const mappedKey = mapAppealType(appealTypeId); assert.deepStrictEqual( normalizeForAssertion( getStagesForAppealType(appealTypeId, 999999999) ), normalizeForAssertion(getStagesForAppealType(mappedKey, 999999999)) ); } }); test("specialist-process-sensitive appeal type preserves extracted mapping without asserting stage-list equivalence outside specialist context", () => { assert.strictEqual(mapAppealType(846040015), "RIGHTS_OF_WAY_SCHEDULE_14"); }); const run = async () => { let passed = 0; for (const currentTest of tests) { await currentTest.fn(); passed += 1; } console.log( `Phase 22 case-lifecycle-appeal-type-mapping tests passed (${passed}/${tests.length}).` ); }; module.exports = run; if (require.main === module) { run().catch((error) => { console.error(error); process.exit(1); }); }