Skip to content

Commit

Permalink
feat(EMS-3877): business - turnover currency - save and back
Browse files Browse the repository at this point in the history
  • Loading branch information
ttbarnes committed Sep 27, 2024
1 parent e46af91 commit 98e84ec
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const {
const baseUrl = Cypress.config('baseUrl');

context(
'Insurance - Your business - Turnover - Alternative currency page - As an Exporter I want to enter the turnover of my business so that UKEF can have clarity on my business financial position when processing my Export Insurance Application',
'Insurance - Your business - Turnover - Currency page - As an Exporter I want to enter the turnover of my business so that UKEF can have clarity on my business financial position when processing my Export Insurance Application',
() => {
let referenceNumber;
let url;
Expand Down Expand Up @@ -70,7 +70,6 @@ context(
const { rendering, formSubmission } = assertCurrencyFormFields({
errors: ERRORS,
expectedRedirectUrl: TURNOVER_ROOT,
hasSaveAndBack: false,
});

rendering();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ context(
const { rendering, formSubmission } = assertCurrencyFormFields({
errors: ERRORS,
expectedRedirectUrl: OUTSTANDING_OR_OVERDUE_PAYMENTS,
hasSaveAndBack: false,
});

rendering();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ const { ALL_SECTIONS } = INSURANCE_ROUTES;
* @param {Function} submitAlternativeCurrencyAndAssertUrl: Submit an alternative currency and assert the URL.
* @param {Function} submitAlternativeCurrencyAndAssertInput: Submit an alternative currency and assert the input.
* @param {Function} completeNonCurrencyFieldsFunction: Optional function to complete non-currency form fields.
* @param {Boolean} hasSaveAndBack: Temporary Flag for if the form has "save and back" functionality
* @returns {Object} Object with Mocha describe blocks and assertions for particular scenarios.
*/
const formSubmissionAssertions = ({
Expand All @@ -28,7 +27,6 @@ const formSubmissionAssertions = ({
submitAlternativeCurrencyAndAssertUrl,
submitAlternativeCurrencyAndAssertInput,
completeNonCurrencyFieldsFunction,
hasSaveAndBack,
}) => {
const executeTests = () => {
describe('currency form fields - form submission', () => {
Expand All @@ -49,24 +47,22 @@ const formSubmissionAssertions = ({
});
});

if (hasSaveAndBack) {
describe('via `save and back` button', () => {
submitASupportedCurrency({
completeNonCurrencyFieldsFunction,
submitRadioAndAssertUrl,
submitAndAssertRadioIsChecked,
expectedRedirectUrl: ALL_SECTIONS,
viaSaveAndBack: true,
});
describe('via `save and back` button', () => {
submitASupportedCurrency({
completeNonCurrencyFieldsFunction,
submitRadioAndAssertUrl,
submitAndAssertRadioIsChecked,
expectedRedirectUrl: ALL_SECTIONS,
viaSaveAndBack: true,
});

submitAlternativeCurrency({
expectedRedirectUrl: ALL_SECTIONS,
submitAlternativeCurrencyAndAssertUrl,
submitAlternativeCurrencyAndAssertInput,
viaSaveAndBack: true,
});
submitAlternativeCurrency({
expectedRedirectUrl: ALL_SECTIONS,
submitAlternativeCurrencyAndAssertUrl,
submitAlternativeCurrencyAndAssertInput,
viaSaveAndBack: true,
});
}
});
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ const {
* @param {Function} hint: Hint selector
* @param {Function} legend: Legend selector
* @param {String} expectedRedirectUrl: Page URL to assert after successful form submission
* @param {Boolean} hasSaveAndBack: Temporary Flag for if the form has "save and back" functionality
* @returns {Object} Rendering and form submission assertion functions
*/
export const assertCurrencyFormFields = ({
Expand All @@ -34,7 +33,6 @@ export const assertCurrencyFormFields = ({
hint,
legend,
expectedRedirectUrl,
hasSaveAndBack,
}) => {
const assertions = fieldAssertions({
alternativeCurrencyText: FIELDS[ALTERNATIVE_CURRENCY_CODE].TEXT,
Expand All @@ -52,7 +50,6 @@ export const assertCurrencyFormFields = ({
completeNonCurrencyFieldsFunction,
errorIndex,
expectedRedirectUrl,
hasSaveAndBack,
}),
prefixAssertions: () => prefixAssertions({ fieldId, clickAlternativeCurrencyLink }),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ export const PAGE_VARIABLES = {
};

/**
* gets the template for Business - Turnover - Alternative currency page
* gets the template for Business - Turnover - Currency page
* @param {Express.Request} Express request
* @param {Express.Response} Express response
* @returns {Express.Response.render} renders Business - Turnover - Alternative currency page with/without previously submitted details
* @returns {Express.Response.render} renders Business - Turnover - Currency page with/without previously submitted details
*/
export const get = async (req: Request, res: Response) => {
try {
Expand Down Expand Up @@ -85,7 +85,7 @@ export const get = async (req: Request, res: Response) => {

/**
* post
* Check Business - Turnover - Alternative currency page validation errors and if successful, redirect to the next part of the flow.
* Check Business - Turnover - Currency page validation errors and if successful, redirect to the next part of the flow.
* @param {Express.Request} Express request
* @param {Express.Response} Express response
* @returns {Express.Response.redirect} Next part of the flow or error page
Expand Down Expand Up @@ -151,7 +151,7 @@ export const post = async (req: Request, res: Response) => {

return res.redirect(`${INSURANCE_ROOT}/${referenceNumber}${TURNOVER_ROOT}`);
} catch (error) {
console.error('Error posting Business - Turnover currency %O', error);
console.error('Error posting business - turnover currency %O', error);

return res.redirect(PROBLEM_WITH_SERVICE);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { FIELD_IDS } from '..';
import { post } from '.';
import { INSURANCE_ROUTES } from '../../../../../constants/routes/insurance';
import INSURANCE_FIELD_IDS from '../../../../../constants/field-ids/insurance';
import constructPayload from '../../../../../helpers/construct-payload';
import generateValidationErrors from '../validation';
import mapAndSave from '../../map-and-save/turnover';
import { Request, Response } from '../../../../../../types';
import { EUR, mockReq, mockRes, mockSpyPromiseRejection, referenceNumber } from '../../../../../test-mocks';

const {
CURRENCY: { CURRENCY_CODE },
} = INSURANCE_FIELD_IDS;

const { INSURANCE_ROOT, ALL_SECTIONS, PROBLEM_WITH_SERVICE } = INSURANCE_ROUTES;

describe('controllers/insurance/business/turnover-currency/save-and-back', () => {
let req: Request;
let res: Response;

jest.mock('../../map-and-save/turnover');

let mapAndSaveSpy = jest.fn(() => Promise.resolve(true));

const mockFormBody = {
[CURRENCY_CODE]: EUR.isoCode,
};

beforeEach(() => {
req = mockReq();
res = mockRes();

req.body = mockFormBody;

mapAndSave.turnover = mapAndSaveSpy;
});

afterAll(() => {
jest.resetAllMocks();
});

describe('when the form has data', () => {
beforeEach(() => {
jest.resetAllMocks();

mapAndSaveSpy = jest.fn(() => Promise.resolve(true));
mapAndSave.turnover = mapAndSaveSpy;
});

it('should call mapAndSave.turnover with data from constructPayload function, application and validationErrors', async () => {
await post(req, res);

const payload = constructPayload(req.body, FIELD_IDS);

const validationErrors = generateValidationErrors(payload);

expect(mapAndSave.turnover).toHaveBeenCalledTimes(1);
expect(mapAndSave.turnover).toHaveBeenCalledWith(payload, res.locals.application, validationErrors);
});

it(`should redirect to ${ALL_SECTIONS}`, async () => {
mapAndSave.turnover = mapAndSaveSpy;

await post(req, res);

const expected = `${INSURANCE_ROOT}/${referenceNumber}${ALL_SECTIONS}`;

expect(res.redirect).toHaveBeenCalledWith(expected);
});
});

describe('when the form does not have any data', () => {
it(`should redirect to ${ALL_SECTIONS}`, async () => {
req.body = { _csrf: '1234' };

await post(req, res);

const expected = `${INSURANCE_ROOT}/${referenceNumber}${ALL_SECTIONS}`;

expect(res.redirect).toHaveBeenCalledWith(expected);
});
});

describe('when there is no application', () => {
beforeEach(() => {
delete res.locals.application;
});

it(`should redirect to ${PROBLEM_WITH_SERVICE}`, async () => {
await post(req, res);

expect(res.redirect).toHaveBeenCalledWith(PROBLEM_WITH_SERVICE);
});
});

describe('api error handling', () => {
describe('when mapAndSave.turnover returns false', () => {
beforeEach(() => {
res.locals = mockRes().locals;
mapAndSaveSpy = jest.fn(() => Promise.resolve(false));
mapAndSave.turnover = mapAndSaveSpy;
});

it(`should redirect to ${PROBLEM_WITH_SERVICE}`, async () => {
await post(req, res);

expect(res.redirect).toHaveBeenCalledWith(PROBLEM_WITH_SERVICE);
});
});

describe('when mapAndSave.turnover fails', () => {
beforeEach(() => {
res.locals = mockRes().locals;
mapAndSaveSpy = mockSpyPromiseRejection;
mapAndSave.turnover = mapAndSaveSpy;
});

it(`should redirect to ${PROBLEM_WITH_SERVICE}`, async () => {
await post(req, res);

expect(res.redirect).toHaveBeenCalledWith(PROBLEM_WITH_SERVICE);
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { INSURANCE_ROUTES } from '../../../../../constants/routes/insurance';
import hasFormData from '../../../../../helpers/has-form-data';
import { FIELD_IDS } from '..';
import constructPayload from '../../../../../helpers/construct-payload';
import generateValidationErrors from '../validation';
import mapAndSave from '../../map-and-save/turnover';
import { Request, Response } from '../../../../../../types';

const { INSURANCE_ROOT, ALL_SECTIONS, PROBLEM_WITH_SERVICE } = INSURANCE_ROUTES;

/**
* post
* Save any valid currency of Business - Turnover - Currency form fields and if successful, redirect to the all sections page
* @param {Express.Request} Express request
* @param {Express.Response} Express response
* @returns {Express.Response.redirect} All sections page or error page
*/
export const post = async (req: Request, res: Response) => {
try {
const { application } = res.locals;

if (!application) {
return res.redirect(PROBLEM_WITH_SERVICE);
}

const { referenceNumber } = req.params;

/**
* If form data is populated:
* 1) generate a payload.
* 2) generate validation errors.
* 3) call mapAndSave
* 4) redirect
*/
if (hasFormData(req.body)) {
const payload = constructPayload(req.body, FIELD_IDS);

const validationErrors = generateValidationErrors(payload);

const saveResponse = await mapAndSave.turnover(payload, application, validationErrors);

if (!saveResponse) {
return res.redirect(PROBLEM_WITH_SERVICE);
}
}

return res.redirect(`${INSURANCE_ROOT}/${referenceNumber}${ALL_SECTIONS}`);
} catch (error) {
console.error('Error updating application - business - turnover currency (save and back) %O', error);

return res.redirect(PROBLEM_WITH_SERVICE);
}
};
4 changes: 3 additions & 1 deletion src/ui/server/routes/insurance/business/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { get as getTurnover, post as postTurnover } from '../../../controllers/i
import { post as postTurnoverSaveAndBack } from '../../../controllers/insurance/business/turnover/save-and-back';

import { get as getTurnoverCurrency, post as postTurnoverCurrency } from '../../../controllers/insurance/business/turnover-currency';
import { post as postTurnoverCurrencySaveAndBack } from '../../../controllers/insurance/business/turnover-currency/save-and-back';

import { get as getCreditControl, post as postCreditControl } from '../../../controllers/insurance/business/credit-control';
import { post as postCreditControlSaveAndBack } from '../../../controllers/insurance/business/credit-control/save-and-back';
Expand All @@ -40,7 +41,7 @@ describe('routes/insurance/your-business', () => {

it('should setup all routes', () => {
expect(get).toHaveBeenCalledTimes(28);
expect(post).toHaveBeenCalledTimes(32);
expect(post).toHaveBeenCalledTimes(33);

expect(get).toHaveBeenCalledWith(ROUTES.INSURANCE.EXPORTER_BUSINESS.ROOT, getYourBusiness);

Expand Down Expand Up @@ -84,6 +85,7 @@ describe('routes/insurance/your-business', () => {

expect(get).toHaveBeenCalledWith(ROUTES.INSURANCE.EXPORTER_BUSINESS.TURNOVER_CURRENCY_ROOT, getTurnoverCurrency);
expect(post).toHaveBeenCalledWith(ROUTES.INSURANCE.EXPORTER_BUSINESS.TURNOVER_CURRENCY_ROOT, postTurnoverCurrency);
expect(post).toHaveBeenCalledWith(ROUTES.INSURANCE.EXPORTER_BUSINESS.TURNOVER_CURRENCY_SAVE_AND_BACK, postTurnoverCurrencySaveAndBack);
expect(get).toHaveBeenCalledWith(ROUTES.INSURANCE.EXPORTER_BUSINESS.TURNOVER_CURRENCY_CHANGE, getTurnoverCurrency);
expect(post).toHaveBeenCalledWith(ROUTES.INSURANCE.EXPORTER_BUSINESS.TURNOVER_CURRENCY_CHANGE, postTurnoverCurrency);
expect(get).toHaveBeenCalledWith(ROUTES.INSURANCE.EXPORTER_BUSINESS.TURNOVER_CURRENCY_CHECK_AND_CHANGE, getTurnoverCurrency);
Expand Down
2 changes: 2 additions & 0 deletions src/ui/server/routes/insurance/business/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { get as getTurnover, post as postTurnover } from '../../../controllers/i
import { post as postTurnoverSaveAndBack } from '../../../controllers/insurance/business/turnover/save-and-back';

import { get as getTurnoverCurrency, post as postTurnoverCurrency } from '../../../controllers/insurance/business/turnover-currency';
import { post as postTurnoverCurrencySaveAndBack } from '../../../controllers/insurance/business/turnover-currency/save-and-back';

import { get as getCreditControl, post as postCreditControl } from '../../../controllers/insurance/business/credit-control';
import { post as postCreditControlSaveAndBack } from '../../../controllers/insurance/business/credit-control/save-and-back';
Expand Down Expand Up @@ -79,6 +80,7 @@ insuranceBusinessRouter.post(`/:referenceNumber${ROUTES.INSURANCE.EXPORTER_BUSIN

insuranceBusinessRouter.get(`/:referenceNumber${ROUTES.INSURANCE.EXPORTER_BUSINESS.TURNOVER_CURRENCY_ROOT}`, getTurnoverCurrency);
insuranceBusinessRouter.post(`/:referenceNumber${ROUTES.INSURANCE.EXPORTER_BUSINESS.TURNOVER_CURRENCY_ROOT}`, postTurnoverCurrency);
insuranceBusinessRouter.post(`/:referenceNumber${ROUTES.INSURANCE.EXPORTER_BUSINESS.TURNOVER_CURRENCY_SAVE_AND_BACK}`, postTurnoverCurrencySaveAndBack);
insuranceBusinessRouter.get(`/:referenceNumber${ROUTES.INSURANCE.EXPORTER_BUSINESS.TURNOVER_CURRENCY_CHANGE}`, getTurnoverCurrency);
insuranceBusinessRouter.post(`/:referenceNumber${ROUTES.INSURANCE.EXPORTER_BUSINESS.TURNOVER_CURRENCY_CHANGE}`, postTurnoverCurrency);
insuranceBusinessRouter.get(`/:referenceNumber${ROUTES.INSURANCE.EXPORTER_BUSINESS.TURNOVER_CURRENCY_CHECK_AND_CHANGE}`, getTurnoverCurrency);
Expand Down
2 changes: 1 addition & 1 deletion src/ui/server/routes/insurance/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('routes/insurance', () => {

it('should setup all routes', () => {
expect(get).toHaveBeenCalledTimes(216);
expect(post).toHaveBeenCalledTimes(224);
expect(post).toHaveBeenCalledTimes(225);

expect(get).toHaveBeenCalledWith(INSURANCE_ROUTES.START, startGet);

Expand Down

0 comments on commit 98e84ec

Please sign in to comment.