diff --git a/pages/api/endpoint/getmylpacases_api.js b/pages/api/endpoint/getmylpacases_api.js index d39dc467..47daab59 100644 --- a/pages/api/endpoint/getmylpacases_api.js +++ b/pages/api/endpoint/getmylpacases_api.js @@ -24,51 +24,72 @@ import { azureHeaders } from "../../../actions/core/headers"; import { consoleLogger } from "../../../actions/core/logger"; import { getToken } from "../../../actions/core/token"; import { hashAPIPath } from "../../../actions/core/hash"; +import { respondError, respondSuccess } from "../middleware/apiResponse"; const WEBAPI_URL = process.env.RELAY_ROOT || "https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/"; export default async function ApiProxy(req, res) { - var lpaid = req.query.lpaid; - var token = await getToken(); + const lpaid = req.query.lpaid; - const lpaList = await getLPA(); + if (typeof lpaid !== "string" || lpaid.trim().length === 0) { + return respondError(res, { + status: 400, + code: "LPA_ID_REQUIRED", + message: "lpaid is required" + }); + } - const lpaGUID = jsonpath({ - path: '$..[?(@ && @.name=="' + lpaid + '")]', - json: lpaList, - eval: true - }); + try { + const token = await getToken(); + const lpaList = await getLPA(); - //console.log( - // '$..[?(@ && @.name="' + lpaid + '")]', - // lpaList, - // lpaid, - // "LPAGUID=", - // lpaGUID - // ); + const lpaGUID = jsonpath({ + path: '$..[?(@ && @.name=="' + lpaid + '")]', + json: lpaList, + eval: true + }); - var queryUrl = - "incidents?$select=pinswg_environmentalstatementlocation,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantlastname,pinswg_appellantfirstname,pinswg_appellantagent,pinswg_agentfirstname,pinswg_agentlastname,pinswg_agentcompanyname&$expand=primarycontactid($select=fullname)&$filter=_pinswg_associatedlpa_value eq " + - lpaGUID[0].accountid + - " and servicestage eq 0 and pinswg_appealcasetype ne null&$orderby=createdon desc&$count=true"; + if (!Array.isArray(lpaGUID) || !lpaGUID[0]?.accountid) { + return respondError(res, { + status: 404, + code: "LPA_NOT_FOUND", + message: "No matching LPA found" + }); + } - //console.log("///////////\nPortal query: ", queryUrl, "<<< { - data.value.forEach(function (element) { - element.pinswg_title = element.title; - }); - res.status(200).json(data); - }) - .catch((error) => { - consoleLogger(error); - res.status(400).json(error); + ); + + data.value.forEach(function (element) { + element.pinswg_title = element.title; }); + + return respondSuccess(res, data); + } catch (error) { + consoleLogger(error); + return respondError(res, { + status: 400, + code: "MY_LPA_CASES_FETCH_FAILED", + message: "Failed to fetch my LPA cases" + }); + } } diff --git a/pages/api/endpoint/getportalmoduledetails_api.js b/pages/api/endpoint/getportalmoduledetails_api.js index 4a127a53..90c07967 100644 --- a/pages/api/endpoint/getportalmoduledetails_api.js +++ b/pages/api/endpoint/getportalmoduledetails_api.js @@ -24,44 +24,64 @@ */ import axios from "axios"; -import CryptoJS from "crypto-js"; import { azureHeaders } from "../../../actions/core/headers"; import { consoleLogger } from "../../../actions/core/logger"; import { getToken } from "../../../actions/core/token"; import { getSelectQuery } from "../../../actions/selectQueryTypes"; import { hashAPIPath } from "../../../actions/core/hash"; +import { respondError, respondSuccess } from "../middleware/apiResponse"; const WEBAPI_URL = process.env.RELAY_ROOT || "https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/"; export default async function ApiProxy(req, res) { - var appealType = req.query.appealType; - var caseReference = req.query.caseReference.split("'").join("''"); - var token = await getToken(); + const appealType = req.query.appealType; + const caseReference = req.query.caseReference; - //console.log("the case:", req.query, caseReference); + if (typeof appealType !== "string" || appealType.trim().length === 0) { + return respondError(res, { + status: 400, + code: "APPEAL_TYPE_REQUIRED", + message: "appealType is required" + }); + } - var queryUrl = - appealType + - "?$filter=pinswg_name eq '" + - caseReference + - "'&$count=true"; + if ( + typeof caseReference !== "string" || + caseReference.trim().length === 0 + ) { + return respondError(res, { + status: 400, + code: "CASE_REFERENCE_REQUIRED", + message: "caseReference is required" + }); + } - queryUrl = queryUrl + getSelectQuery(appealType); + try { + const token = await getToken(); + const escapedCaseReference = caseReference.split("'").join("''"); - //console.log("test:", WEBAPI_URL + queryUrl + hashAPIPath(queryUrl)); + let queryUrl = + appealType + + "?$filter=pinswg_name eq '" + + escapedCaseReference + + "'&$count=true"; - return axios - .get( + queryUrl = queryUrl + getSelectQuery(appealType); + + const { data } = await axios.get( WEBAPI_URL + queryUrl + hashAPIPath(queryUrl), azureHeaders(token.access_token) - ) - .then(({ data }) => { - res.status(200).json(data); - }) - .catch((error) => { - consoleLogger(error); - res.status(400).json(error); + ); + + return respondSuccess(res, data); + } catch (error) { + consoleLogger(error); + return respondError(res, { + status: 400, + code: "PORTAL_MODULE_DETAILS_FETCH_FAILED", + message: "Failed to fetch portal module details" }); + } } diff --git a/pages/api/endpoint/getportalmoduledetailsproxy_api.js b/pages/api/endpoint/getportalmoduledetailsproxy_api.js index 5b833c8c..76e4f05e 100644 --- a/pages/api/endpoint/getportalmoduledetailsproxy_api.js +++ b/pages/api/endpoint/getportalmoduledetailsproxy_api.js @@ -24,40 +24,64 @@ */ import axios from "axios"; -import CryptoJS from "crypto-js"; import { azureHeaders } from "../../../actions/core/headers"; import { consoleLogger } from "../../../actions/core/logger"; import { getToken } from "../../../actions/core/token"; import { getSelectQuery } from "../../../actions/selectQueryTypes"; import { hashAPIPath } from "../../../actions/core/hash"; +import { respondError, respondSuccess } from "../middleware/apiResponse"; const WEBAPI_URL = process.env.RELAY_ROOT || "https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/"; export default async function ApiProxy(req, res) { - var appealType = req.query.appealType; - var caseReference = req.query.caseReference; - var token = await getToken(); + const appealType = req.query.appealType; + const caseReference = req.query.caseReference; - var queryUrl = - appealType + - "?$filter=pinswg_name eq '" + - caseReference + - "'&$count=true"; + if (typeof appealType !== "string" || appealType.trim().length === 0) { + return respondError(res, { + status: 400, + code: "APPEAL_TYPE_REQUIRED", + message: "appealType is required" + }); + } - queryUrl = queryUrl + getSelectQuery(appealType); + if ( + typeof caseReference !== "string" || + caseReference.trim().length === 0 + ) { + return respondError(res, { + status: 400, + code: "CASE_REFERENCE_REQUIRED", + message: "caseReference is required" + }); + } - return axios - .get( + try { + const token = await getToken(); + const escapedCaseReference = caseReference.split("'").join("''"); + + let queryUrl = + appealType + + "?$filter=pinswg_name eq '" + + escapedCaseReference + + "'&$count=true"; + + queryUrl = queryUrl + getSelectQuery(appealType); + + const { data } = await axios.get( WEBAPI_URL + queryUrl + hashAPIPath(queryUrl), azureHeaders(token.access_token) - ) - .then(({ data }) => { - res.status(200).json(data); - }) - .catch((error) => { - consoleLogger(error); - res.status(400).json(error); + ); + + return respondSuccess(res, data); + } catch (error) { + consoleLogger(error); + return respondError(res, { + status: 400, + code: "PORTAL_MODULE_DETAILS_PROXY_FETCH_FAILED", + message: "Failed to fetch portal module details proxy" }); + } } diff --git a/tests/phase21/endpoint-handler-contract.test.cjs b/tests/phase21/endpoint-handler-contract.test.cjs index 56aaf536..1cb9ea97 100644 --- a/tests/phase21/endpoint-handler-contract.test.cjs +++ b/tests/phase21/endpoint-handler-contract.test.cjs @@ -1967,6 +1967,186 @@ test("getbasicdnssearchdetailspaged catch path returns BASIC_DNS_SEARCH_DETAILS_ ); }); +test("getportalmoduledetails returns APPEAL_TYPE_REQUIRED when appealType missing", async () => { + const mod = loadModule("pages/api/endpoint/getportalmoduledetails_api.js", { + respondError: respondErrorMock, + respondSuccess: respondSuccessMock, + getToken: async () => ({ access_token: "token" }), + getSelectQuery: () => "&$select=pinswg_name", + hashAPIPath: () => "&hash=expected", + azureHeaders: () => ({}), + axios: { get: async () => ({ data: { value: [] } }) }, + consoleLogger: () => {} + }); + + const req = { query: { caseReference: "CAS-1" } }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual(res.state.jsonBody.error.code, "APPEAL_TYPE_REQUIRED"); +}); + +test("getportalmoduledetails catch path returns PORTAL_MODULE_DETAILS_FETCH_FAILED", async () => { + const mod = loadModule("pages/api/endpoint/getportalmoduledetails_api.js", { + respondError: respondErrorMock, + respondSuccess: respondSuccessMock, + getToken: async () => ({ access_token: "token" }), + getSelectQuery: () => "&$select=pinswg_name", + hashAPIPath: () => "&hash=expected", + azureHeaders: () => ({}), + axios: { + get: async () => { + throw new Error("relay failed"); + } + }, + consoleLogger: () => {} + }); + + const req = { + query: { + appealType: "pinswg_planningappeals78s", + caseReference: "CAS-1" + } + }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual( + res.state.jsonBody.error.code, + "PORTAL_MODULE_DETAILS_FETCH_FAILED" + ); +}); + +test("getportalmoduledetailsproxy returns APPEAL_TYPE_REQUIRED when appealType missing", async () => { + const mod = loadModule( + "pages/api/endpoint/getportalmoduledetailsproxy_api.js", + { + respondError: respondErrorMock, + respondSuccess: respondSuccessMock, + getToken: async () => ({ access_token: "token" }), + getSelectQuery: () => "&$select=pinswg_name", + hashAPIPath: () => "&hash=expected", + azureHeaders: () => ({}), + axios: { get: async () => ({ data: { value: [] } }) }, + consoleLogger: () => {} + } + ); + + const req = { query: { caseReference: "CAS-1" } }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual(res.state.jsonBody.error.code, "APPEAL_TYPE_REQUIRED"); +}); + +test("getportalmoduledetailsproxy catch path returns PORTAL_MODULE_DETAILS_PROXY_FETCH_FAILED", async () => { + const mod = loadModule( + "pages/api/endpoint/getportalmoduledetailsproxy_api.js", + { + respondError: respondErrorMock, + respondSuccess: respondSuccessMock, + getToken: async () => ({ access_token: "token" }), + getSelectQuery: () => "&$select=pinswg_name", + hashAPIPath: () => "&hash=expected", + azureHeaders: () => ({}), + axios: { + get: async () => { + throw new Error("relay failed"); + } + }, + consoleLogger: () => {} + } + ); + + const req = { + query: { + appealType: "pinswg_planningappeals78s", + caseReference: "CAS-1" + } + }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual( + res.state.jsonBody.error.code, + "PORTAL_MODULE_DETAILS_PROXY_FETCH_FAILED" + ); +}); + +test("getmylpacases returns LPA_ID_REQUIRED when lpaid missing", async () => { + const mod = loadModule("pages/api/endpoint/getmylpacases_api.js", { + respondError: respondErrorMock, + respondSuccess: respondSuccessMock, + getToken: async () => ({ access_token: "token" }), + getLPA: async () => [{ name: "Test LPA", accountid: "acc1" }], + jsonpath: () => [{ accountid: "acc1" }], + hashAPIPath: () => "&hash=expected", + azureHeaders: () => ({}), + axios: { get: async () => ({ data: { value: [] } }) }, + consoleLogger: () => {} + }); + + const req = { query: {} }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual(res.state.jsonBody.error.code, "LPA_ID_REQUIRED"); +}); + +test("getmylpacases returns LPA_NOT_FOUND when lpaid lookup misses", async () => { + const mod = loadModule("pages/api/endpoint/getmylpacases_api.js", { + respondError: respondErrorMock, + respondSuccess: respondSuccessMock, + getToken: async () => ({ access_token: "token" }), + getLPA: async () => [{ name: "Another LPA", accountid: "acc1" }], + jsonpath: () => [], + hashAPIPath: () => "&hash=expected", + azureHeaders: () => ({}), + axios: { get: async () => ({ data: { value: [] } }) }, + consoleLogger: () => {} + }); + + const req = { query: { lpaid: "Missing LPA" } }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(res.state.statusCode, 404); + assert.strictEqual(res.state.jsonBody.error.code, "LPA_NOT_FOUND"); +}); + +test("getmylpacases catch path returns MY_LPA_CASES_FETCH_FAILED", async () => { + const mod = loadModule("pages/api/endpoint/getmylpacases_api.js", { + respondError: respondErrorMock, + respondSuccess: respondSuccessMock, + getToken: async () => ({ access_token: "token" }), + getLPA: async () => [{ name: "Test LPA", accountid: "acc1" }], + jsonpath: () => [{ accountid: "acc1" }], + hashAPIPath: () => "&hash=expected", + azureHeaders: () => ({}), + axios: { + get: async () => { + throw new Error("relay failed"); + } + }, + consoleLogger: () => {} + }); + + const req = { query: { lpaid: "Test LPA" } }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(res.state.statusCode, 400); + assert.strictEqual( + res.state.jsonBody.error.code, + "MY_LPA_CASES_FETCH_FAILED" + ); +}); + const run = async () => { let passed = 0; for (const currentTest of tests) {