feature/IO-2769-Job-Totals-testing: Setup testing method for job totals
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -127,4 +127,4 @@ vitest-report*/
|
|||||||
vitest-coverage/
|
vitest-coverage/
|
||||||
*.vitest.log
|
*.vitest.log
|
||||||
test-output.txt
|
test-output.txt
|
||||||
|
server/job/test/fixtures
|
||||||
|
|||||||
@@ -56,4 +56,5 @@ COPY . .
|
|||||||
EXPOSE 4000 9229
|
EXPOSE 4000 9229
|
||||||
|
|
||||||
# Start the application
|
# Start the application
|
||||||
CMD ["nodemon", "--legacy-watch", "--inspect=0.0.0.0:9229", "server.js"]
|
RUN echo "Starting the application..."
|
||||||
|
CMD ["nodemon", "--ignore", "./server/job/test/fixtures", "--legacy-watch", "--inspect=0.0.0.0:9229", "server.js"]
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
const Dinero = require("dinero.js");
|
const Dinero = require("dinero.js");
|
||||||
const queries = require("../graphql-client/queries");
|
const queries = require("../graphql-client/queries");
|
||||||
// const adminClient = require("../graphql-client/graphql-client").client;
|
|
||||||
// const _ = require("lodash");
|
|
||||||
const logger = require("../utils/logger");
|
const logger = require("../utils/logger");
|
||||||
|
const { captureFixture } = require("./utils/seralizeHelper");
|
||||||
const InstanceMgr = require("../utils/instanceMgr").default;
|
const InstanceMgr = require("../utils/instanceMgr").default;
|
||||||
|
|
||||||
//****************************************************** */
|
//****************************************************** */
|
||||||
@@ -33,7 +32,15 @@ exports.totalsSsu = async function (req, res) {
|
|||||||
id: id
|
id: id
|
||||||
});
|
});
|
||||||
|
|
||||||
const newTotals = await TotalsServerSide({ body: { job: job.jobs_by_pk, client: client } }, res, true);
|
// Extract the job data (the input for TotalsServerSide)
|
||||||
|
const inputForTotals = job.jobs_by_pk;
|
||||||
|
|
||||||
|
const newTotals = await TotalsServerSide({ body: { job: inputForTotals, client: client } }, res, true);
|
||||||
|
|
||||||
|
// Capture fixture data (input and output), using job.id for the filename.
|
||||||
|
if (process.env?.SAVE_TOTALS_DATA) {
|
||||||
|
captureFixture(inputForTotals, inputForTotals, newTotals);
|
||||||
|
}
|
||||||
|
|
||||||
const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, {
|
const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, {
|
||||||
jobId: id,
|
jobId: id,
|
||||||
@@ -45,9 +52,11 @@ exports.totalsSsu = async function (req, res) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result) {
|
if (!result) {
|
||||||
res.status(200).send();
|
throw new Error("Failed to update job totals");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res.status(200).send();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.log("job-totals-ssu-USA-error", "ERROR", req?.user?.email, id, {
|
logger.log("job-totals-ssu-USA-error", "ERROR", req?.user?.email, id, {
|
||||||
jobid: id,
|
jobid: id,
|
||||||
@@ -58,7 +67,7 @@ exports.totalsSsu = async function (req, res) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//IMPORTANT*** These two functions MUST be mirrrored.
|
//IMPORTANT*** These two functions MUST be mirrored.
|
||||||
async function TotalsServerSide(req, res) {
|
async function TotalsServerSide(req, res) {
|
||||||
const { job, client } = req.body;
|
const { job, client } = req.body;
|
||||||
await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user });
|
await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user });
|
||||||
@@ -133,6 +142,9 @@ async function TotalsServerSide(req, res) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exported for testing purposes.
|
||||||
|
exports.TotalsServerSide = TotalsServerSide;
|
||||||
|
|
||||||
async function Totals(req, res) {
|
async function Totals(req, res) {
|
||||||
const { job, id } = req.body;
|
const { job, id } = req.body;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const Dinero = require("dinero.js");
|
const Dinero = require("dinero.js");
|
||||||
const queries = require("../graphql-client/queries");
|
const queries = require("../graphql-client/queries");
|
||||||
const logger = require("../utils/logger");
|
const logger = require("../utils/logger");
|
||||||
|
const { captureFixture } = require("./utils/seralizeHelper");
|
||||||
|
|
||||||
//****************************************************** */
|
//****************************************************** */
|
||||||
//****************************************************** */
|
//****************************************************** */
|
||||||
@@ -30,7 +31,16 @@ exports.totalsSsu = async function (req, res) {
|
|||||||
id: id
|
id: id
|
||||||
});
|
});
|
||||||
|
|
||||||
const newTotals = await TotalsServerSide({ body: { job: job.jobs_by_pk, client: client } }, res, true);
|
// Extract the job data (the input for TotalsServerSide)
|
||||||
|
const inputForTotals = job.jobs_by_pk;
|
||||||
|
|
||||||
|
// Capture the output of TotalsServerSide
|
||||||
|
const newTotals = await TotalsServerSide({ body: { job: inputForTotals, client: client } }, res, true);
|
||||||
|
|
||||||
|
// Capture fixture data (input and output), using job.id for the filename.
|
||||||
|
if (process.env?.SAVE_TOTALS_DATA) {
|
||||||
|
captureFixture(inputForTotals, inputForTotals, newTotals);
|
||||||
|
}
|
||||||
|
|
||||||
const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, {
|
const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB, {
|
||||||
jobId: id,
|
jobId: id,
|
||||||
@@ -57,7 +67,7 @@ exports.totalsSsu = async function (req, res) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//IMPORTANT*** These two functions MUST be mirrrored.
|
//IMPORTANT*** These two functions MUST be mirrored.
|
||||||
async function TotalsServerSide(req, res) {
|
async function TotalsServerSide(req, res) {
|
||||||
const { job, client } = req.body;
|
const { job, client } = req.body;
|
||||||
await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user });
|
await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user });
|
||||||
@@ -81,6 +91,9 @@ async function TotalsServerSide(req, res) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exported for testing purposes
|
||||||
|
exports.TotalsServerSide = TotalsServerSide;
|
||||||
|
|
||||||
async function Totals(req, res) {
|
async function Totals(req, res) {
|
||||||
const { job, id } = req.body;
|
const { job, id } = req.body;
|
||||||
|
|
||||||
|
|||||||
68
server/job/test/job-totals.test.js
Normal file
68
server/job/test/job-totals.test.js
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
import { describe, it, expect } from "vitest";
|
||||||
|
import { TotalsServerSide } from "../job-totals"; // adjust the path as needed
|
||||||
|
import Dinero from "dinero.js";
|
||||||
|
|
||||||
|
// A custom replacer to normalize Dinero objects
|
||||||
|
function dineroReplacer(key, value) {
|
||||||
|
if (value && typeof value === "object" && typeof value.toObject === "function") {
|
||||||
|
return value.toObject();
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalization function to convert any Dinero instances to plain objects
|
||||||
|
function normalizeOutput(obj) {
|
||||||
|
return JSON.parse(JSON.stringify(obj, dineroReplacer));
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("TotalsServerSide fixture tests", () => {
|
||||||
|
// Define the fixture directory.
|
||||||
|
// For example, if this test file is at <projectroot>/server/job/test/,
|
||||||
|
// then the fixtures are in <projectroot>/server/job/test/fixtures/job-totals/
|
||||||
|
const fixturesDir = path.join(__dirname, "fixtures", "job-totals");
|
||||||
|
|
||||||
|
// Read all fixture JSON files from the fixture directory.
|
||||||
|
const fixtureFiles = fs.readdirSync(fixturesDir).filter((f) => f.endsWith(".json"));
|
||||||
|
|
||||||
|
// Create a dummy client. If your TotalsServerSide uses client.request,
|
||||||
|
// make sure these paths are either not triggered or stubbed accordingly.
|
||||||
|
const dummyClient = {
|
||||||
|
request: async () => {
|
||||||
|
// Return an empty object (or any other value that makes sense for your tests).
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a dummy response object. TotalsServerSide might only use it to send error statuses.
|
||||||
|
const dummyRes = {
|
||||||
|
status: () => ({ send: () => {} })
|
||||||
|
};
|
||||||
|
|
||||||
|
fixtureFiles.forEach((file) => {
|
||||||
|
it(`should produce matching output for fixture file ${file}`, async () => {
|
||||||
|
const fixturePath = path.join(fixturesDir, file);
|
||||||
|
const fixtureData = JSON.parse(fs.readFileSync(fixturePath, "utf8"));
|
||||||
|
|
||||||
|
const { input, output: expectedOutput } = fixtureData;
|
||||||
|
|
||||||
|
const req = {
|
||||||
|
body: {
|
||||||
|
job: input,
|
||||||
|
client: dummyClient
|
||||||
|
},
|
||||||
|
user: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call the TotalsServerSide function with the fixture input.
|
||||||
|
const computedOutput = await TotalsServerSide(req, dummyRes);
|
||||||
|
|
||||||
|
// Normalize both computed and expected outputs so that any Dinero objects are replaced with their plain representation.
|
||||||
|
const normalizedComputed = normalizeOutput(computedOutput);
|
||||||
|
const normalizedExpected = normalizeOutput(expectedOutput);
|
||||||
|
|
||||||
|
expect(normalizedComputed).toEqual(normalizedExpected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
47
server/job/utils/seralizeHelper.js
Normal file
47
server/job/utils/seralizeHelper.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
const fixtureDir = path.join(__dirname, "..", "test", "fixtures", "job-totals");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom serializer for Dinero.js objects.
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
const serializeDinero = (key, value) => {
|
||||||
|
// If the value has a toObject method (as in Dinero instances), use it.
|
||||||
|
if (value && typeof value === "object" && typeof value.toObject === "function") {
|
||||||
|
return value.toObject();
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capture a fixture for job totals.
|
||||||
|
* @param job
|
||||||
|
* @param inputData
|
||||||
|
* @param outputData
|
||||||
|
*/
|
||||||
|
const captureFixture = (job, inputData, outputData) => {
|
||||||
|
if (!fs.existsSync(fixtureDir)) {
|
||||||
|
fs.mkdirSync(fixtureDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use job.id to label the file.
|
||||||
|
const fileName = `${job.id}.json`;
|
||||||
|
const filePath = path.join(fixtureDir, fileName);
|
||||||
|
|
||||||
|
const dataToSave = {
|
||||||
|
input: inputData,
|
||||||
|
output: outputData
|
||||||
|
};
|
||||||
|
|
||||||
|
// Save the file using our custom serializer.
|
||||||
|
fs.writeFileSync(filePath, JSON.stringify(dataToSave, serializeDinero, 2), "utf8");
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
captureFixture,
|
||||||
|
serializeDinero
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user