const fs = require("fs"); const path = require("path"); const vm = require("vm"); const assert = require("assert"); const rootDir = path.resolve(__dirname, "..", ".."); const loadClosedCaseStatusModule = () => { const filePath = path.join( rootDir, "lib", "domain", "case-lifecycle", "isClosedCaseStatus.js" ); let source = fs.readFileSync(filePath, "utf8"); source = source.replace( /export function\s+isClosedCaseStatus/, "function isClosedCaseStatus" ); source += "\nmodule.exports = { isClosedCaseStatus };\n"; const context = { module: { exports: {} }, exports: {}, require }; vm.runInNewContext(source, context, { filename: filePath }); return context.module.exports; }; const loadGetLifecycleStageIndexModule = () => { const filePath = path.join( rootDir, "lib", "domain", "case-lifecycle", "getLifecycleStageIndex.js" ); let source = fs.readFileSync(filePath, "utf8"); source = source.replace(/import[\s\S]*?from\s+"[^"]+";\n?/g, ""); source = source.replace( /export function\s+getLifecycleStageIndex/, "function getLifecycleStageIndex" ); source += "\nmodule.exports = { getLifecycleStageIndex };\n"; const context = { module: { exports: {} }, exports: {}, require, isClosedCaseStatus: isClosedCaseStatusModule.isClosedCaseStatus }; vm.runInNewContext(source, context, { filename: filePath }); return context.module.exports; }; 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 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: () => [], isClosedCaseStatus: isClosedCaseStatusModule.isClosedCaseStatus, getLifecycleStageIndex: getLifecycleStageIndexModule.getLifecycleStageIndex }; 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 += ` module.exports = { getStagesForCaseTypeKey }; `; 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 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, isClosedCaseStatus: isClosedCaseStatusModule.isClosedCaseStatus, getLifecycleStageIndex: getLifecycleStageIndexModule.getLifecycleStageIndex }; 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 isClosedCaseStatusModule = loadClosedCaseStatusModule(); const getLifecycleStageIndexModule = loadGetLifecycleStageIndexModule(); const mapAppealTypeModule = loadMapAppealTypeModule(); const mapSpecialistProcessStageTypeModule = loadMapSpecialistProcessStageTypeModule(); const getStageCaseTypeKeyModule = loadGetStageCaseTypeKeyModule(); const stageCatalogueModule = loadStageCatalogueModule(); const getStagesForCaseTypeKeyModule = loadGetStagesForCaseTypeKeyModule(); const stageHelperModule = loadStageHelperModule(); const { isClosedCaseStatus } = isClosedCaseStatusModule; const { getStagesForAppealType } = stageHelperModule; test("current closed statuses are recognized exactly", () => { const closedStatuses = [1000, 5, 6, 846040013, 846040059, 846040060]; for (const closedStatus of closedStatuses) { assert.strictEqual(isClosedCaseStatus(closedStatus), true); } }); test("representative non-closed statuses remain false", () => { const nonClosedStatuses = [ 1, 846040014, 846040018, 846040021, 846040049, 846040062 ]; for (const nonClosedStatus of nonClosedStatuses) { assert.strictEqual(isClosedCaseStatus(nonClosedStatus), false); } }); test("unknown values preserve current false fallback", () => { assert.strictEqual(isClosedCaseStatus(999999999), false); assert.strictEqual(isClosedCaseStatus("UNKNOWN"), false); }); test("null and undefined preserve current false fallback", () => { assert.strictEqual(isClosedCaseStatus(null), false); assert.strictEqual(isClosedCaseStatus(undefined), false); }); test("string and number handling preserves current Number-based closed-status behaviour", () => { assert.strictEqual(isClosedCaseStatus("1000"), true); assert.strictEqual(isClosedCaseStatus("5"), true); assert.strictEqual(isClosedCaseStatus("6"), true); assert.strictEqual(isClosedCaseStatus("846040013"), true); assert.strictEqual(isClosedCaseStatus("846040059"), true); assert.strictEqual(isClosedCaseStatus("846040060"), true); assert.strictEqual(isClosedCaseStatus("846040018"), false); }); test("integration parity preserves existing closed-case progress outputs", () => { const closedStatuses = [1000, 5, 6, 846040013, 846040059, 846040060]; for (const closedStatus of closedStatuses) { const result = normalizeForAssertion( getStagesForAppealType(846040000, closedStatus) ); const closedStage = result.find( (stage) => stage.titleKey === "case-closed" ); assert.ok(closedStage, `Expected closed stage for ${closedStatus}`); assert.strictEqual(closedStage.status, "in-progress"); assert.ok( result .slice( 0, result.findIndex( (stage) => stage.titleKey === "case-closed" ) ) .every((stage) => stage.status === "complete") ); } }); const run = async () => { let passed = 0; for (const currentTest of tests) { await currentTest.fn(); passed += 1; } console.log( `Phase 22 case-lifecycle-closed-case-status tests passed (${passed}/${tests.length}).` ); }; module.exports = run; if (require.main === module) { run().catch((error) => { console.error(error); process.exit(1); }); }