diff --git a/editor.planx.uk/src/@planx/components/Pay/Public/FeeBreakdown/utils.test.ts b/editor.planx.uk/src/@planx/components/Pay/Public/FeeBreakdown/utils.test.ts new file mode 100644 index 0000000000..25e52596b9 --- /dev/null +++ b/editor.planx.uk/src/@planx/components/Pay/Public/FeeBreakdown/utils.test.ts @@ -0,0 +1,71 @@ +import { PassportFeeFields } from "./types"; +import { calculateReduction, toFeeBreakdown, toNumber } from "./utils"; + +describe("toNumber() helper function", () => { + it("outputs a number when passed a number", () => { + const input = 12; + const output = toNumber(input); + + expect(output).toEqual(input); + }); + + it("outputs a number when passed a number tuple", () => { + const input: [number] = [12]; + const output = toNumber(input); + + expect(output).toEqual(12); + }); +}); + +describe("calculateReduction() helper function", () => { + it("correctly outputs the reduction when a calculated value is provided", () => { + const input: PassportFeeFields = { + "application.fee.calculated": 100, + "application.fee.payable": 50, + "application.fee.payable.vat": 0, + }; + const reduction = calculateReduction(input); + + expect(reduction).toEqual(50); + }); + + it("defaults to 0 when calculated is 0", () => { + const input: PassportFeeFields = { + "application.fee.calculated": 0, + "application.fee.payable": 100, + "application.fee.payable.vat": 0, + }; + const reduction = calculateReduction(input); + + expect(reduction).toEqual(0); + }); +}); + +describe("toFeeBreakdown() helper function", () => { + it("correctly maps fields", () => { + const input: PassportFeeFields = { + "application.fee.calculated": 100, + "application.fee.payable": 50, + "application.fee.payable.vat": 10, + }; + + const output = toFeeBreakdown(input); + + expect(output.applicationFee).toEqual(input["application.fee.calculated"]); + expect(output.total).toEqual(input["application.fee.payable"]); + expect(output.vat).toEqual(input["application.fee.payable.vat"]); + expect(output.reduction).toEqual(50); + }); + + it("sets applicationFee to payable amount if no calculated value is provided", () => { + const input: PassportFeeFields = { + "application.fee.calculated": 0, + "application.fee.payable": 50, + "application.fee.payable.vat": 10, + }; + + const output = toFeeBreakdown(input); + + expect(output.applicationFee).toEqual(input["application.fee.payable"]); + }); +}); diff --git a/editor.planx.uk/src/@planx/components/Pay/Public/FeeBreakdown/utils.ts b/editor.planx.uk/src/@planx/components/Pay/Public/FeeBreakdown/utils.ts index 90c76d260d..cd8b41c859 100644 --- a/editor.planx.uk/src/@planx/components/Pay/Public/FeeBreakdown/utils.ts +++ b/editor.planx.uk/src/@planx/components/Pay/Public/FeeBreakdown/utils.ts @@ -2,15 +2,15 @@ import { z } from "zod"; import { FeeBreakdown, PassportFeeFields } from "./types"; -const toNumber = (input: number | number[]) => - Array.isArray(input) ? Number(input[0]) : input; +export const toNumber = (input: number | [number]) => + Array.isArray(input) ? input[0] : input; -const calculateReduction = (data: PassportFeeFields) => +export const calculateReduction = (data: PassportFeeFields) => data["application.fee.calculated"] ? data["application.fee.calculated"] - data["application.fee.payable"] : 0; -const toFeeBreakdown = (data: PassportFeeFields): FeeBreakdown => ({ +export const toFeeBreakdown = (data: PassportFeeFields): FeeBreakdown => ({ applicationFee: data["application.fee.calculated"] || data["application.fee.payable"], total: data["application.fee.payable"], @@ -19,8 +19,8 @@ const toFeeBreakdown = (data: PassportFeeFields): FeeBreakdown => ({ }); export const createPassportSchema = () => { - const questionSchema = z.number(); - const setValueSchema = z.array(z.coerce.number()); + const questionSchema = z.number().positive(); + const setValueSchema = z.tuple([z.coerce.number().positive()]); const feeSchema = z .union([questionSchema, setValueSchema]) .transform(toNumber);