const assert = require("assert"); const { loadModule, createRes, createNextConnectMock, respondSuccessMock, respondErrorMock } = require("./_shared.cjs"); const tests = []; const test = (name, fn) => tests.push({ name, fn }); test("upload handler returns HASH_REQUIRED for missing hash", async () => { const mod = loadModule("pages/api/file/upload.js", { nextConnect: createNextConnectMock(), middleware: () => {}, hashAPIPath: () => "?hash=expected", respondError: respondErrorMock, respondSuccess: respondSuccessMock, createBlob: async () => ({ ok: true }), createRepBlob: async () => ({ ok: true }) }); const req = { query: {}, body: {} }; const res = createRes(); await mod.default.handler(req, res); assert.strictEqual(res.state.statusCode, 400); assert.strictEqual(res.state.jsonBody.error.code, "HASH_REQUIRED"); }); test("upload handler returns INVALID_HASH for wrong hash", async () => { const mod = loadModule("pages/api/file/upload.js", { nextConnect: createNextConnectMock(), middleware: () => {}, hashAPIPath: () => "?hash=expected", respondError: respondErrorMock, respondSuccess: respondSuccessMock, createBlob: async () => ({ ok: true }), createRepBlob: async () => ({ ok: true }) }); const req = { query: { hash: "wrong" }, body: { containerID: ["c1"], casefolderID: ["f1"] } }; const res = createRes(); await mod.default.handler(req, res); assert.strictEqual(res.state.statusCode, 400); assert.strictEqual(res.state.jsonBody.error.code, "INVALID_HASH"); }); test("deleteblob handler returns MISSING_REQUIRED_QUERY when blobname missing", async () => { const mod = loadModule("pages/api/file/deleteblob.js", { nextConnect: createNextConnectMock(), middleware: () => {}, hashAPIPath: () => "&hash=expected", respondError: respondErrorMock, respondSuccess: respondSuccessMock, deleteBlob: async () => ({ ok: true }) }); const req = { query: { container: "c1", casefolderID: "f1", hash: "expected" } }; const res = createRes(); await mod.default.handler(req, res); assert.strictEqual(res.state.statusCode, 400); assert.strictEqual(res.state.jsonBody.error.code, "MISSING_REQUIRED_QUERY"); }); test("getbloblist handler returns INVALID_HASH for mismatch", async () => { const mod = loadModule("pages/api/file/getbloblist.js", { nextConnect: createNextConnectMock(), middleware: () => {}, hashAPIPath: () => "&hash=expected", respondError: respondErrorMock, respondSuccess: respondSuccessMock, getBlobs: async () => ({ id: "x" }), getRepsFilesBlobs: async () => ({ id: "x" }) }); const req = { query: { container: "c1", casefolderID: "f1", hash: "wrong" } }; const res = createRes(); await mod.default.handler(req, res); assert.strictEqual(res.state.statusCode, 400); assert.strictEqual(res.state.jsonBody.error.code, "INVALID_HASH"); }); test("setupcontainer handler returns MISSING_REQUIRED_QUERY when ident missing", async () => { const mod = loadModule("pages/api/file/setupcontainer.js", { nextConnect: createNextConnectMock(), middleware: () => {}, hashAPIPath: () => "&hash=expected", consoleLogger: () => {}, respondError: respondErrorMock, respondSuccess: respondSuccessMock, createContainer: async () => ({ ok: true }) }); const req = { query: { hash: "expected" } }; const res = createRes(); await mod.default.handler(req, res); assert.strictEqual(res.state.statusCode, 400); assert.strictEqual(res.state.jsonBody.error.code, "MISSING_REQUIRED_QUERY"); }); test("upload handler success returns data payload with 200", async () => { const mod = loadModule("pages/api/file/upload.js", { nextConnect: createNextConnectMock(), middleware: () => {}, hashAPIPath: () => "?hash=expected", respondError: respondErrorMock, respondSuccess: respondSuccessMock, createBlob: async () => ({ id: "blob-1" }), createRepBlob: async () => ({ id: "rep-1" }) }); const req = { query: { hash: "expected" }, body: { appealData: { key: "value" }, containerID: ["c1"], casefolderID: ["f1"], repOrAppeal: false } }; const res = createRes(); await mod.default.handler(req, res); assert.strictEqual(res.state.statusCode, 200); assert.deepStrictEqual(JSON.parse(JSON.stringify(res.state.jsonBody)), { data: { id: "blob-1" } }); }); test("setupcontainer handler success returns expected contract", async () => { const mod = loadModule("pages/api/file/setupcontainer.js", { nextConnect: createNextConnectMock(), middleware: () => {}, hashAPIPath: () => "&hash=expected", consoleLogger: () => {}, respondError: respondErrorMock, respondSuccess: respondSuccessMock, createContainer: async () => ({ created: true }) }); const req = { query: { ident: "cont-1", hash: "expected" } }; const res = createRes(); await mod.default.handler(req, res); assert.strictEqual(res.state.statusCode, 200); assert.deepStrictEqual(JSON.parse(JSON.stringify(res.state.jsonBody)), { data: "success", output: { created: true } }); }); test("getbloblist handler success returns value array contract", async () => { const mod = loadModule("pages/api/file/getbloblist.js", { nextConnect: createNextConnectMock(), middleware: () => {}, hashAPIPath: () => "&hash=expected", respondError: respondErrorMock, respondSuccess: respondSuccessMock, getBlobs: async () => ({ file: "a.pdf" }), getRepsFilesBlobs: async () => ({ file: "rep.pdf" }) }); const req = { query: { container: "c1", casefolderID: "f1", hash: "expected" } }; const res = createRes(); await mod.default.handler(req, res); assert.strictEqual(res.state.statusCode, 200); assert.deepStrictEqual(JSON.parse(JSON.stringify(res.state.jsonBody)), { value: [{ file: "a.pdf" }] }); }); test("downloadblob handler success sets attachment header and returns body", async () => { const mod = loadModule("pages/api/file/downloadblob.js", { nextConnect: createNextConnectMock(), middleware: () => {}, hashAPIPath: () => "&hash=expected", respondError: respondErrorMock, downloadFile: async () => Buffer.from("file-content") }); const req = { query: { container: "c1", casefolderID: "f1", blobname: "doc.pdf", hash: "expected" } }; const res = createRes(); await mod.default.handler(req, res); assert.strictEqual(res.state.statusCode, 200); assert.strictEqual( res.state.headers["content-disposition"], "attachment; filename=doc.pdf" ); assert.strictEqual(res.state.sentBody.toString(), "file-content"); }); test("upload handler dependency failure returns UPLOAD_FAILED", async () => { const mod = loadModule("pages/api/file/upload.js", { nextConnect: createNextConnectMock(), middleware: () => {}, hashAPIPath: () => "?hash=expected", respondError: respondErrorMock, respondSuccess: respondSuccessMock, createBlob: async () => { throw new Error("storage down"); }, createRepBlob: async () => ({ id: "rep-1" }) }); const req = { query: { hash: "expected" }, body: { appealData: { key: "value" }, containerID: ["c1"], casefolderID: ["f1"], repOrAppeal: false } }; const res = createRes(); await mod.default.handler(req, res); assert.strictEqual(res.state.statusCode, 400); assert.strictEqual(res.state.jsonBody.error.code, "UPLOAD_FAILED"); }); test("setupcontainer dependency failure returns SETUP_CONTAINER_FAILED", async () => { const mod = loadModule("pages/api/file/setupcontainer.js", { nextConnect: createNextConnectMock(), middleware: () => {}, hashAPIPath: () => "&hash=expected", consoleLogger: () => {}, respondError: respondErrorMock, respondSuccess: respondSuccessMock, createContainer: async () => { throw new Error("container failed"); } }); const req = { query: { ident: "cont-1", hash: "expected" } }; const res = createRes(); await mod.default.handler(req, res); assert.strictEqual(res.state.statusCode, 400); assert.strictEqual(res.state.jsonBody.error.code, "SETUP_CONTAINER_FAILED"); }); test("downloadblob dependency failure returns DOWNLOAD_BLOB_FAILED", async () => { const mod = loadModule("pages/api/file/downloadblob.js", { nextConnect: createNextConnectMock(), middleware: () => {}, hashAPIPath: () => "&hash=expected", respondError: respondErrorMock, downloadFile: async () => { throw new Error("download failed"); } }); const req = { query: { container: "c1", casefolderID: "f1", blobname: "doc.pdf", hash: "expected" } }; const res = createRes(); await mod.default.handler(req, res); assert.strictEqual(res.state.statusCode, 400); assert.strictEqual(res.state.jsonBody.error.code, "DOWNLOAD_BLOB_FAILED"); }); test("generateappealpdfcopy returns INCIDENT_ID_REQUIRED when docProps missing", async () => { const mod = loadModule("pages/api/file/generateappealpdfcopy.js", { respondError: respondErrorMock, getCaseByID: async () => [], getPortalModuleDetails: async () => ({ value: [{}] }), getAppealPDFDocs: async () => [], getFormCollectionByID: () => ({ UrlName: "planningappeals78" }), getPickLists: async () => ({}), planningappeals78_pdf: () => ({}), other_pdf: () => ({}), pdf: () => ({ toBuffer: async () => Buffer.from("pdf") }) }); const req = { body: {} }; const res = createRes(); await mod.default(req, res); assert.strictEqual(res.state.statusCode, 400); assert.strictEqual(res.state.jsonBody.error.code, "INCIDENT_ID_REQUIRED"); }); test("generateappealpdfcopy returns CASE_NOT_FOUND when case lookup is empty", async () => { const mod = loadModule("pages/api/file/generateappealpdfcopy.js", { respondError: respondErrorMock, getCaseByID: async () => [], getPortalModuleDetails: async () => ({ value: [{}] }), getAppealPDFDocs: async () => [], getFormCollectionByID: () => ({ UrlName: "planningappeals78" }), getPickLists: async () => ({}), planningappeals78_pdf: () => ({}), other_pdf: () => ({}), pdf: () => ({ toBuffer: async () => Buffer.from("pdf") }) }); const req = { body: { docProps: "i1" } }; const res = createRes(); await mod.default(req, res); assert.strictEqual(res.state.statusCode, 404); assert.strictEqual(res.state.jsonBody.error.code, "CASE_NOT_FOUND"); }); test("generateappealpdfcopy returns FORM_COLLECTION_NOT_FOUND when collection is unresolved", async () => { const mod = loadModule("pages/api/file/generateappealpdfcopy.js", { respondError: respondErrorMock, getCaseByID: async () => [ { pinswg_appealcasetype: 846040000, ticketnumber: "CAS-1", description: "desc" } ], getPortalModuleDetails: async () => ({ value: [{}] }), getAppealPDFDocs: async () => [], getFormCollectionByID: () => null, getPickLists: async () => ({}), planningappeals78_pdf: () => ({}), other_pdf: () => ({}), pdf: () => ({ toBuffer: async () => Buffer.from("pdf") }) }); const req = { body: { docProps: "i1" } }; const res = createRes(); await mod.default(req, res); assert.strictEqual(res.state.statusCode, 400); assert.strictEqual( res.state.jsonBody.error.code, "FORM_COLLECTION_NOT_FOUND" ); }); test("generateappealpdfcopy success returns pdf buffer and headers", async () => { const mod = loadModule("pages/api/file/generateappealpdfcopy.js", { respondError: respondErrorMock, getCaseByID: async () => [ { pinswg_appealcasetype: 846040000, ticketnumber: "CAS-1", description: "desc" } ], getPortalModuleDetails: async () => ({ value: [{}] }), getAppealPDFDocs: async () => [{ id: "d1" }], getFormCollectionByID: () => ({ UrlName: "planningappeals78", LogicalCollectionName: "pinswg_planningappeals78s" }), getPickLists: async () => ({ a: 1 }), planningappeals78_pdf: () => ({ type: "pdfComponent" }), other_pdf: () => ({ type: "otherComponent" }), pdf: () => ({ toBuffer: async () => Buffer.from("pdf-content") }) }); const req = { body: { docProps: "i1" } }; const res = createRes(); await mod.default(req, res); assert.strictEqual(res.state.headers["content-type"], "application/pdf"); assert.strictEqual( typeof res.state.headers["content-disposition"], "string" ); assert.strictEqual(res.state.sentBody.toString(), "pdf-content"); }); test("generateappealpdfcopy catch path returns APPEAL_PDF_COPY_GENERATION_FAILED", async () => { const mod = loadModule("pages/api/file/generateappealpdfcopy.js", { respondError: respondErrorMock, getCaseByID: async () => [ { pinswg_appealcasetype: 846040000, ticketnumber: "CAS-1", description: "desc" } ], getPortalModuleDetails: async () => ({ value: [{}] }), getAppealPDFDocs: async () => [{ id: "d1" }], getFormCollectionByID: () => ({ UrlName: "planningappeals78", LogicalCollectionName: "pinswg_planningappeals78s" }), getPickLists: async () => ({ a: 1 }), planningappeals78_pdf: () => ({ type: "pdfComponent" }), other_pdf: () => ({ type: "otherComponent" }), pdf: () => ({ toBuffer: async () => { throw new Error("pdf failure"); } }) }); const req = { body: { docProps: "i1" } }; const res = createRes(); await mod.default(req, res); assert.strictEqual(res.state.statusCode, 400); assert.strictEqual( res.state.jsonBody.error.code, "APPEAL_PDF_COPY_GENERATION_FAILED" ); }); const run = async () => { let passed = 0; for (const currentTest of tests) { await currentTest.fn(); passed += 1; } console.log( `Phase 21 file-handler contract tests passed (${passed}/${tests.length}).` ); }; module.exports = run; if (require.main === module) { run().catch((error) => { console.error(error); process.exit(1); }); }