-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add controls & validation to rtn reqs reason page (#688)
* Returns required journey - Select return reason page iteration 2 (2 of 7) https://eaflood.atlassian.net/browse/WATER-4265 This is the second page in the returns required journey. This page will have radio control options. This page will have validation to ensure that the user has selected a radio option. * feat(app): WATER-4265 Added controls and validation for step 2 of 7 This commit adds controls for the 2nd step in the no returns required journey. It also has validation which checks to ensure a value is selected on the form * fix(app): WATER-4265 fixed broken test test had wrong data inside. fixed with correct data * fix: fix broken test * fix: amend sonarcloud issues * fix: amend another sonarcloud issue * Thoughts and opinions Having completed the [Returns required journey - Select start date page iteration 2 (1 of 7)](#646) I was expecting the pattern implemented to follow that more than what we'd originally done for 'no-returns-required'. But with so few pages implemented with controls it's hard to see a pattern! So, that wasn't made clear enough. To help I've completed [Update no-returns-required to use submit service](#708) which updates the 'no-returns-required' page to follow the template laid out for 'start-date'. Essentially, validation and error handling will now be done in a `Submit[Page]Service` rather than reuse `[Page]Service`. And so again, I'll go through and contribute to this PR to highlight the changes and when possible, expand on the reasons why. * Housekeeping - clean up after merging in `main` * Correction - The module name does not match file * Correction - wrong page in comments That was me! Doh! * Consistency - add new submit service This is slightly pre-emptive but we know we will need to handle persisting valid payloads to the sessions record soon. Having a service separate from what we call on the GET request gives us an appropriate place to put that. It also allows us to simplify the controller logic in the meantime. * Remove error handling from the presenter Now handled by the submit service. * Remove optional error from the GET service We'll never pass an error in now because we'll never call this in the POST handler. * Update view to reference error Also bring it inline with no returns required and start date. * Update controller to use new service * Update reference in validator We changed the control to match the page and everything else so we need to update the validator to use the new reference. * Fix the tests * Remove unused static lookup * Make the validator more robust As our unit test confirmed it was checking for a value but would accept any value. Now it will only accept certain values. * Update no-rtns-req validator Now it is consistent with what we just did in the `ReasonValidator`. * Add missing JSDoc comments * Correct test title * Add test for new submit service --------- Co-authored-by: Alan Cruikshanks <[email protected]>
- Loading branch information
1 parent
fbf8833
commit 530cdd7
Showing
14 changed files
with
512 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,3 +43,6 @@ lcov.info | |
|
||
# Build assets | ||
app/public/build | ||
|
||
# ignore husky config | ||
.husky/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
'use strict' | ||
|
||
/** | ||
* Formats data for the `/return-requirements/{sessionId}/reason` page | ||
* @module SelectReasonPresenter | ||
*/ | ||
|
||
function go (session) { | ||
const data = { | ||
id: session.id, | ||
licenceRef: session.data.licence.licenceRef | ||
} | ||
|
||
return data | ||
} | ||
|
||
module.exports = { | ||
go | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
'use strict' | ||
|
||
/** | ||
* Orchestrates fetching and presenting the data for `/return-requirements/{sessionId}/reason` page | ||
* @module SelectReasonService | ||
*/ | ||
const SelectReasonPresenter = require('../../presenters/return-requirements/reason.presenter.js') | ||
const SessionModel = require('../../models/session.model.js') | ||
|
||
/** | ||
* Orchestrates fetching and presenting the data for `/return-requirements/{sessionId}/reason` page | ||
* | ||
* Supports generating the data needed for the select reason page in the return requirements setup journey. It | ||
* fetches the current session record and combines it with the radio buttons and other information needed for the form. | ||
* | ||
* @param {string} id - The UUID for return requirement setup session record | ||
* | ||
* @returns {Promise<Object>} page data needed by the view template | ||
*/ | ||
async function go (sessionId) { | ||
const session = await SessionModel.query().findById(sessionId) | ||
const formattedData = SelectReasonPresenter.go(session) | ||
|
||
return { | ||
activeNavBar: 'search', | ||
pageTitle: 'Select the reason for the return requirement', | ||
...formattedData | ||
} | ||
} | ||
|
||
module.exports = { | ||
go | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
'use strict' | ||
|
||
/** | ||
* Orchestrates validating the data for `/return-requirements/{sessionId}/reason` page | ||
* @module StartDateService | ||
*/ | ||
|
||
const ReasonPresenter = require('../../presenters/return-requirements/reason.presenter.js') | ||
const ReasonValidator = require('../../validators/return-requirements/reason.validator.js') | ||
const SessionModel = require('../../models/session.model.js') | ||
|
||
/** | ||
* Orchestrates validating the data for `/return-requirements/{sessionId}/reason` page | ||
* | ||
* It first retrieves the session instance for the returns requirements journey in progress. | ||
* | ||
* The validation 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 id of the current session | ||
* @param {Object} payload - The submitted form data | ||
* | ||
* @returns {Promise<Object>} The page data for the reason page | ||
*/ | ||
async function go (sessionId, payload) { | ||
const session = await SessionModel.query().findById(sessionId) | ||
|
||
const validationResult = _validate(payload) | ||
|
||
const formattedData = ReasonPresenter.go(session, payload) | ||
|
||
return { | ||
activeNavBar: 'search', | ||
error: validationResult, | ||
pageTitle: 'Select the reason for the return requirement', | ||
...formattedData | ||
} | ||
} | ||
|
||
function _validate (payload) { | ||
const validation = ReasonValidator.go(payload) | ||
|
||
if (!validation.error) { | ||
return null | ||
} | ||
|
||
const { message } = validation.error.details[0] | ||
|
||
return { | ||
text: message | ||
} | ||
} | ||
|
||
module.exports = { | ||
go | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
'use strict' | ||
|
||
/** | ||
* Validates data submitted for the `/return-requirements/{sessionId}/reason` page | ||
* @module ReasonValidator | ||
*/ | ||
|
||
const Joi = require('joi') | ||
|
||
const VALID_VALUES = [ | ||
'change_to_special_agreement', | ||
'name_or_address_change', | ||
'transfer_and_now_chargeable', | ||
'extension_of_licence_validity', | ||
'major_change', | ||
'minor_change', | ||
'new_licence_in_part_succession_or_licence_apportionment', | ||
'new_licence', | ||
'new_special_agreement', | ||
'succession_or_transfer_of_licence', | ||
'succession_to_remainder_licence_or_licence_apportionment' | ||
] | ||
|
||
/** | ||
* Validates data submitted for the `/return-requirements/{sessionId}/reason` page | ||
* | ||
* @param {Object} payload - The payload from the request to be validated | ||
* | ||
* @returns {Object} the result from calling Joi's schema.validate(). It will be an object with a `value:` property. If | ||
* any errors are found the `error:` property will also exist detailing what the issues were | ||
*/ | ||
function go (data) { | ||
const schema = Joi.object({ | ||
reason: Joi.string() | ||
.required() | ||
.valid(...VALID_VALUES) | ||
.messages({ | ||
'any.required': 'Select the reason for the return requirement', | ||
'any.only': 'Select the reason for the return requirement', | ||
'string.empty': 'Select the reason for the return requirement' | ||
}) | ||
}) | ||
|
||
return schema.validate(data, { abortEarly: false }) | ||
} | ||
|
||
module.exports = { | ||
go | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,104 @@ | ||
{% extends 'layout.njk' %} | ||
{% from "govuk/components/back-link/macro.njk" import govukBackLink %} | ||
{% from "govuk/components/button/macro.njk" import govukButton %} | ||
|
||
{% set rootLink = "/system/return-requirements/" + id %} | ||
{% from "govuk/components/error-summary/macro.njk" import govukErrorSummary %} | ||
{% from "govuk/components/radios/macro.njk" import govukRadios %} | ||
|
||
{% block breadcrumbs %} | ||
{# Back link #} | ||
{{ | ||
govukBackLink({ | ||
text: 'Back', | ||
href: rootLink + "/start-date" | ||
href: '/system/return-requirements/' + id + '/start-date' | ||
}) | ||
}} | ||
{% endblock %} | ||
|
||
{% block content %} | ||
{# Main heading #} | ||
{% if error %} | ||
{{ govukErrorSummary({ | ||
titleText: "There is a problem", | ||
errorList: [ | ||
{ | ||
text: error.text, | ||
href: "#reason-error" | ||
} | ||
] | ||
}) }} | ||
{% endif %} | ||
|
||
<div class="govuk-body"> | ||
<h1 class="govuk-heading-xl govuk-!-margin-bottom-3">{{ pageTitle }}</h1> | ||
</div> | ||
<form method="post"> | ||
{{ govukRadios({ | ||
name: "reason", | ||
errorMessage: error, | ||
fieldset: { | ||
legend: { | ||
html: '<span class="govuk-caption-l">Licence ' + licenceRef + '</span>' + pageTitle, | ||
isPageHeading: true, | ||
classes: "govuk-fieldset__legend--l govuk-!-margin-bottom-6" | ||
} | ||
}, | ||
items: [ | ||
{ | ||
text: 'Change to special agreement', | ||
value: 'change_to_special_agreement', | ||
checked: false | ||
}, | ||
{ | ||
text: 'Licence holder name or address change', | ||
value: 'name_or_address_change', | ||
checked: false | ||
}, | ||
{ | ||
text: 'Licence transferred and now chargeable', | ||
value: 'transfer_and_now_chargeable', | ||
checked: false | ||
}, | ||
{ | ||
text: 'Limited extension of licence validity (LEV)', | ||
value: 'extension_of_licence_validity', | ||
checked: false | ||
}, | ||
{ | ||
text: 'Major change', | ||
value: 'major_change', | ||
checked: false | ||
}, | ||
{ | ||
text: 'Minor change', | ||
value: 'minor_change', | ||
checked: false | ||
}, | ||
{ | ||
text: 'New licence in part succession or licence apportionment', | ||
value: 'new_licence_in_part_succession_or_licence_apportionment', | ||
checked: false | ||
}, | ||
{ | ||
text: 'New licence', | ||
value: 'new_licence', | ||
checked: false | ||
}, | ||
{ | ||
text: 'New special agreement', | ||
value: 'new_special_agreement', | ||
checked: false | ||
}, | ||
{ | ||
text: 'Succession or transfer of licence', | ||
value: 'succession_or_transfer_of_licence', | ||
checked: false | ||
}, | ||
{ | ||
text: 'Succession to remainder licence or licence apportionment', | ||
value: 'succession_to_remainder_licence_or_licence_apportionment', | ||
checked: false | ||
} | ||
] | ||
}) }} | ||
|
||
<form method="post"> | ||
<div class="govuk-body"> | ||
{{ govukButton({ text: "Continue" }) }} | ||
</div> | ||
</form> | ||
</form> | ||
</div> | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.