diff --git a/app/controllers/return-requirements.controller.js b/app/controllers/return-requirements.controller.js index 287393e4e2..2961514d1c 100644 --- a/app/controllers/return-requirements.controller.js +++ b/app/controllers/return-requirements.controller.js @@ -7,6 +7,7 @@ const AddNoteService = require('../services/return-requirements/add-note.service.js') const AbstractionPeriodService = require('../services/return-requirements/abstraction-period.service.js') +const AgreementsExceptionsService = require('../services/return-requirements/agreements-exceptions.service.js') const CheckYourAnswersService = require('../services/return-requirements/check-your-answers.service.js') const FrequencyCollectedService = require('../services/return-requirements/frequency-collected.service.js') const FrequencyReportedService = require('../services/return-requirements/frequency-reported.service.js') @@ -21,6 +22,7 @@ const SiteDescriptionService = require('../services/return-requirements/site-des const StartDateService = require('../services/return-requirements/start-date.service.js') const SubmitAddNoteService = require('../services/return-requirements/submit-add-note.service.js') const SubmitAbstractionPeriod = require('../services/return-requirements/submit-abstraction-period.service.js') +const SubmitAgreementsExceptions = require('../services/return-requirements/submit-agreements-exceptions.service.js') const SubmitCheckYourAnswersService = require('../services/return-requirements/submit-check-your-answers.service.js') const SubmitFrequencyCollectedService = require('../services/return-requirements/submit-frequency-collected.service.js') const SubmitFrequencyReportedService = require('../services/return-requirements/submit-frequency-reported.service.js') @@ -56,12 +58,10 @@ async function addNote (request, h) { async function agreementsExceptions (request, h) { const { sessionId } = request.params - const session = await SessionModel.query().findById(sessionId) + const pageData = await AgreementsExceptionsService.go(sessionId) return h.view('return-requirements/agreements-exceptions.njk', { - activeNavBar: 'search', - pageTitle: 'Select agreements and exceptions for the return requirement', - ...session + ...pageData }) } @@ -223,6 +223,12 @@ async function submitAddNote (request, h) { async function submitAgreementsExceptions (request, h) { const { sessionId } = request.params + const pageData = await SubmitAgreementsExceptions.go(sessionId, request.payload) + + if (pageData.error) { + return h.view('return-requirements/agreements-exceptions.njk', pageData) + } + return h.redirect(`/system/return-requirements/${sessionId}/check-your-answers`) } diff --git a/app/presenters/return-requirements/agreements-exceptions.presenter.js b/app/presenters/return-requirements/agreements-exceptions.presenter.js new file mode 100644 index 0000000000..7cca82973c --- /dev/null +++ b/app/presenters/return-requirements/agreements-exceptions.presenter.js @@ -0,0 +1,29 @@ +'use strict' + +/** + * Formats data for the `/return-requirements/{sessionId}/agreements-exceptions` page + * @module AgreementsExceptionsPresenter +*/ + +/** + * Formats data for the `/return-requirements/{sessionId}/agreements-exceptions` page + * + * @param {module:SessionModel} session - The returns requirements session instance + * @param {Object} [payload] - The payload from the request + * + * @returns {Object} - The data formatted for the view template + */ +function go (session) { + const data = { + id: session.id, + licenceId: session.data.licence.id, + licenceRef: session.data.licence.licenceRef, + agreementsExceptions: session.data.agreementsExceptions ? session.data.agreementsExceptions : '' + } + + return data +} + +module.exports = { + go +} diff --git a/app/services/return-requirements/agreements-exceptions.service.js b/app/services/return-requirements/agreements-exceptions.service.js new file mode 100644 index 0000000000..e8bcfd3f9f --- /dev/null +++ b/app/services/return-requirements/agreements-exceptions.service.js @@ -0,0 +1,34 @@ +'use strict' + +/** + * Orchestrates fetching and presenting the data for `/return-requirements/{sessionId}/agreements-exceptions` page + * @module AgreementExceptionService + */ + +const AgreementsExceptionsPresenter = require('../../presenters/return-requirements/agreements-exceptions.presenter.js') +const SessionModel = require('../../models/session.model.js') + +/** + * Orchestrates fetching and presenting the data for `/return-requirements/{sessionId}/agreements-exceptions` page + * + * Supports generating the data needed for the agreements and exceptions page in the return requirements setup journey. + * It fetches the current session record and combines it with the date fields and other information needed for the form. + * + * @param {string} sessionId - The UUID of the current session + * + * @returns {Promise} The view data for the agreements and exceptions page +*/ +async function go (sessionId) { + const session = await SessionModel.query().findById(sessionId) + const formattedData = AgreementsExceptionsPresenter.go(session) + + return { + activeNavBar: 'search', + pageTitle: 'Select agreements and exceptions for the requirements for returns', + ...formattedData + } +} + +module.exports = { + go +} diff --git a/app/services/return-requirements/submit-abstraction-period.service.js b/app/services/return-requirements/submit-abstraction-period.service.js index c73cc2af82..6a416114e1 100644 --- a/app/services/return-requirements/submit-abstraction-period.service.js +++ b/app/services/return-requirements/submit-abstraction-period.service.js @@ -39,7 +39,7 @@ async function go (sessionId, payload) { return { activeNavBar: 'search', error: validationResult, - pageTitle: 'Select the abstraction period for the requirements for returns', + pageTitle: 'Enter the abstraction period for the requirements for returns', ...formattedData } } diff --git a/app/services/return-requirements/submit-agreements-exceptions.service.js b/app/services/return-requirements/submit-agreements-exceptions.service.js new file mode 100644 index 0000000000..903f8c8252 --- /dev/null +++ b/app/services/return-requirements/submit-agreements-exceptions.service.js @@ -0,0 +1,84 @@ +'use strict' + +/** + * Orchestrates validating the data for `/return-requirements/{sessionId}/agreements-exceptions` page + * @module SubmitAgreementsExceptions + */ + +const AgreementsExceptionsPresenter = require('../../presenters/return-requirements/agreements-exceptions.presenter.js') +const AgreementsExceptionsValidator = require('../../validators/return-requirements/agreements-exceptions.validator.js') +const SessionModel = require('../../models/session.model.js') + +/** + * Orchestrates validating the data for `/return-requirements/{sessionId}/agreements-exceptions` page + * + * It first retrieves the session instance for the returns requirements journey in progress. + * + * The user input is then validated and the result is then combined with the output of the presenter to generate the + * page data needed by the view. If there was a validation error the controller will re-render the page so needs this + * information. If all is well the controller will redirect to the next page in the journey. + * + * @param {string} sessionId - The UUID of the current session + * @param {Object} payload - The submitted form data + * + * @returns {Promise} The page data for the agreements and exceptions page + */ +async function go (sessionId, payload) { + const session = await SessionModel.query().findById(sessionId) + + _handleOneOptionSelected(payload) + + const validationResult = _validate(payload) + + if (!validationResult) { + await _save(session, payload) + + return {} + } + + const formattedData = AgreementsExceptionsPresenter.go(session, payload) + + return { + activeNavBar: 'search', + error: validationResult, + pageTitle: 'Select agreements and exceptions for the requirements for returns', + ...formattedData + } +} + +/** + * When a single agreement and exception is checked by the user, it returns as a string. When multiple agreements and + * exceptions are checked, the 'agreementsExceptions' is returned as an array. This function works to make those single + * selected string 'agreementsExceptions' into an array for uniformity. + */ +function _handleOneOptionSelected (payload) { + if (!Array.isArray(payload.agreementsExceptions)) { + payload.agreementsExceptions = [payload.agreementsExceptions] + } +} + +async function _save (session, payload) { + const currentData = session.data + + currentData.agreementsExceptions = payload.agreementsExceptions + + return session.$query().patch({ data: currentData }) +} + +function _validate (payload) { + const validation = AgreementsExceptionsValidator.go(payload) + + if (!validation.error) { + return null + } + + const { message } = validation.error.details[0] + + return { + text: message + } +} + +module.exports = { + go +} diff --git a/app/services/return-requirements/submit-reason.service.js b/app/services/return-requirements/submit-reason.service.js index 8efefe9fbf..2bcddaf318 100644 --- a/app/services/return-requirements/submit-reason.service.js +++ b/app/services/return-requirements/submit-reason.service.js @@ -2,7 +2,7 @@ /** * Orchestrates validating the data for `/return-requirements/{sessionId}/reason` page - * @module StartDateService + * @module SubmitReasonService */ const ReasonPresenter = require('../../presenters/return-requirements/reason.presenter.js') diff --git a/app/validators/return-requirements/agreements-exceptions.validator.js b/app/validators/return-requirements/agreements-exceptions.validator.js new file mode 100644 index 0000000000..951b2a9a8c --- /dev/null +++ b/app/validators/return-requirements/agreements-exceptions.validator.js @@ -0,0 +1,53 @@ +'use strict' + +/** + * Validates data submitted for the `/return-requirements/{sessionId}/agreements-exceptions` page + * @module AgreementsExceptionsValidator + */ + +const Joi = require('joi') + +/** + * Validates data submitted for the `/return-requirements/{sessionId}/agreements-exceptions` page + * + * When setting up a requirement users must specify an agreement and exception for the return requirement. + * Users must select one or more agreements and exceptions linked to the licence. If these requirements are not met + * the validation will return an error. + * + * @param {Object} payload - The payload from the request to be validated + * + * @returns {Object} The result from calling Joi's schema.validate(). If any errors are found the + * `error:` property will also exist detailing what the issue is. + */ +function go (payload) { + const agreementsExceptions = payload.agreementsExceptions + + const errorMessage = 'Select if there are any agreements and exceptions needed for the return requirements' + + const schema = Joi.object({ + agreementsExceptions: Joi.array() + .items(Joi.string().valid(...VALID_VALUES)) + .required() + .messages({ + 'any.required': errorMessage, + 'any.only': errorMessage, + 'array.includesOne': errorMessage, + 'array.includes': errorMessage, + 'array.sparse': errorMessage + }) + }) + + return schema.validate({ agreementsExceptions }, { abortEarly: false }) +} + +const VALID_VALUES = [ + 'gravity-fill', + 'transfer-re-abstraction-scheme', + 'two-part-tariff', + '56-returns-exception', + 'none' +] + +module.exports = { + go +} diff --git a/app/views/return-requirements/abstraction-period.njk b/app/views/return-requirements/abstraction-period.njk index 1ddf94e8ed..b30303832f 100644 --- a/app/views/return-requirements/abstraction-period.njk +++ b/app/views/return-requirements/abstraction-period.njk @@ -54,6 +54,7 @@ {# Main heading #}
+ Licence {{ licenceRef }}

{{ pageTitle }}

diff --git a/app/views/return-requirements/agreements-exceptions.njk b/app/views/return-requirements/agreements-exceptions.njk index 37ce05753a..f979cf0534 100644 --- a/app/views/return-requirements/agreements-exceptions.njk +++ b/app/views/return-requirements/agreements-exceptions.njk @@ -1,6 +1,9 @@ {% extends 'layout.njk' %} {% from "govuk/components/back-link/macro.njk" import govukBackLink %} {% from "govuk/components/button/macro.njk" import govukButton %} +{% from "govuk/components/checkboxes/macro.njk" import govukCheckboxes %} +{% from "govuk/components/error-message/macro.njk" import govukErrorMessage %} +{% from "govuk/components/error-summary/macro.njk" import govukErrorSummary %} {% set rootLink = "/system/return-requirements/" + id %} @@ -15,12 +18,69 @@ {% endblock %} {% block content %} + {# Error summary #} + {% if error %} + {{ govukErrorSummary({ + titleText: "There is a problem", + errorList: [ + { + text: error.text, + href: "#purposes" + } + ] + }) }} + {%endif%} + {# Main heading #} -
-

{{ pageTitle }}

+
+ Licence {{ licenceRef }} +

{{ pageTitle }}

+
+ {{ govukCheckboxes({ + name: "agreementsExceptions", + hint: { + text: "Select all that apply" + }, + errorMessage: error, + items: [ + { + value: "gravity-fill", + text: "Gravity fill", + checked: agreementsExceptions and "gravity-fill" in agreementsExceptions + }, + { + value: "transfer-re-abstraction-scheme", + text: "Transfer re-abstraction scheme", + checked: agreementsExceptions and "transfer-re-abstraction-scheme" in agreementsExceptions + }, + { + value: "two-part-tariff", + text: "Two-part tarrif", + checked: agreementsExceptions and "two-part-tariff" in agreementsExceptions, + hint: { + text: "requires daily collection" + } + }, + { + value: "56-returns-exception", + text: "56 returns exception", + checked: agreementsExceptions and "56-returns-exception" in agreementsExceptions + }, + { + divider: "or" + }, + { + value: "none", + text: "None", + checked: "none" === agreementsExceptions, + behaviour: "exclusive" + } + ] + }) }} +
{{ govukButton({ text: "Continue" }) }}
diff --git a/test/controllers/return-requirements.controller.test.js b/test/controllers/return-requirements.controller.test.js index c5ec42c753..1ab1af2880 100644 --- a/test/controllers/return-requirements.controller.test.js +++ b/test/controllers/return-requirements.controller.test.js @@ -11,6 +11,7 @@ const { expect } = Code // Things we need to stub const AbstractionPeriodService = require('../../app/services/return-requirements/abstraction-period.service.js') const AddNoteService = require('../../app/services/return-requirements/add-note.service.js') +const AgreementsExceptionService = require('../../app/services/return-requirements/agreements-exceptions.service.js') const CheckYourAnswersService = require('../../app/services/return-requirements/check-your-answers.service.js') const FrequencyCollectedService = require('../../app/services/return-requirements/frequency-collected.service.js') const FrequencyReportedService = require('../../app/services/return-requirements/frequency-reported.service.js') @@ -81,6 +82,13 @@ describe('Return requirements controller', () => { }) describe('GET /return-requirements/{sessionId}/agreements-exceptions', () => { + beforeEach(async () => { + Sinon.stub(AgreementsExceptionService, 'go').resolves({ + id: '8702b98f-ae51-475d-8fcc-e049af8b8d38', + pageTitle: 'Select agreements and exceptions for the return requirement' + }) + }) + describe('when the request succeeds', () => { it('returns the page successfully', async () => { const response = await server.inject(_options('agreements-exceptions')) diff --git a/test/presenters/return-requirements/agreements-exceptions.presenter.test.js b/test/presenters/return-requirements/agreements-exceptions.presenter.test.js new file mode 100644 index 0000000000..babce0cb4f --- /dev/null +++ b/test/presenters/return-requirements/agreements-exceptions.presenter.test.js @@ -0,0 +1,76 @@ +'use strict' + +// Test framework dependencies +const Lab = require('@hapi/lab') +const Code = require('@hapi/code') + +const { describe, it, beforeEach } = exports.lab = Lab.script() +const { expect } = Code + +// Thing under test +const AgreementsExceptionsPresenter = require('../../../app/presenters/return-requirements/agreements-exceptions.presenter.js') + +describe('Agreements Exceptions presenter', () => { + describe('when provided with a populated session', () => { + let session + + describe('and no agreements and exceptions in session data', () => { + beforeEach(() => { + session = { + id: '61e07498-f309-4829-96a9-72084a54996d', + data: { + licence: { + id: '8b7f78ba-f3ad-4cb6-a058-78abc4d1383d', + currentVersionStartDate: '2023-01-01T00:00:00.000Z', + endDate: null, + licenceRef: '01/ABC', + licenceHolder: 'Turbo Kid', + startDate: '2022-04-01T00:00:00.000Z' + } + } + } + }) + + it('correctly presents the data', () => { + const result = AgreementsExceptionsPresenter.go(session) + + expect(result).to.equal({ + id: '61e07498-f309-4829-96a9-72084a54996d', + licenceId: '8b7f78ba-f3ad-4cb6-a058-78abc4d1383d', + licenceRef: '01/ABC', + agreementsExceptions: '' + }) + }) + }) + + describe('and with agreements and exceptions in session data', () => { + beforeEach(() => { + session = { + id: '61e07498-f309-4829-96a9-72084a54996d', + data: { + licence: { + id: '8b7f78ba-f3ad-4cb6-a058-78abc4d1383d', + currentVersionStartDate: '2023-01-01T00:00:00.000Z', + endDate: null, + licenceRef: '01/ABC', + licenceHolder: 'Turbo Kid', + startDate: '2022-04-01T00:00:00.000Z' + }, + agreementsExceptions: 'gravity-fill' + } + } + }) + + it('correctly presents the data', () => { + const result = AgreementsExceptionsPresenter.go(session) + + expect(result).to.equal({ + id: '61e07498-f309-4829-96a9-72084a54996d', + licenceId: '8b7f78ba-f3ad-4cb6-a058-78abc4d1383d', + licenceRef: '01/ABC', + agreementsExceptions: 'gravity-fill' + }) + }) + }) + }) +}) diff --git a/test/services/return-requirements/agreements-exceptions.service.test.js b/test/services/return-requirements/agreements-exceptions.service.test.js new file mode 100644 index 0000000000..7d6fdee5bb --- /dev/null +++ b/test/services/return-requirements/agreements-exceptions.service.test.js @@ -0,0 +1,57 @@ +'use strict' + +// Test framework dependencies +const Lab = require('@hapi/lab') +const Code = require('@hapi/code') + +const { describe, it, beforeEach } = exports.lab = Lab.script() +const { expect } = Code + +// Test helpers +const DatabaseSupport = require('../../support/database.js') +const SessionHelper = require('../../support/helpers/session.helper.js') + +// Thing under test +const AgreementsExceptionsService = require('../../../app/services/return-requirements/agreements-exceptions.service.js') + +describe('Agreements Exceptions service', () => { + let session + + beforeEach(async () => { + await DatabaseSupport.clean() + + session = await SessionHelper.add({ + data: { + licence: { + id: '8b7f78ba-f3ad-4cb6-a058-78abc4d1383d', + currentVersionStartDate: '2023-01-01T00:00:00.000Z', + endDate: null, + licenceRef: '01/ABC', + licenceHolder: 'Turbo Kid', + startDate: '2022-04-01T00:00:00.000Z' + } + } + }) + }) + + describe('when called', () => { + it('fetches the current setup session record', async () => { + const result = await AgreementsExceptionsService.go(session.id) + + expect(result.id).to.equal(session.id) + }) + + it('returns page data for the view', async () => { + const result = await AgreementsExceptionsService.go(session.id) + + expect(result).to.equal({ + activeNavBar: 'search', + pageTitle: 'Select agreements and exceptions for the requirements for returns', + id: '465c6792-dd84-4163-a808-cbb834a779be', + licenceId: '8b7f78ba-f3ad-4cb6-a058-78abc4d1383d', + licenceRef: '01/ABC', + agreementsExceptions: '' + }, { skip: ['id'] }) + }) + }) +}) diff --git a/test/services/return-requirements/submit-abstraction-period.service.test.js b/test/services/return-requirements/submit-abstraction-period.service.test.js index 9ae817640e..9a563905be 100644 --- a/test/services/return-requirements/submit-abstraction-period.service.test.js +++ b/test/services/return-requirements/submit-abstraction-period.service.test.js @@ -85,7 +85,7 @@ describe('Submit Abstraction Period service', () => { expect(result).to.equal({ activeNavBar: 'search', error: null, - pageTitle: 'Select the abstraction period for the requirements for returns', + pageTitle: 'Enter the abstraction period for the requirements for returns', id: 'aeb46f58-3431-42af-8724-361a7779becf', licenceId: '8b7f78ba-f3ad-4cb6-a058-78abc4d1383d', licenceRef: '01/ABC', @@ -132,7 +132,7 @@ describe('Submit Abstraction Period service', () => { expect(result).to.equal({ activeNavBar: 'search', error: null, - pageTitle: 'Select the abstraction period for the requirements for returns', + pageTitle: 'Enter the abstraction period for the requirements for returns', id: 'aeb46f58-3431-42af-8724-361a7779becf', licenceId: '8b7f78ba-f3ad-4cb6-a058-78abc4d1383d', licenceRef: '01/ABC', @@ -179,7 +179,7 @@ describe('Submit Abstraction Period service', () => { expect(result).to.equal({ activeNavBar: 'search', error: null, - pageTitle: 'Select the abstraction period for the requirements for returns', + pageTitle: 'Enter the abstraction period for the requirements for returns', id: 'aeb46f58-3431-42af-8724-361a7779becf', licenceId: '8b7f78ba-f3ad-4cb6-a058-78abc4d1383d', licenceRef: '01/ABC', @@ -226,7 +226,7 @@ describe('Submit Abstraction Period service', () => { expect(result).to.equal({ activeNavBar: 'search', error: null, - pageTitle: 'Select the abstraction period for the requirements for returns', + pageTitle: 'Enter the abstraction period for the requirements for returns', id: 'aeb46f58-3431-42af-8724-361a7779becf', licenceId: '8b7f78ba-f3ad-4cb6-a058-78abc4d1383d', licenceRef: '01/ABC', @@ -273,7 +273,7 @@ describe('Submit Abstraction Period service', () => { expect(result).to.equal({ activeNavBar: 'search', error: null, - pageTitle: 'Select the abstraction period for the requirements for returns', + pageTitle: 'Enter the abstraction period for the requirements for returns', id: 'aeb46f58-3431-42af-8724-361a7779becf', licenceId: '8b7f78ba-f3ad-4cb6-a058-78abc4d1383d', licenceRef: '01/ABC', @@ -320,7 +320,7 @@ describe('Submit Abstraction Period service', () => { expect(result).to.equal({ activeNavBar: 'search', error: null, - pageTitle: 'Select the abstraction period for the requirements for returns', + pageTitle: 'Enter the abstraction period for the requirements for returns', id: 'aeb46f58-3431-42af-8724-361a7779becf', licenceId: '8b7f78ba-f3ad-4cb6-a058-78abc4d1383d', licenceRef: '01/ABC', diff --git a/test/services/return-requirements/submit-agreements-exceptions.service.test.js b/test/services/return-requirements/submit-agreements-exceptions.service.test.js new file mode 100644 index 0000000000..fa969a8ffe --- /dev/null +++ b/test/services/return-requirements/submit-agreements-exceptions.service.test.js @@ -0,0 +1,106 @@ +'use strict' + +// Test framework dependencies +const Lab = require('@hapi/lab') +const Code = require('@hapi/code') + +const { describe, it, beforeEach } = exports.lab = Lab.script() +const { expect } = Code + +// Test helpers +const DatabaseSupport = require('../../support/database.js') +const SessionHelper = require('../../support/helpers/session.helper.js') + +// Thing under test +const SubmitAgreementsExceptionsService = require('../../../app/services/return-requirements/submit-agreements-exceptions.service.js') + +describe('Submit Agreements and Exceptions service', () => { + let payload + let session + + beforeEach(async () => { + await DatabaseSupport.clean() + + session = await SessionHelper.add({ + data: { + licence: { + id: '8b7f78ba-f3ad-4cb6-a058-78abc4d1383d', + currentVersionStartDate: '2023-01-01T00:00:00.000Z', + endDate: null, + licenceRef: '01/ABC', + licenceHolder: 'Turbo Kid', + startDate: '2022-04-01T00:00:00.000Z' + }, + journey: 'returns-required' + } + }) + }) + + describe('when called', () => { + describe('with a valid payload', () => { + beforeEach(() => { + payload = { + agreementsExceptions: [ + 'gravity-fill', + 'two-part-tariff', + '56-returns-exception' + ] + } + }) + + it('saves the submitted value', async () => { + await SubmitAgreementsExceptionsService.go(session.id, payload) + + const refreshedSession = await session.$query() + + expect(refreshedSession.data.agreementsExceptions).to.equal([ + 'gravity-fill', + 'two-part-tariff', + '56-returns-exception' + ]) + }) + + it('returns an empty object (no page data needed for a redirect)', async () => { + const result = await SubmitAgreementsExceptionsService.go(session.id, payload) + + expect(result).to.equal({}) + }) + }) + }) + + describe('with an invalid payload', () => { + describe('because the user has not inputted anything', () => { + beforeEach(() => { + payload = {} + }) + + it('fetches the current setup session record', async () => { + const result = await SubmitAgreementsExceptionsService.go(session.id, payload) + + expect(result.id).to.equal(session.id) + }) + + it('returns page data for the view', async () => { + const result = await SubmitAgreementsExceptionsService.go(session.id, payload) + + expect(result).to.equal({ + activeNavBar: 'search', + error: null, + pageTitle: 'Select agreements and exceptions for the requirements for returns', + id: 'aeb46f58-3431-42af-8724-361a7779becf', + licenceId: '8b7f78ba-f3ad-4cb6-a058-78abc4d1383d', + licenceRef: '01/ABC', + agreementsExceptions: '' + }, { skip: ['id', 'error'] }) + }) + + it('returns page data with an error for the data input form element', async () => { + const result = await SubmitAgreementsExceptionsService.go(session.id, payload) + + expect(result.error).to.equal({ + text: 'Select if there are any agreements and exceptions needed for the return requirements' + }) + }) + }) + }) +}) diff --git a/test/validators/no-returns-required/agreements-exceptions.validator.test.js b/test/validators/no-returns-required/agreements-exceptions.validator.test.js new file mode 100644 index 0000000000..fa39f9a40e --- /dev/null +++ b/test/validators/no-returns-required/agreements-exceptions.validator.test.js @@ -0,0 +1,69 @@ +'use strict' + +// Test framework dependencies +const Lab = require('@hapi/lab') +const Code = require('@hapi/code') + +const { describe, it, beforeEach } = exports.lab = Lab.script() +const { expect } = Code + +// Thing under test +const AgreementsExceptionsValidator = require('../../../app/validators/return-requirements/agreements-exceptions.validator.js') + +describe('Agreements Exception validator', () => { + let payload + + describe('when valid data is provided', () => { + beforeEach(() => { + payload = { + agreementsExceptions: [ + 'gravity-fill', + 'two-part-tariff', + '56-returns-exception' + ] + } + }) + + it('confirms the data is valid', () => { + const result = AgreementsExceptionsValidator.go(payload) + + expect(result.value.agreementsExceptions).to.equal([ + 'gravity-fill', + 'two-part-tariff', + '56-returns-exception' + ]) + + expect(result.error).not.to.exist() + }) + }) + + describe('when invalid data is provided', () => { + beforeEach(() => { + payload = { + agreementsExceptions: ['ABC123'] + } + }) + + it('fails validation', () => { + const result = AgreementsExceptionsValidator.go(payload) + + expect(result.error.details[0].message).to.equal( + 'Select if there are any agreements and exceptions needed for the return requirements' + ) + }) + }) + + describe('when no data is provided', () => { + beforeEach(() => { + payload = {} + }) + + it('fails validation', () => { + const result = AgreementsExceptionsValidator.go(payload) + + expect(result.error.details[0].message).to.equal( + 'Select if there are any agreements and exceptions needed for the return requirements' + ) + }) + }) +})