From 8d6251ecec01d23403e5d9b65fc8bb704e22754b Mon Sep 17 00:00:00 2001 From: Tedd Date: Tue, 10 Dec 2024 09:31:47 +0000 Subject: [PATCH] Cya epic (#234) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * SIR-888: water-pollution/your-details (#205) Looks good to me :) * SIR-887 : Story – WP – Check your answers (#208) * SIR-888: water-pollution/your-details (#205) Looks good to me :) * WIP - WP CYA Page * Technical implementation for SIR-887 * Fixed all lint errors * Refactored code and added comments * Refactored code and logic update * Added unit tests for check your answers page * SIR-1102 map widget for check your answers (#207) * linting that i missed * Fixed unit test case issues * fixing unit tests * reverting date test am and AM having issues * CYA routing boilerplate * changing to form-layout otherwise post doesn''t work * Fixed sonar issues part 1 * Fixed lint issues * Fixed sonar issues part 2 * Fixed sonar issues part 3 * Added test coverage part 1 * Added test coverage part 2 * Added test coverage part 3 * Additional logic added for UI renderning * Added null check * Reduced code complexity for sonar * Reduced code complexity for sonar * Updated logic complexity * Additional test cases for more coverage * Updated code based on review comments * Check your answers routing (#210) * SIR-1066 pollution-substance routing from CYA * updating var name for sonarcloud * test coverage * SIR-892 pollution-appearance routing from CYA (#211) * SIR-892 pollution-appearance routing from CYA * SIR-890 change location from CYA (#212) * SIR-890 change location from CYA * removing .only from unit tests * sonarcloud * SIR-1068 CYA routing for WP source (#217) --------- Co-authored-by: Tedd * SIR-893 images-and-videos CYA routing * SIR-891 - observed date time from cya (#220) * SIR-891 - observed date time from cya * sonarcloud stuff * further test coverage for dates * SIR-889 : Story – WP – Check your answers – Watercourse & Extent (#218) * CYA - Watercourse & Extent redirection implementation * CYA - Prepopulate answers for watercourse & Extent pages * WIP - Updated test case * WIP - CYA Test cases * Added test cases for CYA watercourse & extent * SIR-894 : Story – WP – Check your answers – Dead animals (#222) * Technical implementation for SIR-894 * Removed console logs * fixing test missed from merge * SIR-895 : Story – WP – Check your answers – Other text (#225) * Technical implementation for SIR-895 * Added logs to check data on server * Added logs to check data on server * Added logs to check data on server * Removed logs --------- Co-authored-by: Tedd Mason * Reset the referer flag in case if the user restarts the WP journey before report submission (#228) --------- Co-authored-by: sujithvg --- client/js/map.js | 72 ++- client/js/pages/check-your-answers.js | 3 + client/js/pages/location-map.js | 3 +- client/sass/application.scss | 21 + server/plugins/on-post-handler.js | 22 + server/plugins/views.js | 3 +- .../routes/__tests__/water-pollution.spec.js | 7 + .../check-your-answers.spec.js | 498 ++++++++++++++++++ .../effect-on-wildlife.spec.js | 55 +- .../water-pollution/images-or-video.spec.js | 57 ++ .../less-than-10-metres.spec.js | 94 ++++ .../less-than-100-sq-metres.spec.js | 76 +++ .../location-description.spec.js | 29 + .../water-pollution/location-map.spec.js | 34 ++ .../water-pollution/location-option.spec.js | 17 +- .../water-pollution/other-information.spec.js | 130 +---- .../pollution-appearance.spec.js | 61 ++- .../water-pollution/pollution-area.spec.js | 27 + .../water-pollution/pollution-length.spec.js | 36 ++ .../pollution-substance.spec.js | 41 ++ .../__tests__/water-pollution/source.spec.js | 16 + .../water-pollution/water-feature.spec.js | 109 +++- .../__tests__/water-pollution/when.spec.js | 115 +++- .../water-pollution/your-details.spec.js | 87 +++ server/routes/smell/location-map.js | 3 +- server/routes/water-pollution.js | 4 +- .../water-pollution/check-your-answers.js | 342 ++++++++++++ .../water-pollution/effect-on-wildlife.js | 50 +- .../routes/water-pollution/images-or-video.js | 8 +- .../water-pollution/less-than-10-metres.js | 16 +- .../less-than-100-sq-metres.js | 24 +- .../water-pollution/location-description.js | 16 +- server/routes/water-pollution/location-map.js | 21 +- .../routes/water-pollution/location-option.js | 12 +- .../water-pollution/other-information.js | 49 +- .../water-pollution/pollution-appearance.js | 19 +- .../routes/water-pollution/pollution-area.js | 14 +- .../water-pollution/pollution-length.js | 6 +- .../water-pollution/pollution-substance.js | 14 +- server/routes/water-pollution/source.js | 16 +- .../routes/water-pollution/water-feature.js | 37 +- server/routes/water-pollution/when.js | 10 +- server/routes/water-pollution/your-details.js | 91 ++++ server/utils/constants.js | 20 +- server/utils/date-helpers.js | 39 +- server/utils/question-sets.js | 112 ++-- server/utils/template-helpers.js | 14 +- server/views/layout.html | 1 + server/views/partials/date-time-old.html | 92 ---- server/views/partials/date-time.html | 36 +- server/views/partials/location-map.html | 5 +- server/views/shared/images-or-video.html | 4 +- .../water-pollution/check-your-answers.html | 362 +++++++++++++ .../water-pollution/effect-on-wildlife.html | 21 +- .../water-pollution/location-description.html | 3 +- .../water-pollution/location-option.html | 6 +- .../water-pollution/other-information.html | 34 +- .../partials/less-than-x-x.html | 9 +- .../water-pollution/pollution-appearance.html | 11 +- .../views/water-pollution/pollution-area.html | 9 +- .../water-pollution/pollution-length.html | 15 +- .../water-pollution/pollution-substance.html | 18 +- server/views/water-pollution/source.html | 6 +- .../views/water-pollution/water-feature.html | 24 +- .../views/water-pollution/your-details.html | 55 ++ webpack.config.js | 1 + 66 files changed, 2752 insertions(+), 510 deletions(-) create mode 100644 client/js/pages/check-your-answers.js create mode 100644 server/routes/__tests__/water-pollution/check-your-answers.spec.js create mode 100644 server/routes/__tests__/water-pollution/your-details.spec.js create mode 100644 server/routes/water-pollution/check-your-answers.js create mode 100644 server/routes/water-pollution/your-details.js delete mode 100644 server/views/partials/date-time-old.html create mode 100644 server/views/water-pollution/check-your-answers.html create mode 100644 server/views/water-pollution/your-details.html diff --git a/client/js/map.js b/client/js/map.js index 694454c6..01de5804 100644 --- a/client/js/map.js +++ b/client/js/map.js @@ -120,7 +120,9 @@ const dropPin = (coordinate) => { geometry: point }) vectorSource.addFeature(marker) - pointElement.value = JSON.stringify(coordinate) + if (pointElement) { + pointElement.value = JSON.stringify(coordinate) + } } const panToPoint = (point, extentBuffer = 250) => { @@ -145,7 +147,7 @@ const panToOSValue = (value) => { } } -const initialiseMap = () => { +const initialiseMap = options => { ( async () => { await setToken() @@ -159,35 +161,53 @@ const initialiseMap = () => { const oSLayer = new TileLayer({ source: osSource }) - map = new Map({ - target: 'map', - interactions: defaultInteractions({ + + const interactions = options?.disableControls + ? [] + : defaultInteractions({ altShiftDragRotate: false, pinchRotate: false - }), - controls: defaultControls().extend([ - new ScaleLine({ - units: 'metric', - minWidth: 100 - }) - ]), - layers: [ - oSLayer, - vectorLayer - ], - view: new View({ - projection: OSGB36, - showFullExtent: false, - extent, - center, - zoom, - maxZoom }) + + const controls = defaultControls().extend([ + new ScaleLine({ + units: 'metric', + minWidth: 100 + }) + ]) + + const view = new View({ + projection: OSGB36, + showFullExtent: false, + extent, + center: options?.point || center, + zoom: options?.zoom || zoom, + maxZoom }) - // add Marker interaction - map.on('click', (e) => { - dropPin(e.coordinate) + + const layers = [ + oSLayer, + vectorLayer + ] + + map = new Map({ + target: 'map', + interactions, + controls, + layers, + view }) + + if (options?.point) { + dropPin(options.point) + } + + if (!options?.disableControls) { + // add Marker interaction + map.on('click', (e) => { + dropPin(e.coordinate) + }) + } } )() } diff --git a/client/js/pages/check-your-answers.js b/client/js/pages/check-your-answers.js new file mode 100644 index 00000000..b3c33b69 --- /dev/null +++ b/client/js/pages/check-your-answers.js @@ -0,0 +1,3 @@ +import { initialiseMap } from '../map.js' + +export { initialiseMap } diff --git a/client/js/pages/location-map.js b/client/js/pages/location-map.js index d78e7027..58fd1fd2 100644 --- a/client/js/pages/location-map.js +++ b/client/js/pages/location-map.js @@ -25,5 +25,6 @@ const getLocation = async () => { ] } -initialiseMap() initialiseLocationSearch() + +export { initialiseMap } diff --git a/client/sass/application.scss b/client/sass/application.scss index d907336f..0a30023c 100644 --- a/client/sass/application.scss +++ b/client/sass/application.scss @@ -434,6 +434,27 @@ margin-bottom: 0; } } +.map--check-your-answers { + height: auto; + + .ol-viewport { + height: 200px !important; + } + + .ol-zoom, .ol-scale-line, .ol-attribution { + display: none; + } + +} + +.vertical-align-top { + vertical-align: top; +} + +.map--cell { + height: 220px; +} + ////////////////////////////////////////////////// // OS MAP STYLES END ///////////////////////////// ////////////////////////////////////////////////// \ No newline at end of file diff --git a/server/plugins/on-post-handler.js b/server/plugins/on-post-handler.js index 6b861cbf..8d282396 100644 --- a/server/plugins/on-post-handler.js +++ b/server/plugins/on-post-handler.js @@ -1,3 +1,5 @@ +import constants from '../utils/constants.js' + const onPostHandler = { plugin: { name: 'on-post-handler', @@ -5,6 +7,7 @@ const onPostHandler = { server.ext('onPostHandler', async (request, h) => { if (request.response.variety === 'view' && request.method === 'get') { request.response.headers['cache-control'] = 'no-cache, no-store, must-revalidate' + handleReferer(request) } return h.continue }) @@ -12,4 +15,23 @@ const onPostHandler = { } } +const handleReferer = request => { + if (request.headers.referer) { + // If referer was a check route then set the session referer + // Route then decides whether to redirect to referer or not + const setReferer = constants.setReferer.find(item => request.headers.referer.indexOf(item) > -1) + const clearReferer = constants.clearReferer.find(item => request.headers.referer.indexOf(item) > -1) + if (setReferer) { + request.yar.set(constants.redisKeys.REFERER, `/${setReferer}`) + } else if (clearReferer) { + request.yar.clear(constants.redisKeys.REFERER) + } else { + // do nothing for sonarcloud + } + } else { + // If no referer then clear referer key because user has broken the journey + request.yar.clear(constants.redisKeys.REFERER) + } +} + export default onPostHandler diff --git a/server/plugins/views.js b/server/plugins/views.js index dd8f31c4..655f476b 100644 --- a/server/plugins/views.js +++ b/server/plugins/views.js @@ -5,7 +5,7 @@ import config from '../utils/config.js' import constants from '../utils/constants.js' import fs from 'fs' import dirname from '../../dirname.cjs' -import { findErrorMessageById } from '../utils/template-helpers.js' +import { findErrorMessageById, getAnswer } from '../utils/template-helpers.js' const { version } = JSON.parse(fs.readFileSync('./package.json')) const analyticsAccount = config.analyticsAccount @@ -25,6 +25,7 @@ export default { }) // Add global functions for view templates env.addGlobal('findErrorMessageById', findErrorMessageById) + env.addGlobal('getAnswer', getAnswer) return next() } } diff --git a/server/routes/__tests__/water-pollution.spec.js b/server/routes/__tests__/water-pollution.spec.js index b6140917..aaf19d5f 100644 --- a/server/routes/__tests__/water-pollution.spec.js +++ b/server/routes/__tests__/water-pollution.spec.js @@ -9,5 +9,12 @@ describe(url, () => { it(`Should return success response and correct view for ${url}`, async () => { await submitGetRequest({ url }, header) }) + it(`Happy: Reset the CYA journey if user restarts the WP journey before report submission ${url}`, async () => { + const sessionData = { + referer: '/water-pollution/check-your-answers' + } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.request.yar.get(constants.redisKeys.REFERER)).toEqual(null) + }) }) }) diff --git a/server/routes/__tests__/water-pollution/check-your-answers.spec.js b/server/routes/__tests__/water-pollution/check-your-answers.spec.js new file mode 100644 index 00000000..4a118fbf --- /dev/null +++ b/server/routes/__tests__/water-pollution/check-your-answers.spec.js @@ -0,0 +1,498 @@ +import { submitGetRequest, submitPostRequest } from '../../../__test-helpers__/server.js' +import constants from '../../../utils/constants.js' +import moment from 'moment' +import { sendMessage } from '../../../services/service-bus.js' +import { session } from '../../../__mock-data__/session-water-pollution.js' +jest.mock('../../../services/service-bus.js') + +const url = constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS +const header = 'Check your answers before sending your report' + +let sessionData = { + home: { + reporterName: 'John Smith', + reporterPhoneNumber: '012345678910', + reporterEmailAddress: 'test@test.com' + } +} + +describe(url, () => { + describe('GET', () => { + it(`Should return success response and correct view for ${url}`, async () => { + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('Your details') + expect(response.payload).toContain('Location and size of pollution') + expect(response.payload).toContain('About the pollution') + }) + it(`Happy: Should return correct view for your details section ${url}`, async () => { + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('John Smith') + expect(response.payload).toContain('012345678910') + expect(response.payload).toContain('test@test.com') + }) + it(`Happy: Should return correct answer for 'Images or videos available question' ${url}`, async () => { + const answerData = { + 'water-pollution/images-or-video': [{ + questionId: 2800, + questionAsked: 'Do you want to send us any images or videos of the pollution?', + questionResponse: true, + answerId: 2801 + }] + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('Yes') + }) + it(`Happy: Should return correct answer for 'Type of water' question ${url}`, async () => { + const answerData = { + 'water-pollution/water-feature': [{ + questionId: 500, + questionAsked: 'In what kind of water is the pollution?', + questionResponse: true, + answerId: 501 + }] + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('River') + }) + it(`Happy: Should return correct answer for 'Location - Describe the locaion' question ${url}`, async () => { + const answerData = { + 'water-pollution/location-option': [{ + questionId: 2600, + questionAsked: 'Where did you see the pollution?', + questionResponse: true, + answerId: 2601 + }] + } + const otherData = { + 'water-pollution/location-description': [{ + questionId: 900, + questionAsked: 'Where is the pollution?', + questionResponse: true, + answerId: 901, + otherDetails: 'Test data for location description' + }] + } + sessionData = { ...sessionData, ...answerData, ...otherData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('Test data for location description') + }) + it(`Happy: Should return correct answer for 'Less than 10m in size' question ${url}`, async () => { + const answerData = { + 'water-pollution/less-than-10-metres': [{ + questionId: 700, + questionAsked: 'Does the pollution spread less than 10 metres along the watercourse?', + questionResponse: true, + answerId: 702 + }] + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('No') + }) + it(`Happy: Should return correct answer for 'Less than 100 square metres in size' question ${url}`, async () => { + const answerData = { + 'water-pollution/less-than-100-sq-metres': [{ + questionId: 800, + questionAsked: 'Does the pollution cover an area less than 100 square metres in size?', + questionResponse: true, + answerId: 801 + }] + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('Yes') + }) + it(`Happy: Should return correct question label 'Less than 100 square metres in size' based on the answer for 'Type of water' question ${url}`, async () => { + const answerData = { + 'water-pollution/water-feature': [{ + questionId: 500, + questionAsked: 'In what kind of water is the pollution?', + questionResponse: true, + answerId: 502 + }] + } + const additionalData = { + 'water-pollution/less-than-100-sq-metres': [{ + questionId: 800, + questionAsked: 'Does the pollution cover an area less than 100 square metres in size?', + questionResponse: true, + answerId: 801 + }] + } + sessionData = { ...sessionData, ...answerData, ...additionalData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('Less than 100 square metres in size') + }) + it(`Happy: Should return correct question label 'Less than 10m in size' based on the answer for 'Type of water' question ${url}`, async () => { + const answerData = { + 'water-pollution/water-feature': [{ + questionId: 500, + questionAsked: 'In what kind of water is the pollution?', + questionResponse: true, + answerId: 501 + }] + } + const additionalData = { + 'water-pollution/less-than-10-metres': [{ + questionId: 700, + questionAsked: 'Does the pollution spread less than 10 metres along the watercourse?', + questionResponse: true, + answerId: 701 + }] + } + sessionData = { ...sessionData, ...answerData, ...additionalData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('Less than 10m in size') + }) + it(`Happy: Should return correct answer for 'Size (estimated)' question ${url}`, async () => { + const answerData = { + 'water-pollution/water-feature': [{ + questionId: 500, + questionAsked: 'In what kind of water is the pollution?', + questionResponse: true, + answerId: 501 + }] + } + const additionalData1 = { + 'water-pollution/less-than-10-metres': [{ + questionId: 700, + questionAsked: 'Does the pollution spread less than 10 metres along the watercourse?', + questionResponse: true, + answerId: 702 + }] + } + const additionalData2 = { + 'water-pollution/pollution-length': [{ + questionId: 400, + questionAsked: 'How far along the water feature does the pollution spread?', + questionResponse: true, + answerId: 402 + }] + } + sessionData = { ...sessionData, ...answerData, ...additionalData1, ...additionalData2 } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('100 to 500 metres') + }) + it(`Happy: Should return correct answer for 'When did you see the pollution?' question ${url}`, async () => { + const answerData = { + 'water-pollution/when': '2024-10-05T08:09:00.000Z' + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('5th October 2024 at 09:09 am') + }) + it(`Happy: Should accept a valid time for today and return correct answer for 'When did you see the pollution?' question ${url}`, async () => { + const date = new Date() + const dateTime = moment().hours(date.getHours().toString()).minutes(0).seconds(0).milliseconds(0) + const answerData = { + 'water-pollution/when': dateTime.toISOString() + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('Today at') + }) + it(`Happy: Should accept a valid time for yesterday and return correct answer for 'When did you see the pollution?' question ${url}`, async () => { + const dateTime = moment().hours(0).minutes(30).seconds(0).milliseconds(0).subtract(1, 'days') + const answerData = { + 'water-pollution/when': dateTime.toISOString() + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('Yesterday at') + }) + it(`Happy: Should return correct answer with date suffix 'st' for 'When did you see the pollution?' question ${url}`, async () => { + const answerData = { + 'water-pollution/when': '2024-11-01T09:09:00.000Z' + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('1st November 2024 at 09:09 am') + }) + it(`Happy: Should return correct answer with date suffix 'nd' for 'When did you see the pollution?' question ${url}`, async () => { + const answerData = { + 'water-pollution/when': '2024-11-02T09:09:00.000Z' + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('2nd November 2024 at 09:09 am') + }) + it(`Happy: Should return correct answer with date suffix 'rd' for 'When did you see the pollution?' question ${url}`, async () => { + const answerData = { + 'water-pollution/when': '2024-11-03T09:09:00.000Z' + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('3rd November 2024 at 09:09 am') + }) + it(`Happy: Should return correct answer with date suffix 'th' for 'When did you see the pollution?' question ${url}`, async () => { + const answerData = { + 'water-pollution/when': '2024-11-04T09:09:00.000Z' + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('4th November 2024 at 09:09 am') + }) + it(`Happy: Should return correct answer with date suffix default case 'th' for 'When did you see the pollution?' question ${url}`, async () => { + const answerData = { + 'water-pollution/when': '2024-10-25T08:09:00.000Z' + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('25th October 2024 at 09:09 am') + }) + it(`Happy: Should return correct answer with date for 12:00 pm scenario for 'When did you see the pollution?' question ${url}`, async () => { + const answerData = { + 'water-pollution/when': '2024-10-30T12:00:00.000Z' + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('30th October 2024 at 12:00 pm') + }) + it(`Happy: Should return correct answer for 'What do you think the pollution is?' question ${url}`, async () => { + const answerData = { + 'water-pollution/pollution-substance': [{ + questionId: 2900, + questionAsked: 'What do you think the pollution is?', + questionResponse: true, + answerId: 2901 + }, + { + questionId: 2900, + questionAsked: 'What do you think the pollution is?', + questionResponse: true, + answerId: 2902 + }, + { + questionId: 2900, + questionAsked: 'What do you think the pollution is?', + questionResponse: true, + answerId: 2903 + }] + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('Sewage') + expect(response.payload).toContain('Oil or petrol') + expect(response.payload).toContain('Agricultural waste') + }) + it(`Happy: Should return correct answer for 'What does the pollution look like?' question ${url}`, async () => { + const answerData = { + 'water-pollution/pollution-appearance': [{ + questionId: 1000, + questionAsked: 'What does the pollution look like?', + questionResponse: true, + answerId: 1002 + }, + { + questionId: 1000, + questionAsked: 'What does the pollution look like?', + questionResponse: true, + answerId: 1003 + }, + { + questionId: 1000, + questionAsked: 'What does the pollution look like?', + questionResponse: true, + answerId: 1004 + }, + { + questionId: 1000, + questionAsked: 'What does the pollution look like?', + questionResponse: true, + answerId: 1005, + otherDetails: 'Something else data for pollution appearance' + }] + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('Cloudy or grey water') + expect(response.payload).toContain('Foam or scum') + expect(response.payload).toContain('Something else - Something else data for pollution appearance') + }) + it(`Happy: Should return correct answer for 'Do you know where the pollution is coming from?' question ${url}`, async () => { + const answerData = { + 'water-pollution/source': [{ + questionId: 100, + questionAsked: 'Do you know where the pollution is coming from?', + questionResponse: true, + answerId: 101 + }, + { + questionId: 100, + questionAsked: 'Do you know where the pollution is coming from?', + questionResponse: true, + answerId: 103, + otherDetails: 'Test data for pollution source' + }] + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('Yes - Test data for pollution source') + }) + it(`Happy: Should return correct answer for 'Have you seen any dead fish or animals?' question ${url}`, async () => { + const answerData = { + 'water-pollution/effect-on-wildlife': [{ + questionId: 200, + questionAsked: 'Have you seen any dead or distressed fish or animals nearby?', + questionResponse: true, + answerId: 201 + }, + { + questionId: 200, + questionAsked: 'Have you seen any dead or distressed fish or animals nearby?', + questionResponse: true, + answerId: 203, + otherDetails: 'Test data for effect on wildlife' + }] + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('Yes - Test data for effect on wildlife') + }) + it(`Happy: Should return correct answer for 'Is there anything else you'd like to add?' question ${url}`, async () => { + const answerData = { + 'water-pollution/other-information': 'Details of other information' + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('Details of other information') + }) + it(`Happy: Should return correct answer as No for 'Is there anything else you'd like to add?' question if no data is provided ${url}`, async () => { + const answerData = { + 'water-pollution/other-information': '' + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('No') + }) + }) + + describe('POST', () => { + it('Should accept and store a description', async () => { + const options = { + url + } + const response = await submitPostRequest(options, 302, session) + expect(sendMessage).toHaveBeenCalledTimes(1) + expect(sendMessage).toHaveBeenCalledWith(expect.objectContaining({ + info: expect.any(Function) + }), + expect.objectContaining({ + reportingAnEnvironmentalProblem: expect.objectContaining({ + reportType: 100, + reporterName: 'John Smith', + reporterPhoneNumber: '012345678910', + reporterEmailAddress: 'test@test.com', + reporterAccessCode: 'password', + otherDetails: 'test', + questionSetId: 100, + data: expect.arrayContaining([ + expect.objectContaining({ + questionId: 500, + questionAsked: 'In what kind of water is the pollution?', + questionResponse: true, + answerId: 506 + }), + expect.objectContaining({ + questionId: 500, + questionAsked: 'In what kind of water is the pollution?', + questionResponse: true, + answerId: 508, + otherDetails: 'this is a test' + }), + expect.objectContaining({ + questionId: 700, + questionAsked: 'Does the pollution spread less than 10 metres along the watercourse?', + questionResponse: true, + answerId: 702 + }), + expect.objectContaining({ + questionId: 400, + questionAsked: 'How far along the water feature does the pollution spread?', + questionResponse: true, + answerId: 403 + }), + expect.objectContaining({ + questionId: 900, + questionAsked: 'Where is the pollution?', + questionResponse: true, + answerId: 901, + otherDetails: 'test location' + }), + expect.objectContaining({ + questionId: 1000, + questionAsked: 'What does the pollution look like?', + questionResponse: true, + answerId: 1002 + }), + expect.objectContaining({ + questionId: 1000, + questionAsked: 'What does the pollution look like?', + questionResponse: true, + answerId: 1003 + }), + expect.objectContaining({ + questionId: 2800, + questionAsked: 'Do you want to send us any images or videos of the pollution?', + questionResponse: true, + answerId: 2801 + }), + expect.objectContaining({ + questionId: 2900, + questionAsked: 'What do you think the pollution is?', + questionResponse: true, + answerId: 2901 + }), + expect.objectContaining({ + questionId: 2900, + questionAsked: 'What do you think the pollution is?', + questionResponse: true, + answerId: 2905 + }), + expect.objectContaining({ + questionId: 2900, + questionAsked: 'What do you think the pollution is?', + questionResponse: true, + answerId: 2907, + otherDetails: 'other details' + }), + expect.objectContaining({ + questionId: 100, + questionAsked: 'Do you know where the pollution is coming from?', + questionResponse: true, + answerId: 101 + }), + expect.objectContaining({ + questionId: 100, + questionAsked: 'Do you know where the pollution is coming from?', + questionResponse: true, + answerId: 103, + otherDetails: 'other details' + }) + ]) + }) + })) + // expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_OTHER_INFORMATION)).toEqual(otherInfo) + expect(new Date(response.request.yar.get(constants.redisKeys.SUBMISSION_TIMESTAMP))).toBeInstanceOf(Date) + expect(response.headers.location).toEqual(constants.routes.REPORT_SENT) + }) + it('Should error if validatePayload fails', async () => { + const { submitPostRequest } = await import('../../../__test-helpers__/server.js') + const helpers = await import('../../../utils/helpers.js') + helpers.validatePayload = jest.fn().mockImplementation(() => { + return false + }) + + const otherInfo = 'This is a description of the water pollution' + const options = { + url, + payload: { + otherInfo + } + } + await submitPostRequest(options, 500) + }) + }) +}) diff --git a/server/routes/__tests__/water-pollution/effect-on-wildlife.spec.js b/server/routes/__tests__/water-pollution/effect-on-wildlife.spec.js index 95391385..b3630c0f 100644 --- a/server/routes/__tests__/water-pollution/effect-on-wildlife.spec.js +++ b/server/routes/__tests__/water-pollution/effect-on-wildlife.spec.js @@ -10,26 +10,57 @@ const baseAnswer = { questionAsked: question.text, questionResponse: true } - -const payload = { - effectOnWildlife: 'yes', - yesDetails: 'Further details' -} - describe(url, () => { describe('GET', () => { it(`Should return success response and correct view for ${url}`, async () => { await submitGetRequest({ url }, header) }) + it(`Should return success response and correct view when yes is selected for ${url}`, async () => { + const sessionData = { + 'water-pollution/effect-on-wildlife': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.yes.answerId + }] + } + const response = await submitGetRequest({ url }, 'Have you seen any dead or distressed fish or animals nearby?', constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('') + }) + it(`Should return success response and correct view when no is selected for ${url}`, async () => { + const sessionData = { + 'water-pollution/effect-on-wildlife': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.no.answerId + }] + } + const response = await submitGetRequest({ url }, 'Have you seen any dead or distressed fish or animals nearby?', constants.statusCodes.OK, sessionData) + expect(response.payload).toContain(' { + const sessionData = { + 'water-pollution/effect-on-wildlife': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.yes.answerId + }, { + questionId: baseAnswer.questionId, + answerId: question.answers.yesDetails.answerId, + otherDetails: 'Further details' + }] + } + const response = await submitGetRequest({ url }, 'Have you seen any dead or distressed fish or animals nearby?', constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('') + expect(response.payload).toContain('Further details') + }) }) describe('POST', () => { it('Happy accepts Yes and yes Details and forwards to WATER_POLLUTION_OTHER_INFORMATION', async () => { + const answerId = question.answers.yes.answerId + const yesDetails = 'Further details' const options = { url, payload: { - effectOnWildlife: 'yes', - yesDetails: 'Further details' + answerId, + yesDetails } } const response = await submitPostRequest(options) @@ -40,14 +71,15 @@ describe(url, () => { }, { ...baseAnswer, answerId: question.answers.yesDetails.answerId, - otherDetails: payload.yesDetails + otherDetails: yesDetails }]) }) it('Happy accepts Yes and empty yes details and forwards to WATER_POLLUTION_OTHER_INFORMATION', async () => { + const answerId = question.answers.yes.answerId const options = { url, payload: { - effectOnWildlife: 'yes' + answerId } } const response = await submitPostRequest(options) @@ -58,10 +90,11 @@ describe(url, () => { }]) }) it('Happy accepts No and forwards to WATER_POLLUTION_OTHER_INFORMATION', async () => { + const answerId = question.answers.no.answerId const options = { url, payload: { - effectOnWildlife: 'no' + answerId } } const response = await submitPostRequest(options) diff --git a/server/routes/__tests__/water-pollution/images-or-video.spec.js b/server/routes/__tests__/water-pollution/images-or-video.spec.js index f4b3c707..e1192f79 100644 --- a/server/routes/__tests__/water-pollution/images-or-video.spec.js +++ b/server/routes/__tests__/water-pollution/images-or-video.spec.js @@ -16,12 +16,27 @@ const sessionData = { } } +const sessionDataWithAnswer = { + home: { + reporterEmailAddress: 'test@test.com' + }, + 'water-pollution/images-or-video': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.yes.answerId + }] +} + describe(url, () => { describe('GET', () => { it(`Should return success response and correct view for ${url}`, async () => { const response = await submitGetRequest({ url }, 'Do you want to send us any images or videos of the pollution?', constants.statusCodes.OK, sessionData) expect(response.payload).toContain('We\'ll send a message to test@test.com with details on where to send these, if needed.') }) + it(`Should return success response and correct view for ${url} with pre entered data`, async () => { + const response = await submitGetRequest({ url }, 'Do you want to send us any images or videos of the pollution?', constants.statusCodes.OK, sessionDataWithAnswer) + expect(response.payload).toContain('We\'ll send a message to test@test.com with details on where to send these, if needed.') + expect(response.payload).toContain('value="2801" checked') + }) }) describe('POST', () => { it('Should accept yes option and redirect to WATER_POLLUTION_LESS_THAN_10_METRES if flowing water feature', async () => { @@ -64,6 +79,48 @@ describe(url, () => { answerId }]) }) + it('Should accept yes option and redirect to WATER_POLLUTION_CHECK_YOUR_ANSWERS if flowing water feature if set in referer', async () => { + const answerId = question.answers.yes.answerId + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + 'water-pollution/water-feature': [{ + questionId: 500, + answerId: 501 // A River + }], + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_IMAGES_OR_VIDEO)).toEqual([{ + ...baseAnswer, + answerId + }]) + }) + it('Should accept no option and redirects to WATER_POLLUTION_CHECK_YOUR_ANSWERS if static water feature if set in referer', async () => { + const answerId = question.answers.yes.answerId + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + 'water-pollution/water-feature': [{ + questionId: 500, + answerId: 503 // The sea + }], + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_IMAGES_OR_VIDEO)).toEqual([{ + ...baseAnswer, + answerId + }]) + }) it('Sad: no radio selected, returns error state', async () => { const options = { url, diff --git a/server/routes/__tests__/water-pollution/less-than-10-metres.spec.js b/server/routes/__tests__/water-pollution/less-than-10-metres.spec.js index 7610ddff..4161b98b 100644 --- a/server/routes/__tests__/water-pollution/less-than-10-metres.spec.js +++ b/server/routes/__tests__/water-pollution/less-than-10-metres.spec.js @@ -30,6 +30,44 @@ describe(url, () => { sessionData[constants.redisKeys.WATER_POLLUTION_WATER_FEATURE][0].answerId = 505 await submitGetRequest({ url }, 'Does the pollution spread less than 10 metres along the watercourse?', constants.statusCodes.OK, sessionData) }) + it(`Should return success response and correct view when yes is selected for ${url}`, async () => { + let sessionData = { + 'water-pollution/less-than-10-metres': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.yes.answerId + }] + } + const answerData = { + 'water-pollution/water-feature': [{ + questionId: 500, + questionAsked: 'In what kind of water is the pollution?', + questionResponse: true, + answerId: 501 + }] + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, 'Does the pollution spread less than 10 metres along the river?', constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('') + }) + it(`Should return success response and correct view when no is selected for ${url}`, async () => { + let sessionData = { + 'water-pollution/less-than-10-metres': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.no.answerId + }] + } + const answerData = { + 'water-pollution/water-feature': [{ + questionId: 500, + questionAsked: 'In what kind of water is the pollution?', + questionResponse: true, + answerId: 504 + }] + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, 'Does the pollution spread less than 10 metres along the canal?', constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('') + }) }) describe('POST', () => { it('Happy: accepts yes and redirects to other information', async () => { @@ -86,5 +124,61 @@ describe(url, () => { expect(response.payload).toContain('There is a problem') expect(response.payload).toContain('Select yes if the pollution spreads less than 10 metres') }) + it('Happy: For CYA journey, accepts valid answerID for no and redirects to pollution-length', async () => { + const answerId = question.answers.no.answerId + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_POLLUTION_LENGTH) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_AREA)).toEqual(null) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_LESS_THAN_10_METRES)).toEqual([{ + ...baseAnswer, + answerId + }]) + }) + it('Happy: For CYA journey, accepts valid answerID for yes and redirects to check-your-answers', async () => { + const answerId = question.answers.yes.answerId + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_LENGTH)).toEqual(null) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_AREA)).toEqual(null) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_LESS_THAN_10_METRES)).toEqual([{ + ...baseAnswer, + answerId + }]) + }) + it('Happy: For CYA journey, accepts valid answerID for do not know and redirects to check-your-answers', async () => { + const answerId = question.answers.youDoNotKnow.answerId + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_LENGTH)).toEqual(null) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_AREA)).toEqual(null) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_LESS_THAN_10_METRES)).toEqual([{ + ...baseAnswer, + answerId + }]) + }) }) }) diff --git a/server/routes/__tests__/water-pollution/less-than-100-sq-metres.spec.js b/server/routes/__tests__/water-pollution/less-than-100-sq-metres.spec.js index 31056e49..145c13c9 100644 --- a/server/routes/__tests__/water-pollution/less-than-100-sq-metres.spec.js +++ b/server/routes/__tests__/water-pollution/less-than-100-sq-metres.spec.js @@ -16,6 +16,26 @@ describe(url, () => { it(`Should return success response and correct view for ${url}`, async () => { await submitGetRequest({ url }, header) }) + it(`Should return success response and correct view when yes is selected for ${url}`, async () => { + const sessionData = { + 'water-pollution/less-than-100-sq-metres': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.yes.answerId + }] + } + const response = await submitGetRequest({ url }, 'Does the pollution cover an area less than 100 square metres in size?', constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('') + }) + it(`Should return success response and correct view when no is selected for ${url}`, async () => { + const sessionData = { + 'water-pollution/less-than-100-sq-metres': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.no.answerId + }] + } + const response = await submitGetRequest({ url }, 'Does the pollution cover an area less than 100 square metres in size?', constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('') + }) }) describe('POST', () => { it('Happy: accepts yes and redirects to other information', async () => { @@ -72,5 +92,61 @@ describe(url, () => { expect(response.payload).toContain('There is a problem') expect(response.payload).toContain('Select yes if the pollution covers less than 100 square metres') }) + it('Happy: For CYA journey, accepts valid answerID for no and redirects to pollution-area', async () => { + const answerId = question.answers.no.answerId + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_POLLUTION_AREA) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_LENGTH)).toEqual(null) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_LESS_THAN_100_SQ_METRES)).toEqual([{ + ...baseAnswer, + answerId + }]) + }) + it('Happy: For CYA journey, accepts valid answerID for yes and redirects to check-your-answers', async () => { + const answerId = question.answers.yes.answerId + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_LENGTH)).toEqual(null) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_AREA)).toEqual(null) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_LESS_THAN_100_SQ_METRES)).toEqual([{ + ...baseAnswer, + answerId + }]) + }) + it('Happy: For CYA journey, accepts valid answerID for do not know and redirects to check-your-answers', async () => { + const answerId = question.answers.youDoNotKnow.answerId + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_LENGTH)).toEqual(null) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_AREA)).toEqual(null) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_LESS_THAN_100_SQ_METRES)).toEqual([{ + ...baseAnswer, + answerId + }]) + }) }) }) diff --git a/server/routes/__tests__/water-pollution/location-description.spec.js b/server/routes/__tests__/water-pollution/location-description.spec.js index 060e4445..61d259cd 100644 --- a/server/routes/__tests__/water-pollution/location-description.spec.js +++ b/server/routes/__tests__/water-pollution/location-description.spec.js @@ -12,11 +12,23 @@ const baseAnswer = { answerId: question.answers.locationDetails.answerId } +const sessionData = { + 'water-pollution/location-description': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.locationDetails.answerId, + otherDetails: 'test details' + }] +} + describe(url, () => { describe('GET', () => { it(`Should return success response and correct view for ${url}`, async () => { await submitGetRequest({ url }, header) }) + it(`Should return success response and correct view for ${url}`, async () => { + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('test details') + }) }) describe('POST', () => { @@ -35,6 +47,23 @@ describe(url, () => { otherDetails: locationDescription }]) }) + it('Happy: accept and store a location description and redirect to referrer', async () => { + const locationDescription = 'This is a description of the location of the water pollution' + const options = { + url, + payload: { + locationDescription + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_LOCATION_DESCRIPTION)).toEqual([{ + ...baseAnswer, + otherDetails: locationDescription + }]) + }) it('Sad: errors on no locationDescription provided', async () => { const options = { url, diff --git a/server/routes/__tests__/water-pollution/location-map.spec.js b/server/routes/__tests__/water-pollution/location-map.spec.js index 63f52bdb..6162769d 100644 --- a/server/routes/__tests__/water-pollution/location-map.spec.js +++ b/server/routes/__tests__/water-pollution/location-map.spec.js @@ -52,6 +52,40 @@ describe(url, () => { otherDetails: '52.983397' }]) }) + it('Happy: accept and store a point as a national grid reference and redirects to referer', async () => { + const point = '[365739.764, 343015.986]' + const options = { + url, + payload: { + point + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_LOCATION_MAP)).toEqual([{ + ...baseAnswer, + answerId: question.answers.nationalGridReference.answerId, + otherDetails: 'SJ 65739 43015' + }, { + ...baseAnswer, + answerId: question.answers.easting.answerId, + otherDetails: '365739' + }, { + ...baseAnswer, + answerId: question.answers.northing.answerId, + otherDetails: '343015' + }, { + ...baseAnswer, + answerId: question.answers.lng.answerId, + otherDetails: '-2.511745' + }, { + ...baseAnswer, + answerId: question.answers.lat.answerId, + otherDetails: '52.983397' + }]) + }) it('Sad: errors on no point provided', async () => { const options = { url, diff --git a/server/routes/__tests__/water-pollution/location-option.spec.js b/server/routes/__tests__/water-pollution/location-option.spec.js index 31dcc44d..2d707e94 100644 --- a/server/routes/__tests__/water-pollution/location-option.spec.js +++ b/server/routes/__tests__/water-pollution/location-option.spec.js @@ -10,11 +10,22 @@ const baseAnswer = { questionResponse: true } +const sessionData = { + 'water-pollution/location-option': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.description.answerId + }] +} + describe(url, () => { describe('GET', () => { it(`Should return success response and correct view for ${url}`, async () => { await submitGetRequest({ url }, 'Where did you see the pollution?') }) + it(`Should return success response and correct view for ${url}`, async () => { + const response = await submitGetRequest({ url }, 'Where did you see the pollution?', constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('') + }) }) describe('POST', () => { it('Should accept map option and redirect to water-pollution/location-map', async () => { @@ -32,7 +43,7 @@ describe(url, () => { answerId }]) }) - it('Should accept description option and redirect to water-pollution/location-description', async () => { + it('Should accept description option and redirect to water-pollution/location-description even with referrer set', async () => { const answerId = question.answers.description.answerId const options = { url, @@ -40,7 +51,9 @@ describe(url, () => { answerId } } - const response = await submitPostRequest(options) + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_LOCATION_DESCRIPTION) expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_LOCATION_OPTION)).toEqual([{ ...baseAnswer, diff --git a/server/routes/__tests__/water-pollution/other-information.spec.js b/server/routes/__tests__/water-pollution/other-information.spec.js index e5eba0e2..3dbecd42 100644 --- a/server/routes/__tests__/water-pollution/other-information.spec.js +++ b/server/routes/__tests__/water-pollution/other-information.spec.js @@ -1,8 +1,5 @@ import { submitGetRequest, submitPostRequest } from '../../../__test-helpers__/server.js' import constants from '../../../utils/constants.js' -import { sendMessage } from '../../../services/service-bus.js' -import { session } from '../../../__mock-data__/session-water-pollution.js' -jest.mock('../../../services/service-bus.js') const url = constants.routes.WATER_POLLUTION_OTHER_INFORMATION const header = 'Is there anything else you\'d like to add (optional)?' @@ -12,6 +9,13 @@ describe(url, () => { it(`Should return success response and correct view for ${url}`, async () => { await submitGetRequest({ url }, header) }) + it(`Should return success response and correct view with prefilled data for ${url}`, async () => { + const sessionData = { + 'water-pollution/other-information': 'Details of other information' + } + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('Details of other information { @@ -23,125 +27,9 @@ describe(url, () => { otherInfo } } - const response = await submitPostRequest(options, 302, session) - expect(sendMessage).toHaveBeenCalledTimes(1) - expect(sendMessage).toHaveBeenCalledWith(expect.objectContaining({ - info: expect.any(Function) - }), - expect.objectContaining({ - reportingAnEnvironmentalProblem: expect.objectContaining({ - reportType: 100, - reporterName: 'John Smith', - reporterPhoneNumber: '012345678910', - reporterEmailAddress: 'test@test.com', - reporterAccessCode: 'password', - otherDetails: otherInfo, - questionSetId: 100, - data: expect.arrayContaining([ - expect.objectContaining({ - questionId: 500, - questionAsked: 'In what kind of water is the pollution?', - questionResponse: true, - answerId: 506 - }), - expect.objectContaining({ - questionId: 500, - questionAsked: 'In what kind of water is the pollution?', - questionResponse: true, - answerId: 508, - otherDetails: 'this is a test' - }), - expect.objectContaining({ - questionId: 700, - questionAsked: 'Does the pollution spread less than 10 metres along the watercourse?', - questionResponse: true, - answerId: 702 - }), - expect.objectContaining({ - questionId: 400, - questionAsked: 'How far along the water feature does the pollution spread?', - questionResponse: true, - answerId: 403 - }), - expect.objectContaining({ - questionId: 900, - questionAsked: 'Where is the pollution?', - questionResponse: true, - answerId: 901, - otherDetails: 'test location' - }), - expect.objectContaining({ - questionId: 1000, - questionAsked: 'What does the pollution look like?', - questionResponse: true, - answerId: 1002 - }), - expect.objectContaining({ - questionId: 1000, - questionAsked: 'What does the pollution look like?', - questionResponse: true, - answerId: 1003 - }), - expect.objectContaining({ - questionId: 2800, - questionAsked: 'Do you want to send us any images or videos of the pollution?', - questionResponse: true, - answerId: 2801 - }), - expect.objectContaining({ - questionId: 2900, - questionAsked: 'What do you think the pollution is?', - questionResponse: true, - answerId: 2901 - }), - expect.objectContaining({ - questionId: 2900, - questionAsked: 'What do you think the pollution is?', - questionResponse: true, - answerId: 2905 - }), - expect.objectContaining({ - questionId: 2900, - questionAsked: 'What do you think the pollution is?', - questionResponse: true, - answerId: 2907, - otherDetails: 'other details' - }), - expect.objectContaining({ - questionId: 100, - questionAsked: 'Do you know where the pollution is coming from?', - questionResponse: true, - answerId: 101 - }), - expect.objectContaining({ - questionId: 100, - questionAsked: 'Do you know where the pollution is coming from?', - questionResponse: true, - answerId: 103, - otherDetails: 'other details' - }) - ]) - }) - })) + const response = await submitPostRequest(options) expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_OTHER_INFORMATION)).toEqual(otherInfo) - expect(new Date(response.request.yar.get(constants.redisKeys.SUBMISSION_TIMESTAMP))).toBeInstanceOf(Date) - expect(response.headers.location).toEqual(constants.routes.REPORT_SENT) - }) - it('Should error if validatePayload fails', async () => { - const { submitPostRequest } = await import('../../../__test-helpers__/server.js') - const helpers = await import('../../../utils/helpers.js') - helpers.validatePayload = jest.fn().mockImplementation(() => { - return false - }) - - const otherInfo = 'This is a description of the water pollution' - const options = { - url, - payload: { - otherInfo - } - } - await submitPostRequest(options, 500) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) }) }) }) diff --git a/server/routes/__tests__/water-pollution/pollution-appearance.spec.js b/server/routes/__tests__/water-pollution/pollution-appearance.spec.js index 482e230d..b57897a3 100644 --- a/server/routes/__tests__/water-pollution/pollution-appearance.spec.js +++ b/server/routes/__tests__/water-pollution/pollution-appearance.spec.js @@ -10,11 +10,35 @@ const baseAnswer = { questionResponse: true } +const sessionData = { + 'water-pollution/pollution-appearance': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.cloudy.answerId + }, { + questionId: baseAnswer.questionId, + answerId: question.answers.scum.answerId + }, { + questionId: baseAnswer.questionId, + answerId: question.answers.somethingElse.answerId + }, { + questionId: baseAnswer.questionId, + answerId: question.answers.somethingElseDetail.answerId, + otherDetails: 'test details' + }] +} + describe(url, () => { describe('GET', () => { it(`Should return success response and correct view for ${url}`, async () => { await submitGetRequest({ url }, baseAnswer.questionAsked) }) + it(`Should return success response and correct view for ${url} with prior entered values`, async () => { + const response = await submitGetRequest({ url }, baseAnswer.questionAsked, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('') + expect(response.payload).toContain('') + expect(response.payload).toContain('') + }) }) describe('POST', () => { @@ -35,8 +59,8 @@ describe(url, () => { }) it('Happy: accepts valid answerIds and redirects to WATER_POLLUTION_SOURCE', async () => { const answerId = [ - question.answers.cloudy.answerId, - question.answers.scum.answerId + question.answers.cloudy.answerId.toString(), + question.answers.scum.answerId.toString() ] const options = { url, @@ -48,18 +72,18 @@ describe(url, () => { expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_SOURCE) expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_APPEARANCE)).toEqual([{ ...baseAnswer, - answerId: answerId[0] + answerId: Number(answerId[0]) }, { ...baseAnswer, - answerId: answerId[1] + answerId: Number(answerId[1]) }]) }) it('Happy: accepts valid answerId with something else details', async () => { const somethingElseDetail = 'Something else details' const answerId = [ - question.answers.cloudy.answerId, - question.answers.scum.answerId, - question.answers.somethingElse.answerId + question.answers.cloudy.answerId.toString(), + question.answers.scum.answerId.toString(), + question.answers.somethingElse.answerId.toString() ] const options = { url, @@ -72,19 +96,36 @@ describe(url, () => { expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_SOURCE) expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_APPEARANCE)).toEqual([{ ...baseAnswer, - answerId: answerId[0] + answerId: Number(answerId[0]) }, { ...baseAnswer, - answerId: answerId[1] + answerId: Number(answerId[1]) }, { ...baseAnswer, - answerId: answerId[2] + answerId: Number(answerId[2]) }, { ...baseAnswer, answerId: question.answers.somethingElseDetail.answerId, otherDetails: somethingElseDetail }]) }) + it('Happy: Redirects to referer when set', async () => { + const answerId = question.answers.cloudy.answerId.toString() + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_APPEARANCE)).toEqual([{ + ...baseAnswer, + answerId: question.answers.cloudy.answerId + }]) + }) it('Sad: errors on no answerId', async () => { const options = { url, diff --git a/server/routes/__tests__/water-pollution/pollution-area.spec.js b/server/routes/__tests__/water-pollution/pollution-area.spec.js index a64d8cb4..2b214a33 100644 --- a/server/routes/__tests__/water-pollution/pollution-area.spec.js +++ b/server/routes/__tests__/water-pollution/pollution-area.spec.js @@ -15,6 +15,16 @@ describe(url, () => { it(`Should return success response and correct view for ${url}`, async () => { await submitGetRequest({ url }, question.text) }) + it(`Should return success response and correct view when 100 to 500 metres is selected for ${url}`, async () => { + const sessionData = { + 'water-pollution/pollution-area': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.over500sqm.answerId + }] + } + const response = await submitGetRequest({ url }, 'How large an area does the pollution cover?', constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('') + }) }) describe('POST', () => { it('Happy: accepts valid answer and redirects to other information', async () => { @@ -41,5 +51,22 @@ describe(url, () => { expect(response.payload).toContain('There is a problem') expect(response.payload).toContain('Select your estimated area, or that you do not know') }) + it('Happy: For CYA journey, accepts valid answer and redirects to check-your-answers', async () => { + const answerId = question.answers.under500sqm.answerId + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_AREA)).toEqual([{ + ...baseAnswer, + answerId + }]) + }) }) }) diff --git a/server/routes/__tests__/water-pollution/pollution-length.spec.js b/server/routes/__tests__/water-pollution/pollution-length.spec.js index 8e422396..56baac63 100644 --- a/server/routes/__tests__/water-pollution/pollution-length.spec.js +++ b/server/routes/__tests__/water-pollution/pollution-length.spec.js @@ -30,6 +30,25 @@ describe(url, () => { sessionData[constants.redisKeys.WATER_POLLUTION_WATER_FEATURE][0].answerId = 505 await submitGetRequest({ url }, 'How far along the watercourse does the pollution spread?', constants.statusCodes.OK, sessionData) }) + it(`Should return success response and correct view when 100 to 500 metres is selected for ${url}`, async () => { + let sessionData = { + 'water-pollution/pollution-length': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.stretches100to500m.answerId + }] + } + const answerData = { + 'water-pollution/water-feature': [{ + questionId: 500, + questionAsked: 'In what kind of water is the pollution?', + questionResponse: true, + answerId: 501 + }] + } + sessionData = { ...sessionData, ...answerData } + const response = await submitGetRequest({ url }, 'How far along the river does the pollution spread?', constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('') + }) }) describe('POST', () => { it('Happy: accepts valid answer and redirects to width', async () => { @@ -56,5 +75,22 @@ describe(url, () => { expect(response.payload).toContain('There is a problem') expect(response.payload).toContain('Select your estimated length, or that you do not know') }) + it('Happy: For CYA journey, accepts valid answer and redirects to check-your-answers', async () => { + const answerId = question.answers.stretches10to100m.answerId + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_LENGTH)).toEqual([{ + ...baseAnswer, + answerId + }]) + }) }) }) diff --git a/server/routes/__tests__/water-pollution/pollution-substance.spec.js b/server/routes/__tests__/water-pollution/pollution-substance.spec.js index 0762a3a5..3412df3d 100644 --- a/server/routes/__tests__/water-pollution/pollution-substance.spec.js +++ b/server/routes/__tests__/water-pollution/pollution-substance.spec.js @@ -10,11 +10,35 @@ const baseAnswer = { questionResponse: true } +const sessionData = { + 'water-pollution/pollution-substance': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.sewage.answerId + }, { + questionId: baseAnswer.questionId, + answerId: question.answers.chemical.answerId + }, { + questionId: baseAnswer.questionId, + answerId: question.answers.somethingElse.answerId + }, { + questionId: baseAnswer.questionId, + answerId: question.answers.somethingElseDetail.answerId, + otherDetails: 'test details' + }] +} + describe(url, () => { describe('GET', () => { it(`Should return success response and correct view for ${url}`, async () => { await submitGetRequest({ url }, baseAnswer.questionAsked) }) + it(`Should return success response and correct view for ${url} with prior entered values`, async () => { + const response = await submitGetRequest({ url }, baseAnswer.questionAsked, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('') + expect(response.payload).toContain('') + expect(response.payload).toContain('') + }) }) describe('POST', () => { @@ -87,5 +111,22 @@ describe(url, () => { answerId: question.answers.unknown.answerId }]) }) + it('Happy: Redirects to referer when set', async () => { + const answerId = question.answers.sewage.answerId.toString() + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_POLLUTION_SUBSTANCE)).toEqual([{ + ...baseAnswer, + answerId: question.answers.sewage.answerId + }]) + }) }) }) diff --git a/server/routes/__tests__/water-pollution/source.spec.js b/server/routes/__tests__/water-pollution/source.spec.js index 48ffa67c..158e0c63 100644 --- a/server/routes/__tests__/water-pollution/source.spec.js +++ b/server/routes/__tests__/water-pollution/source.spec.js @@ -11,11 +11,27 @@ const baseAnswer = { questionResponse: true } +const sessionData = { + 'water-pollution/source': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.yes.answerId + }, { + questionId: baseAnswer.questionId, + answerId: question.answers.yesDetails.answerId, + otherDetails: 'test details' + }] +} + describe(url, () => { describe('GET', () => { it(`Should return success response and correct view for ${url}`, async () => { await submitGetRequest({ url }, header) }) + it(`Should return success response and correct view for ${url}`, async () => { + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('value="101" checked') + expect(response.payload).toContain('test details') + }) }) describe('POST', () => { diff --git a/server/routes/__tests__/water-pollution/water-feature.spec.js b/server/routes/__tests__/water-pollution/water-feature.spec.js index 792e7fd8..fd523f85 100644 --- a/server/routes/__tests__/water-pollution/water-feature.spec.js +++ b/server/routes/__tests__/water-pollution/water-feature.spec.js @@ -16,6 +16,41 @@ describe(url, () => { it(`Should return success response and correct view for ${url}`, async () => { await submitGetRequest({ url }, header) }) + it(`Should return success response and correct view when a river is selected for ${url}`, async () => { + const sessionData = { + 'water-pollution/water-feature': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.river.answerId + }] + } + const response = await submitGetRequest({ url }, 'In what kind of water is the pollution?', constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('') + }) + it(`Should return success response and correct view when the sea is selected for ${url}`, async () => { + const sessionData = { + 'water-pollution/water-feature': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.sea.answerId + }] + } + const response = await submitGetRequest({ url }, 'In what kind of water is the pollution?', constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('') + }) + it(`Should return success response and correct view when something else is selected for ${url}`, async () => { + const sessionData = { + 'water-pollution/water-feature': [{ + questionId: baseAnswer.questionId, + answerId: question.answers.somethingElse.answerId + }, { + questionId: baseAnswer.questionId, + answerId: question.answers.somethingElseDetails.answerId, + otherDetails: 'test details' + }] + } + const response = await submitGetRequest({ url }, 'In what kind of water is the pollution?', constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('') + expect(response.payload).toContain('value="test details">') + }) }) describe('POST', () => { it('Happy: accepts valid answerId of sea or lake/reservoir and redirects to pollution-location', async () => { @@ -50,12 +85,12 @@ describe(url, () => { }) it('Happy: accepts valid answerId of something else with further details ', async () => { const answerId = question.answers.somethingElse.answerId - const otherSource = 'test other details' + const somethingElseDetails = 'test other details' const options = { url, payload: { answerId, - otherSource + somethingElseDetails } } const response = await submitPostRequest(options) @@ -66,7 +101,7 @@ describe(url, () => { }, { ...baseAnswer, answerId: question.answers.somethingElseDetails.answerId, - otherDetails: otherSource + otherDetails: somethingElseDetails }]) }) it('Sad: errors on no answerId', async () => { @@ -78,5 +113,73 @@ describe(url, () => { expect(response.payload).toContain('There is a problem') expect(response.payload).toContain('Select a type of watercourse or feature, or you do not know') }) + it('Happy: For CYA journey, accepts valid answerID for lake/reservoir and redirects to less-than-100-sq-metres', async () => { + const answerId = question.answers.lakeOrReservoir.answerId + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_LESS_THAN_100_SQ_METRES) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_WATER_FEATURE)).toEqual([{ + ...baseAnswer, + answerId + }]) + }) + it('Happy: For CYA journey, accepts valid answerID for sea and redirects to less-than-100-sq-metres', async () => { + const answerId = question.answers.sea.answerId + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_LESS_THAN_100_SQ_METRES) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_WATER_FEATURE)).toEqual([{ + ...baseAnswer, + answerId + }]) + }) + it('Happy: For CYA journey, accepts valid answerID for river and redirects to less-than-10-metres', async () => { + const answerId = question.answers.river.answerId + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_LESS_THAN_10_METRES) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_WATER_FEATURE)).toEqual([{ + ...baseAnswer, + answerId + }]) + }) + it('Happy: For CYA journey, accepts valid answerID for do not know and redirects to less-than-10-metres', async () => { + const answerId = question.answers.youDoNotKnow.answerId + const options = { + url, + payload: { + answerId + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_LESS_THAN_10_METRES) + expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_WATER_FEATURE)).toEqual([{ + ...baseAnswer, + answerId + }]) + }) }) }) diff --git a/server/routes/__tests__/water-pollution/when.spec.js b/server/routes/__tests__/water-pollution/when.spec.js index a40b1a5e..ea9b8661 100644 --- a/server/routes/__tests__/water-pollution/when.spec.js +++ b/server/routes/__tests__/water-pollution/when.spec.js @@ -1,6 +1,7 @@ import { submitGetRequest, submitPostRequest } from '../../../__test-helpers__/server.js' import constants from '../../../utils/constants.js' import moment from 'moment' +import { getDateContext } from '../../../utils/date-helpers.js' const url = constants.routes.WATER_POLLUTION_WHEN const header = 'When did you see the pollution?' @@ -25,6 +26,112 @@ describe(url, () => { it(`Should return success response and correct view for ${url}`, async () => { await submitGetRequest({ url }, header) }) + it('Should show today\'s date in correct inputs on return to page', async () => { + const today = new Date() + const session = { + 'water-pollution/when': today.toISOString() + } + + const context = getDateContext(today) + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, session) + expect(response.payload).toContain('') + expect(response.payload).toContain(``) + expect(response.payload).toContain(``) + expect(response.payload).toContain(``) + }) + it('Should show yesterday\'s date in correct inputs on return to page', async () => { + const yesterday = new Date() + yesterday.setDate(yesterday.getDate() - 1) + const session = { + 'water-pollution/when': yesterday.toISOString() + } + + const context = getDateContext(yesterday) + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, session) + expect(response.payload).toContain('') + expect(response.payload).toContain(``) + expect(response.payload).toContain(``) + expect(response.payload).toContain(``) + }) + it('Should show earlier date in correct inputs on return to page', async () => { + const earlier = new Date() + earlier.setDate(earlier.getDate() - 7) + const session = { + 'water-pollution/when': earlier.toISOString() + } + + const context = getDateContext(earlier) + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, session) + expect(response.payload).toContain(`id="date-day" name="date-day" type="text" value="${context.day}" inputmode="numeric">`) + expect(response.payload).toContain(`id="date-month" name="date-month" type="text" value="${context.month}" inputmode="numeric">`) + expect(response.payload).toContain(`id="date-year" name="date-year" type="text" value="${context.year}" inputmode="numeric">`) + expect(response.payload).toContain('') + expect(response.payload).toContain(``) + expect(response.payload).toContain(``) + expect(response.payload).toContain(``) + }) + it('Should show earlier date in correct inputs on return to page with an am time in GMT', async () => { + const earlier = new Date('2024-11-01T10:00:00.000Z') + const session = { + 'water-pollution/when': earlier.toISOString() + } + + // const context = getDateContext(earlier) + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, session) + expect(response.payload).toContain('id="date-day" name="date-day" type="text" value="1" inputmode="numeric">') + expect(response.payload).toContain('id="date-month" name="date-month" type="text" value="11" inputmode="numeric">') + expect(response.payload).toContain('id="date-year" name="date-year" type="text" value="2024" inputmode="numeric">') + expect(response.payload).toContain('') + expect(response.payload).toContain('') + expect(response.payload).toContain('') + expect(response.payload).toContain('') + }) + it('Should show earlier date in correct inputs on return to page with a pm time in GMT', async () => { + const earlier = new Date('2024-11-01T16:00:00.000Z') + const session = { + 'water-pollution/when': earlier.toISOString() + } + + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, session) + expect(response.payload).toContain('id="date-day" name="date-day" type="text" value="1" inputmode="numeric">') + expect(response.payload).toContain('id="date-month" name="date-month" type="text" value="11" inputmode="numeric">') + expect(response.payload).toContain('id="date-year" name="date-year" type="text" value="2024" inputmode="numeric">') + expect(response.payload).toContain('') + expect(response.payload).toContain('') + expect(response.payload).toContain('') + expect(response.payload).toContain('') + }) + it('Should show earlier date in correct inputs on return to page with an am time in BST', async () => { + const earlier = new Date('2024-07-01T10:00:00.000Z') + const session = { + 'water-pollution/when': earlier.toISOString() + } + + // const context = getDateContext(earlier) + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, session) + expect(response.payload).toContain('id="date-day" name="date-day" type="text" value="1" inputmode="numeric">') + expect(response.payload).toContain('id="date-month" name="date-month" type="text" value="7" inputmode="numeric">') + expect(response.payload).toContain('id="date-year" name="date-year" type="text" value="2024" inputmode="numeric">') + expect(response.payload).toContain('') + expect(response.payload).toContain('') + expect(response.payload).toContain('') + expect(response.payload).toContain('') + }) + it('Should show earlier date in correct inputs on return to page with a pm time in BST', async () => { + const earlier = new Date('2024-07-01T16:00:00.000Z') + const session = { + 'water-pollution/when': earlier.toISOString() + } + + const response = await submitGetRequest({ url }, header, constants.statusCodes.OK, session) + expect(response.payload).toContain('id="date-day" name="date-day" type="text" value="1" inputmode="numeric">') + expect(response.payload).toContain('id="date-month" name="date-month" type="text" value="7" inputmode="numeric">') + expect(response.payload).toContain('id="date-year" name="date-year" type="text" value="2024" inputmode="numeric">') + expect(response.payload).toContain('') + expect(response.payload).toContain('') + expect(response.payload).toContain('') + expect(response.payload).toContain('') + }) }) describe('POST', () => { @@ -67,7 +174,7 @@ describe(url, () => { expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_POLLUTION_SUBSTANCE) expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_WHEN)).toEqual(dateTime.toISOString()) }) - it('Happy: accept a valid time and date not today or yesterday and continue to WATER_POLLUTION_POLLUTION_SUBSTANCE', async () => { + it('Happy: accept a valid time and date not today or yesterday and continue to WATER_POLLUTION_CHECK_YOUR_ANSWERS when REFERER is set', async () => { const options = { url, payload: { @@ -81,8 +188,10 @@ describe(url, () => { } } const dateTime = moment('2024-09-11T11:00:00.000Z') - const response = await submitPostRequest(options) - expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_POLLUTION_SUBSTANCE) + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, { + referer: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS + }) + expect(response.headers.location).toEqual(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) expect(response.request.yar.get(constants.redisKeys.WATER_POLLUTION_WHEN)).toEqual(dateTime.toISOString()) }) it('Sad path: No option selected', async () => { diff --git a/server/routes/__tests__/water-pollution/your-details.spec.js b/server/routes/__tests__/water-pollution/your-details.spec.js new file mode 100644 index 00000000..0dec426a --- /dev/null +++ b/server/routes/__tests__/water-pollution/your-details.spec.js @@ -0,0 +1,87 @@ +import { submitGetRequest, submitPostRequest } from '../../../__test-helpers__/server.js' +import constants from '../../../utils/constants.js' +const url = constants.routes.WATER_POLLUTION_YOUR_DETAILS +const phoneEmptyError = 'Enter a phone number' +const phoneError = 'Enter a phone number, like 01632 960 001, 07700 900 982 or +44 808 157 0192' +const emailError = 'Enter an email address in the correct format, like name@example.com' + +const sessionData = { + home: { + reporterName: 'test name', + reporterPhoneNumber: '012345678910', + reporterEmailAddress: 'test@test.com', + reporterAccessCode: 'test' + } +} + +describe(url, () => { + describe('GET', () => { + it('Should display update-details view', async () => { + const response = await submitGetRequest({ url }, 'Your details', constants.statusCodes.OK, sessionData) + expect(response.result).toContain('value="test name"') + expect(response.result).toContain('value="012345678910"') + expect(response.result).toContain('value="test@test.com"') + }) + }) + describe('POST', () => { + // Happy: All valid with correct accessCode + it('Should redirect to WATER_POLLUTION_CHECK_YOUR_ANSWERS', async () => { + const options = { + url, + payload: { + fullName: 'John Smith', + phone: '#+441234567890', + email: 'test@test.com' + } + } + const response = await submitPostRequest(options, constants.statusCodes.REDIRECT, sessionData) + expect(response.headers.location).toEqual('/water-pollution/check-your-answers') + expect(response.request.yar.get(constants.redisKeys.HOME)).toEqual({ + reporterName: 'John Smith', + reporterPhoneNumber: '#+441234567890', + reporterEmailAddress: 'test@test.com', + reporterAccessCode: 'test' + }) + }) + // Sad: name, phone, code missing + it('Should error if all is data missing', async () => { + const options = { + url, + payload: {} + } + const response = await submitPostRequest(options, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('There is a problem') + expect(response.payload).toContain('Enter your name') + expect(response.payload).toContain(phoneEmptyError) + expect(response.payload).toContain(emailError) + }) + // Sad: invalid phone format + it('Should error with if invalid phone number', async () => { + const options = { + url, + payload: { + fullName: 'John Smith', + phone: 'sdfsrt' + } + } + const response = await submitPostRequest(options, 200, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('There is a problem') + expect(response.payload).not.toContain('Enter your name') + expect(response.payload).toContain(phoneError) + }) + // Sad: invalid email format + it('Should error with if invalid email address', async () => { + const options = { + url, + payload: { + fullName: 'John Smith', + phone: '012345678910', + email: 'sdfdsf' + } + } + const response = await submitPostRequest(options, 200, constants.statusCodes.OK, sessionData) + expect(response.payload).toContain('There is a problem') + expect(response.payload).toContain(emailError) + }) + }) +}) diff --git a/server/routes/smell/location-map.js b/server/routes/smell/location-map.js index 6b3f307a..0e4938b7 100644 --- a/server/routes/smell/location-map.js +++ b/server/routes/smell/location-map.js @@ -39,7 +39,8 @@ const handlers = { const getContext = () => { return { - question + question, + locationAnswer: {} } } diff --git a/server/routes/water-pollution.js b/server/routes/water-pollution.js index 873ee60e..037a7743 100644 --- a/server/routes/water-pollution.js +++ b/server/routes/water-pollution.js @@ -1,8 +1,10 @@ import constants from '../utils/constants.js' const handlers = { - get: async (_request, h) => { + get: async (request, h) => { const context = _getContext() + // Clear referer key in case if user restarts the journey before report submission + request.yar.clear(constants.redisKeys.REFERER) return h.view(constants.views.WATER_POLUTION, { ...context }) diff --git a/server/routes/water-pollution/check-your-answers.js b/server/routes/water-pollution/check-your-answers.js new file mode 100644 index 00000000..ab198d22 --- /dev/null +++ b/server/routes/water-pollution/check-your-answers.js @@ -0,0 +1,342 @@ +import constants from '../../utils/constants.js' +import { questionSets } from '../../utils/question-sets.js' +import { sendMessage } from '../../services/service-bus.js' +import { validatePayload } from '../../utils/helpers.js' + +const url = constants.routes + +const handlers = { + get: async (request, h) => { + return h.view(constants.views.WATER_POLLUTION_CHECK_YOUR_ANSWERS, { + ...getContext(), + ...getYourDetails(request), + ...getLocationAndSizeOfPollution(request), + ...getAboutThePollution(request) + }) + }, + post: async (request, h) => { + request.yar.set(constants.redisKeys.SUBMISSION_TIMESTAMP, (new Date()).toISOString()) + + // Build the payload to send to service bus + const payload = buildPayload(request.yar) + + // test the payload against the schema + if (!validatePayload(payload)) { + throw new Error('Invalid payload') + } + + await sendMessage(request.logger, payload) + + return h.redirect(constants.routes.REPORT_SENT) + } +} + +const getContext = () => { + return { + url + } +} + +// Get answers for 'Your details' section +const getYourDetails = (request) => { + // Get answer for 'Name, Phone number and Email address' questions + const { reporterName, reporterPhoneNumber, reporterEmailAddress } = request.yar.get(constants.redisKeys.HOME) + + // Get answer for 'Images or videos available' question + const imagesOrVideoUrl = 'WATER_POLLUTION_IMAGES_OR_VIDEO' + const imagesOrVideoAnswer = getData(request, imagesOrVideoUrl) + + return { + reporterName, + reporterPhoneNumber, + reporterEmailAddress, + imagesOrVideoAnswer + } +} + +// Get answers for 'Location and size of pollution' section +const getLocationAndSizeOfPollution = (request) => { + // Get answer for 'Type of water' question + const waterFeatureAnswer = getDataSet(request, 'WATER_POLLUTION_WATER_FEATURE') + + // Do we need to show map or location description + const locationAnswer = getLocationAnswer(request, 'WATER_POLLUTION_LOCATION_OPTION') + + // Get answer for 'Less than 10m in size' question + const lessThan10MetersAnswer = getData(request, 'WATER_POLLUTION_LESS_THAN_10_METRES') + + // Get answer for 'Less than 100 square meters in size' question + const lessThan100SqMetersAnswer = getData(request, 'WATER_POLLUTION_LESS_THAN_100_SQ_METRES') + + // Check if 'Type of water' is measured in area + const isMeasuredInArea = getIsMeasuredInArea(request) + let lessThanSizeAnswer + if (isMeasuredInArea) { + lessThanSizeAnswer = lessThan100SqMetersAnswer + } else { + lessThanSizeAnswer = lessThan10MetersAnswer + } + + // Check if 'Size (estimated)' option is required + const isSizeEstimatedRequired = getIsSizeEstimatedRequired(request) + let sizeEstimatedAnswer + + // Get answer for 'Size (estimated)' question + if (isSizeEstimatedRequired) { + const pollutionLengthAnswer = getData(request, 'WATER_POLLUTION_POLLUTION_LENGTH') + const pollutionAreaAnswer = getData(request, 'WATER_POLLUTION_POLLUTION_AREA') + + sizeEstimatedAnswer = pollutionLengthAnswer || pollutionAreaAnswer + } + + return { + waterFeatureAnswer, + locationAnswer, + lessThanSizeAnswer, + isMeasuredInArea, + isSizeEstimatedRequired, + sizeEstimatedAnswer + } +} + +// Get answers for 'About the pollution' section +const getAboutThePollution = (request) => { + // Get answer for 'When did you see the pollution?' question + const whenAnswer = getWhenData(request, 'WATER_POLLUTION_WHEN') + + // Get answer for 'What do you think the pollution is?' question + const pollutionSubstanceAnswer = getDataSet(request, 'WATER_POLLUTION_POLLUTION_SUBSTANCE') + + // get answer for 'What does the pollution look like?' question + const pollutionAppearanceAnswer = getDataSet(request, 'WATER_POLLUTION_POLLUTION_APPEARANCE') + + // Get answer for 'Do you know where the pollution is coming from?' question + const pollutionSourceAnswer = getDataSet(request, 'WATER_POLLUTION_SOURCE') + + // Get answer for 'Have you seen any dead fish or animals?' question + const effectOnWildlifeAnswer = getDataSet(request, 'WATER_POLLUTION_EFFECT_ON_WILDLIFE') + + // Get answer for 'Is there anything else you'd like to add?' question + const otherInformationAnswer = request.yar.get(constants.redisKeys.WATER_POLLUTION_OTHER_INFORMATION) || 'No' + + return { + whenAnswer, + pollutionSubstanceAnswer, + pollutionAppearanceAnswer, + pollutionSourceAnswer, + effectOnWildlifeAnswer, + otherInformationAnswer + } +} + +// Get data and construct answers for the questions +const getData = (request, pageUrl) => { + const recordedAnswer = request.yar.get(constants.redisKeys[pageUrl]) + if (recordedAnswer?.length === 1) { + const selectedAnswerId = recordedAnswer[0].answerId + const answerSet = Object.values(questionSets.WATER_POLLUTION.questions[pageUrl].answers) + const filterAnswer = answerSet.filter(item => item.answerId === selectedAnswerId) + return filterAnswer[0].shortText || filterAnswer[0].text + } else if (recordedAnswer?.length > 1) { + const multiAnswerSet = [] + let otherDetailsData + + for (const element of recordedAnswer) { + const selectedAnswerId = element.answerId + const answerSet = Object.values(questionSets.WATER_POLLUTION.questions[pageUrl].answers) + const filterAnswer = answerSet.filter(item => item.answerId === selectedAnswerId) + const answerText = filterAnswer[0].shortText + if (answerText) { + multiAnswerSet.push(answerText) + } + if (element.otherDetails) { + otherDetailsData = element.otherDetails + } + } + + return { + answerText: multiAnswerSet, + otherDetails: otherDetailsData + } + } else { + return null + } +} + +// Get data and construct multiple answers for the questions +const getDataSet = (request, pageUrl) => { + const recordedAnswerSet = getData(request, pageUrl) + let answerData + if (recordedAnswerSet?.otherDetails) { + const joinData = recordedAnswerSet.answerText.join('
') + answerData = `${joinData} - ${recordedAnswerSet.otherDetails}` + } else if (recordedAnswerSet?.answerText) { + answerData = recordedAnswerSet.answerText.join('
') + } else { + answerData = recordedAnswerSet + } + + return answerData +} + +// Get either map details or location description +const getLocationAnswer = (request, pageUrl) => { + const locationOptionAnswer = getData(request, pageUrl) + let locationAnswerData + if (locationOptionAnswer) { + if (locationOptionAnswer === questionSets.WATER_POLLUTION.questions[pageUrl].answers.description.text) { + locationAnswerData = request.yar.get(constants.redisKeys.WATER_POLLUTION_LOCATION_DESCRIPTION)[0].otherDetails + } else { + const location = request.yar.get(constants.redisKeys.WATER_POLLUTION_LOCATION_MAP) + locationAnswerData = { + point: [Number(location[1].otherDetails), Number(location[2].otherDetails)], + disableControls: true, + zoom: 10 + } + } + } + return locationAnswerData +} + +const getIsMeasuredInArea = (request) => { + const waterFeatureAnswerData = request.yar.get(constants.redisKeys.WATER_POLLUTION_WATER_FEATURE) + let isMeasuredInAreaData = false + if (waterFeatureAnswerData) { + const answerIsLakeorReservoir = waterFeatureAnswerData[0].answerId === questionSets.WATER_POLLUTION.questions.WATER_POLLUTION_WATER_FEATURE.answers.lakeOrReservoir.answerId + const answerIsSea = waterFeatureAnswerData[0].answerId === questionSets.WATER_POLLUTION.questions.WATER_POLLUTION_WATER_FEATURE.answers.sea.answerId + isMeasuredInAreaData = answerIsLakeorReservoir || answerIsSea + } + + return isMeasuredInAreaData +} + +const getIsSizeEstimatedRequired = (request) => { + const lessThan10MetersAnswerData = request.yar.get(constants.redisKeys.WATER_POLLUTION_LESS_THAN_10_METRES) + const lessThan100SqMetersAnswerData = request.yar.get(constants.redisKeys.WATER_POLLUTION_LESS_THAN_100_SQ_METRES) + + // Check if 'Size (estimated)' field is required + let isSizeEstimatedRequiredData = false + if (lessThan10MetersAnswerData && lessThan10MetersAnswerData[0].answerId === questionSets.WATER_POLLUTION.questions.WATER_POLLUTION_LESS_THAN_10_METRES.answers.no.answerId) { + isSizeEstimatedRequiredData = true + } else if (lessThan100SqMetersAnswerData && lessThan100SqMetersAnswerData[0].answerId === questionSets.WATER_POLLUTION.questions.WATER_POLLUTION_LESS_THAN_100_SQ_METRES.answers.no.answerId) { + isSizeEstimatedRequiredData = true + } else { + // do nothing for sonarcloud + } + + return isSizeEstimatedRequiredData +} + +// Format date and time data +const getWhenData = (request, pageUrl) => { + const whenAnswerData = request.yar.get(constants.redisKeys[pageUrl]) + let dateTimeData + const pollutionDateAndTime = new Date(whenAnswerData) + + if (whenAnswerData) { + const checkIfToday = () => { + const today = new Date() + return pollutionDateAndTime.getDate() === today.getDate() && + pollutionDateAndTime.getMonth() === today.getMonth() && + pollutionDateAndTime.getFullYear() === today.getFullYear() + } + + const checkIfYesterday = () => { + const yesterday = new Date() + yesterday.setDate(yesterday.getDate() - 1) + return pollutionDateAndTime.getDate() === yesterday.getDate() && + pollutionDateAndTime.getMonth() === yesterday.getMonth() && + pollutionDateAndTime.getFullYear() === yesterday.getFullYear() + } + + const isToday = checkIfToday() + const isYesterday = checkIfYesterday() + + const date = new Date(pollutionDateAndTime) + const pollutionTime = date.toLocaleString('en-GB', { + hour: '2-digit', + minute: '2-digit', + hourCycle: 'h12', + timeZone: 'Europe/London' + }) + + if (isToday) { + dateTimeData = `Today at ${pollutionTime}` + } else if (isYesterday) { + dateTimeData = `Yesterday at ${pollutionTime}` + } else { + const dateObj = new Date(pollutionDateAndTime) + const day = dateObj.getDate() + const month = dateObj.toLocaleString('default', { month: 'long' }) + const year = dateObj.getFullYear() + + const nthNumber = (number) => { + const numRangeStart = 3 + const numRangeEnd = 21 + if (number > numRangeStart && number < numRangeEnd) { + return 'th' + } + + const numPrefixOne = 1 + const numPrefixTwo = 2 + const numPrefixThree = 3 + + switch (number % 10) { + case numPrefixOne: + return 'st' + case numPrefixTwo: + return 'nd' + case numPrefixThree: + return 'rd' + default: + return 'th' + } + } + const pollutionDate = `${day}${nthNumber(day)} ${month} ${year}` + dateTimeData = `${pollutionDate} at ${pollutionTime}` + } + + return dateTimeData + } + return null +} + +const buildPayload = (session) => { + const reporter = session.get(constants.redisKeys.HOME) + return { + reportingAnEnvironmentalProblem: { + sessionGuid: session.id, + reportType: questionSets.WATER_POLLUTION.questionSetId, + datetimeObserved: session.get(constants.redisKeys.WATER_POLLUTION_WHEN), + datetimeReported: session.get(constants.redisKeys.SUBMISSION_TIMESTAMP), + otherDetails: session.get(constants.redisKeys.WATER_POLLUTION_OTHER_INFORMATION), + questionSetId: questionSets.WATER_POLLUTION.questionSetId, + data: buildAnswerDataset(session, questionSets.WATER_POLLUTION), + ...reporter + } + } +} + +const buildAnswerDataset = (session, questionSet) => { + const data = [] + Object.keys(questionSet.questions).forEach(key => { + const answers = session.get(questionSet.questions[key].key) + answers?.forEach(item => { + data.push(item) + }) + }) + return data +} + +export default [ + { + method: 'GET', + path: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS, + handler: handlers.get + }, + { + method: 'POST', + path: constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS, + handler: handlers.post + } +] diff --git a/server/routes/water-pollution/effect-on-wildlife.js b/server/routes/water-pollution/effect-on-wildlife.js index f958af41..b60d8cd2 100644 --- a/server/routes/water-pollution/effect-on-wildlife.js +++ b/server/routes/water-pollution/effect-on-wildlife.js @@ -11,57 +11,69 @@ const baseAnswer = { } const handlers = { - get: async (_request, h) => { + get: async (request, h) => { return h.view(constants.views.WATER_POLLUTION_EFFECT_ON_WILDLIFE, { - ...getContext() + ...getContext(request) }) }, post: async (request, h) => { + // get payload + let { answerId, yesDetails } = request.payload + // validate payload - const errorSummary = validatePayload(request.payload) + const errorSummary = validatePayload(answerId) if (errorSummary.errorList.length > 0) { return h.view(constants.views.WATER_POLLUTION_EFFECT_ON_WILDLIFE, { - ...getContext(), - errorSummary, - ...request.payload + ...getContext(request), + errorSummary }) } - request.yar.set(constants.redisKeys.WATER_POLLUTION_EFFECT_ON_WILDLIFE, buildAnswers(request.payload)) + // convert answerId to number + answerId = Number(answerId) + + // set answer in session + request.yar.set(constants.redisKeys.WATER_POLLUTION_EFFECT_ON_WILDLIFE, buildAnswers(answerId, yesDetails)) - return h.redirect(constants.routes.WATER_POLLUTION_OTHER_INFORMATION) + // handle redirection + return h.redirect(request.yar.get(constants.redisKeys.REFERER) || constants.routes.WATER_POLLUTION_OTHER_INFORMATION) } } -const getContext = () => { +const getContext = (request) => { + const answers = request.yar.get(question.key) return { - question + question, + answers } } -const validatePayload = payload => { +const validatePayload = answerId => { const errorSummary = getErrorSummary() - if (!payload.effectOnWildlife) { + if (!answerId) { errorSummary.errorList.push({ text: 'Select yes if you\'ve seen dead or distressed fish or other animals nearby', - href: '#effectOnWildlife' + href: '#answerId' }) } return errorSummary } -const buildAnswers = payload => { - const answers = [{ +const buildAnswers = (answerId, yesDetails) => { + const answers = [] + answers.push({ ...baseAnswer, - answerId: payload.effectOnWildlife === 'yes' ? question.answers.yes.answerId : question.answers.no.answerId - }] - if (payload.effectOnWildlife === 'yes' && payload.yesDetails) { + answerId + }) + + if (answerId === question.answers.yes.answerId && yesDetails) { answers.push({ ...baseAnswer, answerId: question.answers.yesDetails.answerId, - otherDetails: payload.yesDetails + otherDetails: yesDetails }) } + return answers } diff --git a/server/routes/water-pollution/images-or-video.js b/server/routes/water-pollution/images-or-video.js index fa056e26..7fe9221f 100644 --- a/server/routes/water-pollution/images-or-video.js +++ b/server/routes/water-pollution/images-or-video.js @@ -37,18 +37,20 @@ const handlers = { // handle redirects const waterFeatureAnswer = request.yar.get(constants.redisKeys.WATER_POLLUTION_WATER_FEATURE) if (waterFeatureAnswer[0].answerId === waterFeatureQuestion.answers.lakeOrReservoir.answerId || waterFeatureAnswer[0].answerId === waterFeatureQuestion.answers.sea.answerId) { - return h.redirect(constants.routes.WATER_POLLUTION_LESS_THAN_100_SQ_METRES) + return h.redirect(request.yar.get(constants.redisKeys.REFERER) || constants.routes.WATER_POLLUTION_LESS_THAN_100_SQ_METRES) } else { - return h.redirect(constants.routes.WATER_POLLUTION_LESS_THAN_10_METRES) + return h.redirect(request.yar.get(constants.redisKeys.REFERER) || constants.routes.WATER_POLLUTION_LESS_THAN_10_METRES) } } } const getContext = (request) => { const { reporterEmailAddress } = request.yar.get(constants.redisKeys.HOME) + const answers = request.yar.get(question.key) return { question, - reporterEmailAddress + reporterEmailAddress, + answers } } diff --git a/server/routes/water-pollution/less-than-10-metres.js b/server/routes/water-pollution/less-than-10-metres.js index 3e1a0e0b..7053fd2f 100644 --- a/server/routes/water-pollution/less-than-10-metres.js +++ b/server/routes/water-pollution/less-than-10-metres.js @@ -36,7 +36,17 @@ const handlers = { request.yar.set(constants.redisKeys.WATER_POLLUTION_LESS_THAN_10_METRES, buildAnswers(answerId)) // handle redirects - if (answerId === question.answers.no.answerId) { + const refValue = request.yar.get(constants.redisKeys.REFERER) + if (refValue) { + if (answerId === question.answers.no.answerId) { + request.yar.clear(constants.redisKeys.WATER_POLLUTION_POLLUTION_AREA) + return h.redirect(constants.routes.WATER_POLLUTION_POLLUTION_LENGTH) + } else { + request.yar.clear(constants.redisKeys.WATER_POLLUTION_POLLUTION_LENGTH) + request.yar.clear(constants.redisKeys.WATER_POLLUTION_POLLUTION_AREA) + return h.redirect(request.yar.get(constants.redisKeys.REFERER)) + } + } else if (answerId === question.answers.no.answerId) { return h.redirect(constants.routes.WATER_POLLUTION_POLLUTION_LENGTH) } else { return h.redirect(constants.routes.WATER_POLLUTION_EFFECT_ON_WILDLIFE) @@ -46,9 +56,11 @@ const handlers = { const getContext = request => { const waterFeature = constants.waterFeatureLabels[request.yar.get(constants.redisKeys.WATER_POLLUTION_WATER_FEATURE)[0].answerId] + const answers = request.yar.get(question.key) return { question, - waterFeature + waterFeature, + answers } } diff --git a/server/routes/water-pollution/less-than-100-sq-metres.js b/server/routes/water-pollution/less-than-100-sq-metres.js index 8377613e..77eb78a9 100644 --- a/server/routes/water-pollution/less-than-100-sq-metres.js +++ b/server/routes/water-pollution/less-than-100-sq-metres.js @@ -11,9 +11,9 @@ const baseAnswer = { } const handlers = { - get: async (_request, h) => { + get: async (request, h) => { return h.view(constants.views.WATER_POLLUTION_LESS_THAN_100_SQ_METRES, { - ...getContext() + ...getContext(request) }) }, post: async (request, h) => { @@ -24,7 +24,7 @@ const handlers = { if (errorSummary.errorList.length > 0) { return h.view(constants.views.WATER_POLLUTION_LESS_THAN_100_SQ_METRES, { errorSummary, - ...getContext() + ...getContext(request) }) } @@ -35,7 +35,17 @@ const handlers = { request.yar.set(constants.redisKeys.WATER_POLLUTION_LESS_THAN_100_SQ_METRES, buildAnswers(answerId)) // handle redirects - if (answerId === question.answers.no.answerId) { + const refValue = request.yar.get(constants.redisKeys.REFERER) + if (refValue) { + if (answerId === question.answers.no.answerId) { + request.yar.clear(constants.redisKeys.WATER_POLLUTION_POLLUTION_LENGTH) + return h.redirect(constants.routes.WATER_POLLUTION_POLLUTION_AREA) + } else { + request.yar.clear(constants.redisKeys.WATER_POLLUTION_POLLUTION_AREA) + request.yar.clear(constants.redisKeys.WATER_POLLUTION_POLLUTION_LENGTH) + return h.redirect(request.yar.get(constants.redisKeys.REFERER)) + } + } else if (answerId === question.answers.no.answerId) { return h.redirect(constants.routes.WATER_POLLUTION_POLLUTION_AREA) } else { return h.redirect(constants.routes.WATER_POLLUTION_EFFECT_ON_WILDLIFE) @@ -43,9 +53,11 @@ const handlers = { } } -const getContext = () => { +const getContext = (request) => { + const answers = request.yar.get(question.key) return { - question + question, + answers } } diff --git a/server/routes/water-pollution/location-description.js b/server/routes/water-pollution/location-description.js index f5882e72..24c9bf76 100644 --- a/server/routes/water-pollution/location-description.js +++ b/server/routes/water-pollution/location-description.js @@ -12,9 +12,9 @@ const baseAnswer = { } const handlers = { - get: async (_request, h) => { + get: async (request, h) => { return h.view(constants.views.WATER_POLLUTION_LOCATION_DESCRIPTION, { - ...getContext() + ...getContext(request) }) }, post: async (request, h) => { @@ -24,20 +24,22 @@ const handlers = { const errorSummary = validatePayload(locationDescription) if (errorSummary.errorList.length > 0) { return h.view(constants.views.WATER_POLLUTION_LOCATION_DESCRIPTION, { - ...getContext(), + ...getContext(request), errorSummary }) } - request.yar.set(constants.redisKeys.WATER_POLLUTION_LOCATION_DESCRIPTION, buildAnswers(locationDescription)) + request.yar.set(question.key, buildAnswers(locationDescription)) - return h.redirect(constants.routes.WATER_POLLUTION_WHEN) + return h.redirect(request.yar.get(constants.redisKeys.REFERER) || constants.routes.WATER_POLLUTION_WHEN) } } -const getContext = () => { +const getContext = request => { + const answers = request.yar.get(question.key) return { - question + question, + answers } } diff --git a/server/routes/water-pollution/location-map.js b/server/routes/water-pollution/location-map.js index b4d0947b..68e6314b 100644 --- a/server/routes/water-pollution/location-map.js +++ b/server/routes/water-pollution/location-map.js @@ -11,9 +11,9 @@ const baseAnswer = { } const handlers = { - get: async (_request, h) => { + get: async (request, h) => { return h.view(constants.views.WATER_POLLUTION_LOCATION_MAP, { - ...getContext() + ...getContext(request) }) }, post: async (request, h) => { @@ -23,23 +23,30 @@ const handlers = { if (!point || point.length === 0) { return h.view(constants.views.WATER_POLLUTION_LOCATION_MAP, { - ...getContext(), + ...getContext(request), noPoint: true }) } const lngLat = oSGBToWGS84(point) - request.yar.set(constants.redisKeys.WATER_POLLUTION_LOCATION_MAP, buildAnswers(point, lngLat)) + request.yar.set(question.key, buildAnswers(point, lngLat)) // handle redirects - return h.redirect(constants.routes.WATER_POLLUTION_WHEN) + return h.redirect(request.yar.get(constants.redisKeys.REFERER) || constants.routes.WATER_POLLUTION_WHEN) } } -const getContext = () => { +const getContext = request => { + const location = request.yar.get(constants.redisKeys.WATER_POLLUTION_LOCATION_MAP) + const locationAnswer = location && { + point: [Number(location[1].otherDetails), Number(location[2].otherDetails)], + zoom: 10 + } + return { - question + question, + locationAnswer } } diff --git a/server/routes/water-pollution/location-option.js b/server/routes/water-pollution/location-option.js index 4d12edee..027b605a 100644 --- a/server/routes/water-pollution/location-option.js +++ b/server/routes/water-pollution/location-option.js @@ -11,9 +11,9 @@ const baseAnswer = { } const handlers = { - get: async (_request, h) => { + get: async (request, h) => { return h.view(constants.views.WATER_POLLUTION_LOCATION_OPTION, { - ...getContext() + ...getContext(request) }) }, post: async (request, h) => { @@ -23,7 +23,7 @@ const handlers = { const errorSummary = validatePayload(answerId) if (errorSummary.errorList.length > 0) { return h.view(constants.views.WATER_POLLUTION_LOCATION_OPTION, { - ...getContext(), + ...getContext(request), errorSummary }) } @@ -42,9 +42,11 @@ const handlers = { } } -const getContext = () => { +const getContext = request => { + const answers = request.yar.get(question.key) return { - question + question, + answers } } diff --git a/server/routes/water-pollution/other-information.js b/server/routes/water-pollution/other-information.js index 48a26e0c..e599dbb5 100644 --- a/server/routes/water-pollution/other-information.js +++ b/server/routes/water-pollution/other-information.js @@ -1,57 +1,26 @@ import constants from '../../utils/constants.js' -import { questionSets } from '../../utils/question-sets.js' -import { sendMessage } from '../../services/service-bus.js' -import { validatePayload } from '../../utils/helpers.js' const handlers = { - get: async (_request, h) => h.view(constants.views.WATER_POLLUTION_OTHER_INFORMATION), + get: async (request, h) => { + return h.view(constants.views.WATER_POLLUTION_OTHER_INFORMATION, { + ...getContext(request) + }) + }, post: async (request, h) => { const { otherInfo } = request.payload request.yar.set(constants.redisKeys.WATER_POLLUTION_OTHER_INFORMATION, otherInfo) - request.yar.set(constants.redisKeys.SUBMISSION_TIMESTAMP, (new Date()).toISOString()) - - // Build the payload to send to service bus - const payload = buildPayload(request.yar) - - // test the payload against the schema - if (!validatePayload(payload)) { - throw new Error('Invalid payload') - } - - await sendMessage(request.logger, payload) - - return h.redirect(constants.routes.REPORT_SENT) + return h.redirect(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) } } -const buildPayload = (session) => { - const reporter = session.get(constants.redisKeys.HOME) +const getContext = request => { + const answers = request.yar.get(constants.redisKeys.WATER_POLLUTION_OTHER_INFORMATION) return { - reportingAnEnvironmentalProblem: { - sessionGuid: session.id, - reportType: questionSets.WATER_POLLUTION.questionSetId, - datetimeObserved: session.get(constants.redisKeys.WATER_POLLUTION_WHEN), - datetimeReported: session.get(constants.redisKeys.SUBMISSION_TIMESTAMP), - otherDetails: session.get(constants.redisKeys.WATER_POLLUTION_OTHER_INFORMATION), - questionSetId: questionSets.WATER_POLLUTION.questionSetId, - data: buildAnswerDataset(session, questionSets.WATER_POLLUTION), - ...reporter - } + answers } } -const buildAnswerDataset = (session, questionSet) => { - const data = [] - Object.keys(questionSet.questions).forEach(key => { - const answers = session.get(questionSet.questions[key].key) - answers?.forEach(item => { - data.push(item) - }) - }) - return data -} - export default [ { method: 'GET', diff --git a/server/routes/water-pollution/pollution-appearance.js b/server/routes/water-pollution/pollution-appearance.js index aeba2637..2d307e8b 100644 --- a/server/routes/water-pollution/pollution-appearance.js +++ b/server/routes/water-pollution/pollution-appearance.js @@ -10,8 +10,8 @@ const baseAnswer = { } const handlers = { - get: async (_request, h) => h.view(constants.views.WATER_POLLUTION_POLLUTION_APPEARANCE, { - ...getContext() + get: async (request, h) => h.view(constants.views.WATER_POLLUTION_POLLUTION_APPEARANCE, { + ...getContext(request) }), post: async (request, h) => { // get payload @@ -20,9 +20,10 @@ const handlers = { // validate payload for errors const errorSummary = validatePayload(answerId) if (errorSummary.errorList.length > 0) { + request.yar.set(question.key, []) return h.view(constants.views.WATER_POLLUTION_POLLUTION_APPEARANCE, { errorSummary, - ...getContext() + ...getContext(request) }) } @@ -32,9 +33,9 @@ const handlers = { } // set answer in session - request.yar.set(constants.redisKeys.WATER_POLLUTION_POLLUTION_APPEARANCE, buildAnswers(answerId, somethingElseDetail)) + request.yar.set(question.key, buildAnswers(answerId, somethingElseDetail)) - return h.redirect(constants.routes.WATER_POLLUTION_SOURCE) + return h.redirect(request.yar.get(constants.redisKeys.REFERER) || constants.routes.WATER_POLLUTION_SOURCE) } } @@ -47,7 +48,7 @@ const buildAnswers = (answerId, somethingElseDetail) => { }) }) - if (somethingElseDetail) { + if (answerId.indexOf(question.answers.somethingElse.answerId.toString()) > -1 && somethingElseDetail) { answers.push({ ...baseAnswer, answerId: question.answers.somethingElseDetail.answerId, @@ -58,9 +59,11 @@ const buildAnswers = (answerId, somethingElseDetail) => { return answers } -const getContext = () => { +const getContext = request => { + const answers = request.yar.get(question.key) return { - question + question, + answers } } diff --git a/server/routes/water-pollution/pollution-area.js b/server/routes/water-pollution/pollution-area.js index ffd75976..a69428db 100644 --- a/server/routes/water-pollution/pollution-area.js +++ b/server/routes/water-pollution/pollution-area.js @@ -11,9 +11,9 @@ const baseAnswer = { } const handlers = { - get: async (_request, h) => { + get: async (request, h) => { return h.view(constants.views.WATER_POLLUTION_POLLUTION_AREA, { - ...getContext() + ...getContext(request) }) }, post: async (request, h) => { @@ -25,7 +25,7 @@ const handlers = { if (errorSummary.errorList.length > 0) { return h.view(constants.views.WATER_POLLUTION_POLLUTION_AREA, { errorSummary, - ...getContext() + ...getContext(request) }) } @@ -36,7 +36,7 @@ const handlers = { request.yar.set(constants.redisKeys.WATER_POLLUTION_POLLUTION_AREA, buildAnswers(answerId)) // handle redirection - return h.redirect(constants.routes.WATER_POLLUTION_EFFECT_ON_WILDLIFE) + return h.redirect(request.yar.get(constants.redisKeys.REFERER) || constants.routes.WATER_POLLUTION_EFFECT_ON_WILDLIFE) } } @@ -49,9 +49,11 @@ const buildAnswers = answerId => { return answers } -const getContext = () => { +const getContext = request => { + const answers = request.yar.get(question.key) return { - question + question, + answers } } diff --git a/server/routes/water-pollution/pollution-length.js b/server/routes/water-pollution/pollution-length.js index caa74a27..5c3afb1b 100644 --- a/server/routes/water-pollution/pollution-length.js +++ b/server/routes/water-pollution/pollution-length.js @@ -36,7 +36,7 @@ const handlers = { request.yar.set(constants.redisKeys.WATER_POLLUTION_POLLUTION_LENGTH, buildAnswers(answerId)) // handle redirection - return h.redirect(constants.routes.WATER_POLLUTION_EFFECT_ON_WILDLIFE) + return h.redirect(request.yar.get(constants.redisKeys.REFERER) || constants.routes.WATER_POLLUTION_EFFECT_ON_WILDLIFE) } } @@ -51,9 +51,11 @@ const buildAnswers = answerId => { const getContext = request => { const waterFeature = constants.waterFeatureLabels[request.yar.get(constants.redisKeys.WATER_POLLUTION_WATER_FEATURE)[0].answerId] + const answers = request.yar.get(question.key) return { question, - waterFeature + waterFeature, + answers } } diff --git a/server/routes/water-pollution/pollution-substance.js b/server/routes/water-pollution/pollution-substance.js index 619ca878..8a5a562d 100644 --- a/server/routes/water-pollution/pollution-substance.js +++ b/server/routes/water-pollution/pollution-substance.js @@ -9,8 +9,8 @@ const baseAnswer = { } const handlers = { - get: async (_request, h) => h.view(constants.views.WATER_POLLUTION_POLLUTION_SUBSTANCE, { - ...getContext() + get: async (request, h) => h.view(constants.views.WATER_POLLUTION_POLLUTION_SUBSTANCE, { + ...getContext(request) }), post: async (request, h) => { // get payload @@ -22,9 +22,9 @@ const handlers = { } // set answer in session - request.yar.set(constants.redisKeys.WATER_POLLUTION_POLLUTION_SUBSTANCE, buildAnswers(answerId, somethingElseDetail)) + request.yar.set(question.key, buildAnswers(answerId, somethingElseDetail)) - return h.redirect(constants.routes.WATER_POLLUTION_POLLUTION_APPEARANCE) + return h.redirect(request.yar.get(constants.redisKeys.REFERER) || constants.routes.WATER_POLLUTION_POLLUTION_APPEARANCE) } } @@ -59,9 +59,11 @@ const buildAnswers = (answerId, somethingElseDetail) => { return answers } -const getContext = () => { +const getContext = request => { + const answers = request.yar.get(question.key) return { - question + question, + answers } } diff --git a/server/routes/water-pollution/source.js b/server/routes/water-pollution/source.js index c04ef6e0..adb224b5 100644 --- a/server/routes/water-pollution/source.js +++ b/server/routes/water-pollution/source.js @@ -11,9 +11,9 @@ const baseAnswer = { } const handlers = { - get: async (_request, h) => { + get: async (request, h) => { return h.view(constants.views.WATER_POLLUTION_SOURCE, { - ...getContext() + ...getContext(request) }) }, post: async (request, h) => { @@ -23,7 +23,7 @@ const handlers = { const errorSummary = validatePayload(answerId, yesDetails) if (errorSummary.errorList.length > 0) { return h.view(constants.views.WATER_POLLUTION_SOURCE, { - ...getContext(), + ...getContext(request), errorSummary, yesChecked: Number(answerId) === question.answers.yes.answerId }) @@ -32,16 +32,18 @@ const handlers = { // convert answerId to number answerId = Number(answerId) - request.yar.set(constants.redisKeys.WATER_POLLUTION_SOURCE, buildAnswers(answerId, yesDetails)) + request.yar.set(question.key, buildAnswers(answerId, yesDetails)) // handle redirects - return h.redirect(constants.routes.WATER_POLLUTION_IMAGES_OR_VIDEO) + return h.redirect(request.yar.get(constants.redisKeys.REFERER) || constants.routes.WATER_POLLUTION_IMAGES_OR_VIDEO) } } -const getContext = () => { +const getContext = request => { + const answers = request.yar.get(question.key) return { - question + question, + answers } } diff --git a/server/routes/water-pollution/water-feature.js b/server/routes/water-pollution/water-feature.js index 70f5a451..169df624 100644 --- a/server/routes/water-pollution/water-feature.js +++ b/server/routes/water-pollution/water-feature.js @@ -11,21 +11,21 @@ const baseAnswer = { } const handlers = { - get: async (_request, h) => { + get: async (request, h) => { return h.view(constants.views.WATER_POLLUTION_WATER_FEATURE, { - ...getContext() + ...getContext(request) }) }, post: async (request, h) => { // get payload - let { answerId, otherSource } = request.payload + let { answerId, somethingElseDetails } = request.payload // validate payload for errors const errorSummary = validatePayload(answerId) if (errorSummary.errorList.length > 0) { return h.view(constants.views.WATER_POLLUTION_WATER_FEATURE, { errorSummary, - ...getContext() + ...getContext(request) }) } @@ -33,33 +33,46 @@ const handlers = { answerId = Number(answerId) // set answer in session - request.yar.set(constants.redisKeys.WATER_POLLUTION_WATER_FEATURE, buildAnswers(answerId, otherSource)) - - return h.redirect(constants.routes.WATER_POLLUTION_LOCATION_OPTION) + request.yar.set(constants.redisKeys.WATER_POLLUTION_WATER_FEATURE, buildAnswers(answerId, somethingElseDetails)) + // handle redirects + const refValue = request.yar.get(constants.redisKeys.REFERER) + if (refValue) { + if (answerId === question.answers.lakeOrReservoir.answerId || answerId === question.answers.sea.answerId) { + request.yar.clear(constants.redisKeys.WATER_POLLUTION_LESS_THAN_10_METRES) + return h.redirect(constants.routes.WATER_POLLUTION_LESS_THAN_100_SQ_METRES) + } else { + request.yar.clear(constants.redisKeys.WATER_POLLUTION_LESS_THAN_100_SQ_METRES) + return h.redirect(constants.routes.WATER_POLLUTION_LESS_THAN_10_METRES) + } + } else { + return h.redirect(constants.routes.WATER_POLLUTION_LOCATION_OPTION) + } } } -const buildAnswers = (answerId, otherSource) => { +const buildAnswers = (answerId, somethingElseDetails) => { const answers = [] answers.push({ ...baseAnswer, answerId }) - if (answerId === question.answers.somethingElse.answerId && otherSource) { + if (answerId === question.answers.somethingElse.answerId && somethingElseDetails) { answers.push({ ...baseAnswer, answerId: question.answers.somethingElseDetails.answerId, - otherDetails: otherSource + otherDetails: somethingElseDetails }) } return answers } -const getContext = () => { +const getContext = request => { + const answers = request.yar.get(question.key) return { - question + question, + answers } } diff --git a/server/routes/water-pollution/when.js b/server/routes/water-pollution/when.js index 2503985d..59ba0691 100644 --- a/server/routes/water-pollution/when.js +++ b/server/routes/water-pollution/when.js @@ -5,16 +5,18 @@ import { fieldErrorClasses, getDateErrors, getTimeErrors, - validatePayload + validatePayload, + getDateContext } from '../../utils/date-helpers.js' const handlers = { - get: async (_request, h) => { + get: async (request, h) => { return h.view(constants.views.WATER_POLLUTION_WHEN, { fieldErrorClasses, getDateErrors, getTimeErrors, - validateAndError: dateValidateAndError() + validateAndError: dateValidateAndError(), + ...getDateContext(request.yar.get(constants.redisKeys.WATER_POLLUTION_WHEN)) }) }, post: async (request, h) => { @@ -71,7 +73,7 @@ const handlers = { request.yar.set(constants.redisKeys.WATER_POLLUTION_WHEN, dateTime.toISOString()) - return h.redirect(constants.routes.WATER_POLLUTION_POLLUTION_SUBSTANCE) + return h.redirect(request.yar.get(constants.redisKeys.REFERER) || constants.routes.WATER_POLLUTION_POLLUTION_SUBSTANCE) } } diff --git a/server/routes/water-pollution/your-details.js b/server/routes/water-pollution/your-details.js new file mode 100644 index 00000000..fa68fde8 --- /dev/null +++ b/server/routes/water-pollution/your-details.js @@ -0,0 +1,91 @@ +import constants from '../../utils/constants.js' +import { getErrorSummary, validateEmail } from '../../utils/helpers.js' + +const handlers = { + get: async (request, h) => { + return h.view(constants.views.WATER_POLLUTION_YOUR_DETAILS, { + ...getContext(request) + }) + }, + post: async (request, h) => { + const { fullName, phone, email } = request.payload + const errorSummary = validatePayload(fullName, phone, email) + + // Validation error so return view in Error state + if (errorSummary.errorList.length > 0) { + return h.view(constants.views.WATER_POLLUTION_YOUR_DETAILS, { + errorSummary, + ...request.payload + }) + } + + const { reporterAccessCode } = request.yar.get(constants.redisKeys.HOME) + + request.yar.set(constants.redisKeys.HOME, { + reporterName: fullName, + reporterPhoneNumber: phone, + reporterEmailAddress: email, + reporterAccessCode + }) + + // handle redirects + return h.redirect(constants.routes.WATER_POLLUTION_CHECK_YOUR_ANSWERS) + } +} + +const getContext = request => { + const { + reporterName: fullName, + reporterPhoneNumber: phone, + reporterEmailAddress: email + } = request.yar.get(constants.redisKeys.HOME) + + return { + fullName, + phone, + email + } +} + +const validatePayload = (fullName, phone, email) => { + const errorSummary = getErrorSummary() + if (!fullName) { + errorSummary.errorList.push({ + text: 'Enter your name', + href: '#fullName' + }) + } + if (!phone) { + errorSummary.errorList.push({ + text: 'Enter a phone number', + href: '#phone' + }) + } else if (!constants.phoneRegex.test(phone)) { + errorSummary.errorList.push({ + text: 'Enter a phone number, like 01632 960 001, 07700 900 982 or +44 808 157 0192', + href: '#phone' + }) + } else { + // do nothing; sonarcloud has lost the plot. + } + if (!validateEmail(email)) { + errorSummary.errorList.push({ + text: 'Enter an email address in the correct format, like name@example.com', + href: '#email' + }) + } + return errorSummary +} + +export default [ + { + method: 'GET', + path: constants.routes.WATER_POLLUTION_YOUR_DETAILS, + handler: handlers.get + }, + { + method: 'POST', + path: constants.routes.WATER_POLLUTION_YOUR_DETAILS, + handler: handlers.post + } +] diff --git a/server/utils/constants.js b/server/utils/constants.js index 9d71d52e..d5527525 100644 --- a/server/utils/constants.js +++ b/server/utils/constants.js @@ -40,6 +40,8 @@ const WATER_POLLUTION_POLLUTION_AREA = 'water-pollution/pollution-area' const WATER_POLLUTION_POLLUTION_LENGTH = 'water-pollution/pollution-length' const WATER_POLLUTION_EFFECT_ON_WILDLIFE = 'water-pollution/effect-on-wildlife' const WATER_POLLUTION_OTHER_INFORMATION = 'water-pollution/other-information' +const WATER_POLLUTION_CHECK_YOUR_ANSWERS = 'water-pollution/check-your-answers' +const WATER_POLLUTION_YOUR_DETAILS = 'water-pollution/your-details' const SMELL = 'smell' const SMELL_LOCATION_HOME = 'smell/location-home' @@ -66,6 +68,7 @@ const SMELL_OTHER_INFORMATION = 'smell/other-information' // Meta data const SUBMISSION_TIMESTAMP = 'submission-timestamp' +const REFERER = 'referer' const QUESTION_SET_ID = 'question-set-id' const views = { @@ -98,6 +101,8 @@ const views = { WATER_POLLUTION_POLLUTION_LENGTH, WATER_POLLUTION_EFFECT_ON_WILDLIFE, WATER_POLLUTION_OTHER_INFORMATION, + WATER_POLLUTION_CHECK_YOUR_ANSWERS, + WATER_POLLUTION_YOUR_DETAILS, SMELL, SMELL_LOCATION_HOME, SMELL_LOCATION_ADDRESS, @@ -133,6 +138,7 @@ for (const [key, value] of Object.entries(views)) { const redisKeys = { ...views, SUBMISSION_TIMESTAMP, + REFERER, QUESTION_SET_ID } @@ -162,6 +168,16 @@ const waterFeatureLabels = { 507: 'watercourse' } +// Pages that set a referrer to return to after next page completion +const setReferer = [ + WATER_POLLUTION_CHECK_YOUR_ANSWERS +] + +// Pages that clear a referrer to break the above chain +const clearReferer = [ + +] + export default Object.freeze({ routes, views, @@ -170,5 +186,7 @@ export default Object.freeze({ redisKeys, errorSummary, phoneRegex, - waterFeatureLabels + waterFeatureLabels, + setReferer, + clearReferer }) diff --git a/server/utils/date-helpers.js b/server/utils/date-helpers.js index 4921853c..5b87b425 100644 --- a/server/utils/date-helpers.js +++ b/server/utils/date-helpers.js @@ -216,10 +216,47 @@ const returnError = (errorSummary, validateAndError, text, href, invalidDate, in } } +const getDateContext = answer => { + let context = {} + if (answer) { + const today = new Date() + const yesterday = new Date() + yesterday.setDate(yesterday.getDate() - 1) + + const date = new Date(answer) + + const isToday = date.getDate() === today.getDate() && + date.getMonth() === today.getMonth() && + date.getFullYear() === today.getFullYear() + + const isYesterday = date.getDate() === yesterday.getDate() && + date.getMonth() === yesterday.getMonth() && + date.getFullYear() === yesterday.getFullYear() + + const twelve = 12 + const thirteen = 13 + + context = { + isToday, + isYesterday, + isEarlier: !(isToday || isYesterday), + day: date.getDate(), + month: date.getMonth() + 1, + year: date.getFullYear(), + hour: date.getHours() < thirteen ? date.getHours() : date.getHours() - twelve, + minute: date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes(), + period: date.getHours() < twelve ? 'am' : 'pm', + isPageReturn: true + } + } + return context +} + export { dateValidateAndError, fieldErrorClasses, getDateErrors, getTimeErrors, - validatePayload + validatePayload, + getDateContext } diff --git a/server/utils/question-sets.js b/server/utils/question-sets.js index bd15f230..2a1b6c90 100644 --- a/server/utils/question-sets.js +++ b/server/utils/question-sets.js @@ -4,6 +4,7 @@ import constants from './constants.js' const YOU_DO_NOT_KNOW = 'You do not know' const SOMETHING_ELSE = 'Something else' const NONE_OF_THESE = 'None of these' +const YOU_DO_NOT_KNOW_SHORT = 'Don\'t know' const questionSets = { WATER_POLLUTION: { @@ -16,31 +17,38 @@ const questionSets = { answers: { river: { answerId: 501, - text: 'A river' + text: 'A river', + shortText: 'River' }, lakeOrReservoir: { answerId: 502, - text: 'A lake or reservoir' + text: 'A lake or reservoir', + shortText: 'Lake or reservoir' }, sea: { answerId: 503, - text: 'The sea' + text: 'The sea', + shortText: 'Sea' }, canal: { answerId: 504, - text: 'A canal' + text: 'A canal', + shortText: 'Canal' }, smallWatercourse: { answerId: 505, - text: 'A smaller stream or watercourse' + text: 'A smaller stream or watercourse', + shortText: 'Smaller stream or watercourse' }, somethingElse: { answerId: 506, - text: SOMETHING_ELSE + text: SOMETHING_ELSE, + shortText: SOMETHING_ELSE }, youDoNotKnow: { answerId: 507, - text: YOU_DO_NOT_KNOW + text: YOU_DO_NOT_KNOW, + shortText: YOU_DO_NOT_KNOW_SHORT }, somethingElseDetails: { answerId: 508 @@ -54,15 +62,18 @@ const questionSets = { answers: { yes: { answerId: 701, - text: 'Yes' + text: 'Yes', + shortText: 'Yes' }, no: { answerId: 702, - text: 'No, it is over a longer stretch' + text: 'No, it is over a longer stretch', + shortText: 'No' }, youDoNotKnow: { answerId: 703, - text: YOU_DO_NOT_KNOW + text: YOU_DO_NOT_KNOW, + shortText: YOU_DO_NOT_KNOW_SHORT } } }, @@ -73,15 +84,18 @@ const questionSets = { answers: { yes: { answerId: 801, - text: 'Yes' + text: 'Yes', + shortText: 'Yes' }, no: { answerId: 802, - text: 'No, it spreads over a larger area' + text: 'No, it spreads over a larger area', + shortText: 'No' }, youDoNotKnow: { answerId: 803, - text: YOU_DO_NOT_KNOW + text: YOU_DO_NOT_KNOW, + shortText: YOU_DO_NOT_KNOW_SHORT } } }, @@ -92,23 +106,28 @@ const questionSets = { answers: { stretches10to100m: { answerId: 401, - text: '10 to 100 metres (less than 2 minutes average walk)' + text: '10 to 100 metres (less than 2 minutes average walk)', + shortText: '10 to 100 metres' }, stretches100to500m: { answerId: 402, - text: '100 to 500 metres (around 2 to 8 minutes walk)' + text: '100 to 500 metres (around 2 to 8 minutes walk)', + shortText: '100 to 500 metres' }, stretches500to1000m: { answerId: 403, - text: '500 metres to a kilometre (around 8 to 16 minutes walk)' + text: '500 metres to a kilometre (around 8 to 16 minutes walk)', + shortText: '500 metres to a kilometre' }, over1km: { answerId: 404, - text: 'Over a kilometre' + text: 'Over a kilometre', + shortText: 'Over a kilometre' }, youDoNotKnow: { answerId: 405, - text: YOU_DO_NOT_KNOW + text: YOU_DO_NOT_KNOW, + shortText: YOU_DO_NOT_KNOW_SHORT } } }, @@ -119,15 +138,18 @@ const questionSets = { answers: { under500sqm: { answerId: 301, - text: '100 to 500 square metres (sq m)' + text: '100 to 500 square metres (sq m)', + shortText: '100 to 500 square metres' }, over500sqm: { answerId: 302, - text: 'More than 500 sq m' + text: 'More than 500 sq m', + shortText: 'More than 500 square metres' }, youDoNotKnow: { answerId: 303, - text: YOU_DO_NOT_KNOW + text: YOU_DO_NOT_KNOW, + shortText: YOU_DO_NOT_KNOW_SHORT } } }, @@ -138,19 +160,23 @@ const questionSets = { answers: { cloudy: { answerId: 1002, - text: 'Cloudy or grey water' + text: 'Cloudy or grey water', + shortText: 'Cloudy or grey water' }, rainbow: { answerId: 1001, - text: 'A \'rainbow\' film on top of the water' + text: 'A \'rainbow\' film on top of the water', + shortText: 'A rainbow film' }, scum: { answerId: 1003, - text: 'A foam or scum' + text: 'A foam or scum', + shortText: 'Foam or scum' }, somethingElse: { answerId: 1004, - text: SOMETHING_ELSE + text: SOMETHING_ELSE, + shortText: SOMETHING_ELSE }, somethingElseDetail: { answerId: 1005, @@ -165,11 +191,13 @@ const questionSets = { answers: { yes: { answerId: 101, - text: 'Yes' + text: 'Yes', + shortText: 'Yes' }, no: { answerId: 102, - text: 'No' + text: 'No', + shortText: 'No' }, yesDetails: { answerId: 103, @@ -184,11 +212,13 @@ const questionSets = { answers: { yes: { answerId: 2801, - text: 'Yes' + text: 'Yes', + shortText: 'Yes' }, no: { answerId: 2802, - text: 'No' + text: 'No', + shortText: 'No' } } }, @@ -246,11 +276,13 @@ const questionSets = { answers: { yes: { answerId: 201, - text: 'Yes' + text: 'Yes', + shortText: 'Yes' }, no: { answerId: 202, - text: 'No' + text: 'No', + shortText: 'No' }, yesDetails: { answerId: 203, @@ -265,27 +297,33 @@ const questionSets = { answers: { sewage: { answerId: 2901, - text: 'Sewage' + text: 'Sewage', + shortText: 'Sewage' }, chemical: { answerId: 2902, - text: 'Oil or petrol' + text: 'Oil or petrol', + shortText: 'Oil or petrol' }, rural: { answerId: 2903, - text: 'Agricultural waste, for example from muck spreading' + text: 'Agricultural waste, for example from muck spreading', + shortText: 'Agricultural waste' }, refuse: { answerId: 2904, - text: 'Rubbish or refuse' + text: 'Rubbish or refuse', + shortText: 'Rubbish or refuse' }, somethingElse: { answerId: 2905, - text: SOMETHING_ELSE + text: SOMETHING_ELSE, + shortText: SOMETHING_ELSE }, unknown: { answerId: 2906, - text: YOU_DO_NOT_KNOW + text: YOU_DO_NOT_KNOW, + shortText: YOU_DO_NOT_KNOW_SHORT }, somethingElseDetail: { answerId: 2907, diff --git a/server/utils/template-helpers.js b/server/utils/template-helpers.js index 609d5e14..109ce3e2 100644 --- a/server/utils/template-helpers.js +++ b/server/utils/template-helpers.js @@ -1,9 +1,19 @@ // This is a location for storing helpers that are used by front end nunjucks templates const findErrorMessageById = (errorSummary, id) => { - return errorSummary?.errorList?.find((error) => error.href === `#${id}`) + return errorSummary?.errorList?.find(error => error.href === `#${id}`) +} + +const getAnswer = (answers, answerId) => { + const answer = answers?.find(item => item.answerId === answerId) + if (answer?.otherDetails) { + return answer.otherDetails + } else { + return answer ? true : '' + } } export { - findErrorMessageById + findErrorMessageById, + getAnswer } diff --git a/server/views/layout.html b/server/views/layout.html index 399761d4..81167323 100644 --- a/server/views/layout.html +++ b/server/views/layout.html @@ -12,6 +12,7 @@ {% from "dist/govuk/components/checkboxes/macro.njk" import govukCheckboxes %} {% from "dist/govuk/components/notification-banner/macro.njk" import govukNotificationBanner %} {% from "dist/govuk/components/fieldset/macro.njk" import govukFieldset %} +{% from "dist/govuk/components/summary-list/macro.njk" import govukSummaryList %} {% block head %} diff --git a/server/views/partials/date-time-old.html b/server/views/partials/date-time-old.html deleted file mode 100644 index 749af720..00000000 --- a/server/views/partials/date-time-old.html +++ /dev/null @@ -1,92 +0,0 @@ -
-
-

- {{ pageTitle }}? -

- {{ govukDateInput({ - id: "date", - namePrefix: "date", - errorMessage: getDateErrors(errorSummary, validateAndError)[0], - fieldset: { - legend: { - text: "Date", - isPageHeading: false, - classes: "govuk-label govuk-label--m" - } - }, - items: [ - { - classes: fieldErrorClasses(validateAndError.day, 'govuk-input--width-2'), - name: "day", - value: validateAndError.day.value - }, - { - classes: fieldErrorClasses(validateAndError.month, 'govuk-input--width-2'), - name: "month", - value: validateAndError.month.value - }, - { - classes: fieldErrorClasses(validateAndError.year, 'govuk-input--width-4'), - name: "year", - value: validateAndError.year.value - } - ], - hint: { - text: "For example, 27 1 2024." - } - }) }} -
-
- - Time (approximately) - -
- For example, 9:30am or 2:55pm. -
- {% if getTimeErrors(errorSummary, validateAndError) %} -

- Error: {{ getTimeErrors(errorSummary, validateAndError)[0].text }} -

- {% endif %} -
-
-
- - -
-
-
- -
-
-
- - -
-
-
-
- - -
-
-
-
-
- - {{ govukButton({ - text: "Continue" - }) }} - -
-
diff --git a/server/views/partials/date-time.html b/server/views/partials/date-time.html index 44cf0156..6ac10697 100644 --- a/server/views/partials/date-time.html +++ b/server/views/partials/date-time.html @@ -23,7 +23,7 @@

- +
@@ -34,7 +34,7 @@

- +

@@ -44,8 +44,8 @@

@@ -74,7 +74,7 @@

- +
@@ -85,7 +85,7 @@

- +

@@ -95,8 +95,8 @@

@@ -120,17 +120,17 @@

{ classes: fieldErrorClasses(validateAndError.day, 'govuk-input--width-2'), name: "day", - value: validateAndError.day.value + value: day if isEarlier else validateAndError.day.value }, { classes: fieldErrorClasses(validateAndError.month, 'govuk-input--width-2'), name: "month", - value: validateAndError.month.value + value: month if isEarlier else validateAndError.month.value }, { classes: fieldErrorClasses(validateAndError.year, 'govuk-input--width-4'), name: "year", - value: validateAndError.year.value + value: year if isEarlier else validateAndError.year.value } ] }) }} @@ -153,7 +153,7 @@

- +
@@ -164,7 +164,7 @@

- +

@@ -174,8 +174,8 @@

@@ -193,7 +193,7 @@

{ value: 0, text: "Today", - checked: current === '0', + checked: (current === '0' or isToday), conditional: { html: todayHtml } @@ -201,7 +201,7 @@

{ value: 1, text: "Yesterday", - checked: current === '1', + checked: (current === '1' or isYesterday), conditional: { html: yesterdayHtml } @@ -209,7 +209,7 @@

{ value: 2, text: "Before then", - checked: current === '2', + checked: (current === '2' or isEarlier), conditional: { html: dateHtml } diff --git a/server/views/partials/location-map.html b/server/views/partials/location-map.html index e1810f41..d96d8f50 100644 --- a/server/views/partials/location-map.html +++ b/server/views/partials/location-map.html @@ -82,5 +82,8 @@

{{ super() }} - + {% endblock %} diff --git a/server/views/shared/images-or-video.html b/server/views/shared/images-or-video.html index 8984e52d..86817eed 100644 --- a/server/views/shared/images-or-video.html +++ b/server/views/shared/images-or-video.html @@ -24,13 +24,15 @@

{ value: question.answers.yes.answerId, text: question.answers.yes.text, + checked: getAnswer(answers, question.answers.yes.answerId), conditional: { html: contactHtml } }, { value: question.answers.no.answerId, - text: question.answers.no.text + text: question.answers.no.text, + checked: getAnswer(answers, question.answers.no.answerId) } ] }) }} diff --git a/server/views/water-pollution/check-your-answers.html b/server/views/water-pollution/check-your-answers.html new file mode 100644 index 00000000..b3ee7d43 --- /dev/null +++ b/server/views/water-pollution/check-your-answers.html @@ -0,0 +1,362 @@ +{% extends 'form-layout.html' %} + +{% set pageTitle = 'Check your answers before sending your report' %} + +{% block formContent %} + +
+
+ +

Check your answers before sending your report

+

Your details

+ + {{ govukSummaryList({ + classes: "govuk-!-margin-bottom-9", + rows: [ + { + key: { + text: "Name" + }, + value: { + text: reporterName + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_YOUR_DETAILS, + text: "Change", + visuallyHiddenText: "name" + } + ] + } + }, + { + key: { + text: "Phone number" + }, + value: { + text: reporterPhoneNumber + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_YOUR_DETAILS, + text: "Change", + visuallyHiddenText: "phone number" + } + ] + } + }, + { + key: { + text: "Email address" + }, + value: { + text: reporterEmailAddress + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_YOUR_DETAILS, + text: "Change", + visuallyHiddenText: "email address" + } + ] + } + }, + { + key: { + text: "Images or videos available" + }, + value: { + text: imagesOrVideoAnswer + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_IMAGES_OR_VIDEO, + text: "Change", + visuallyHiddenText: "images or videos available" + } + ] + } + } + ] + }) }} + +

Location and size of pollution

+ {% if locationAnswer.point %} + {% set locationListItem = { + key: { + classes: "vertical-align-top", + text: "Location" + }, + classes: '', + value: { + html: "
" + }, + actions: { + classes: "vertical-align-top", + items: [ + { + href: url.WATER_POLLUTION_LOCATION_OPTION, + text: "Change", + visuallyHiddenText: "location" + } + ] + } + }%} + {% else %} + {% set locationListItem = { + key: { + text: "Location" + }, + value: { + text: locationAnswer + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_LOCATION_OPTION, + text: "Change", + visuallyHiddenText: "location" + } + ] + } + }%} + {% endif %} + + {% if isMeasuredInArea %} + {% set lessThanListItem = { + key: { + text: "Less than 100 square metres in size" + }, + value: { + text: lessThanSizeAnswer + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_LESS_THAN_100_SQ_METRES, + text: "Change", + visuallyHiddenText: "less than 100 square metres in size" + } + ] + } + }%} + {% else %} + {% set lessThanListItem = { + key: { + text: "Less than 10m in size" + }, + value: { + text: lessThanSizeAnswer + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_LESS_THAN_10_METRES, + text: "Change", + visuallyHiddenText: "less than 10m in size" + } + ] + } + }%} + {% endif %} + + {% if isSizeEstimatedRequired %} + {% if isMeasuredInArea %} + {% set sizeEsitmatedListItem = { + + key: { + text: "Size (estimated)" + }, + value: { + text: sizeEstimatedAnswer + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_POLLUTION_AREA, + text: "Change", + visuallyHiddenText: "size estimated" + } + ] + } + }%} + {% else %} + {% set sizeEsitmatedListItem = { + key: { + text: "Size (estimated)" + }, + value: { + text: sizeEstimatedAnswer + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_POLLUTION_LENGTH, + text: "Change", + visuallyHiddenText: "size estimated" + } + ] + } + }%} + {% endif %} + {% endif %} + + {{ govukSummaryList({ + classes: "govuk-!-margin-bottom-9", + rows: [ + { + key: { + text: "Type of water" + }, + value: { + text: waterFeatureAnswer + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_WATER_FEATURE, + text: "Change", + visuallyHiddenText: "type of water" + } + ] + } + }, + locationListItem, + lessThanListItem, + sizeEsitmatedListItem + ] + }) }} + +

About the pollution

+ + {{ govukSummaryList({ + classes: "govuk-!-margin-bottom-9", + rows: [ + { + key: { + text: "When did you see the pollution?" + }, + value: { + text: whenAnswer + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_WHEN, + text: "Change", + visuallyHiddenText: "when did you see the pollution?" + } + ] + } + }, + { + key: { + text: "What do you think the pollution is?" + }, + value: { + html: pollutionSubstanceAnswer + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_POLLUTION_SUBSTANCE, + text: "Change", + visuallyHiddenText: "what do you think the pollution is?" + } + ] + } + }, + { + key: { + text: "What does the pollution look like?" + }, + value: { + html: pollutionAppearanceAnswer + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_POLLUTION_APPEARANCE, + text: "Change", + visuallyHiddenText: "what does the pollution look like?" + } + ] + } + }, + { + key: { + text: "Do you know where the pollution is coming from?" + }, + value: { + text: pollutionSourceAnswer + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_SOURCE, + text: "Change", + visuallyHiddenText: "do you know where the pollution is coming from?" + } + ] + } + }, + { + key: { + text: "Have you seen any dead fish or animals?" + }, + value: { + text: effectOnWildlifeAnswer + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_EFFECT_ON_WILDLIFE, + text: "Change", + visuallyHiddenText: "Have you seen any dead fish or animals?" + } + ] + } + }, + { + key: { + text: "Is there anything else you'd like to add?" + }, + value: { + text: otherInformationAnswer + }, + actions: { + items: [ + { + href: url.WATER_POLLUTION_OTHER_INFORMATION, + text: "Change", + visuallyHiddenText: "Is there anything else you'd like to add?" + } + ] + } + } + ] + }) }} + + {{ govukButton({ + text: "Finish and send report" + }) }} + +
+
+ +{% endblock %} + +{% block bodyEnd %} + {{ super() }} + {% if locationAnswer.point %} + + + {% endif %} +{% endblock %} \ No newline at end of file diff --git a/server/views/water-pollution/effect-on-wildlife.html b/server/views/water-pollution/effect-on-wildlife.html index 82aeaf74..f223a25e 100644 --- a/server/views/water-pollution/effect-on-wildlife.html +++ b/server/views/water-pollution/effect-on-wildlife.html @@ -12,6 +12,7 @@ name: "yesDetails", errorMessage: findErrorMessageById(errorSummary, "yesDetails"), classes: "govuk-!-width-two-third", + value: getAnswer(answers, question.answers.yesDetails.answerId), label: { text: question.answers.yesDetails.text } @@ -19,9 +20,9 @@ {% endset -%} {{ govukRadios ({ - id: "effectOnWildlife", - name: "effectOnWildlife", - errorMessage: findErrorMessageById(errorSummary, "effectOnWildlife"), + id: "answerId", + name: "answerId", + errorMessage: findErrorMessageById(errorSummary, "answerId"), fieldset: { legend: { text: question.text, @@ -31,17 +32,17 @@ }, items: [ { - value: "yes", - text: "Yes", + value: question.answers.yes.answerId, + text: question.answers.yes.text, + checked: getAnswer(answers, question.answers.yes.answerId), conditional: { html: sourceDetailsHtml - }, - checked: effectOnWildlife === 'yes' + } }, { - value: "no", - text: "No", - checked: effectOnWildlife === 'no' + value: question.answers.no.answerId, + text: question.answers.no.text, + checked: getAnswer(answers, question.answers.no.answerId) } ] }) }} diff --git a/server/views/water-pollution/location-description.html b/server/views/water-pollution/location-description.html index 05815a8d..0d567e09 100644 --- a/server/views/water-pollution/location-description.html +++ b/server/views/water-pollution/location-description.html @@ -19,7 +19,8 @@ hint: { html: "Include things like the name of the watercourse and nearest town or landmarks. You can also include things like what3words (opens new tab) or map references." }, - errorMessage: findErrorMessageById(errorSummary, 'locationDescription') + errorMessage: findErrorMessageById(errorSummary, 'locationDescription'), + value: getAnswer(answers, question.answers.locationDetails.answerId) }) }} {{ govukButton({ diff --git a/server/views/water-pollution/location-option.html b/server/views/water-pollution/location-option.html index 10ca0b49..3ea3aa83 100644 --- a/server/views/water-pollution/location-option.html +++ b/server/views/water-pollution/location-option.html @@ -16,11 +16,13 @@

items: [ { value: question.answers.map.answerId, - text: question.answers.map.text + text: question.answers.map.text, + checked: getAnswer(answers, question.answers.map.answerId) }, { value: question.answers.description.answerId, - text: question.answers.description.text + text: question.answers.description.text, + checked: getAnswer(answers, question.answers.description.answerId) } ] }) }} diff --git a/server/views/water-pollution/other-information.html b/server/views/water-pollution/other-information.html index 3114e3f1..18ad71f7 100644 --- a/server/views/water-pollution/other-information.html +++ b/server/views/water-pollution/other-information.html @@ -1 +1,33 @@ -{% include "shared/other-information.html" %} +{% extends 'form-layout.html' %} + +{% set pageTitle = 'Is there anything else you\'d like to add' %} + +{% block formContent %} + +
+
+ + {{ govukTextarea({ + name: "otherInfo", + id: "otherInfo", + rows: "10", + value: answers, + label: { + text: pageTitle + " (optional)?", + classes: "govuk-label--l", + isPageHeading: true + }, + hint: { + text: "For example, what you think the substance is, or where it is coming from." + }, + errorMessage: findErrorMessageById(errorSummary, 'otherInfo') + }) }} + + {{ govukButton({ + text: "Continue" + }) }} + +
+
+ +{% endblock %} diff --git a/server/views/water-pollution/partials/less-than-x-x.html b/server/views/water-pollution/partials/less-than-x-x.html index e0f6691e..37c19ae2 100644 --- a/server/views/water-pollution/partials/less-than-x-x.html +++ b/server/views/water-pollution/partials/less-than-x-x.html @@ -15,18 +15,21 @@

items: [ { value: question.answers.yes.answerId, - text: question.answers.yes.text + text: question.answers.yes.text, + checked: getAnswer(answers, question.answers.yes.answerId) }, { value: question.answers.no.answerId, - text: question.answers.no.text + text: question.answers.no.text, + checked: getAnswer(answers, question.answers.no.answerId) }, { divider: "or" }, { value: question.answers.youDoNotKnow.answerId, - text: question.answers.youDoNotKnow.text + text: question.answers.youDoNotKnow.text, + checked: getAnswer(answers, question.answers.youDoNotKnow.answerId) } ] }) }} diff --git a/server/views/water-pollution/pollution-appearance.html b/server/views/water-pollution/pollution-appearance.html index b9cd48d3..8ec5654f 100644 --- a/server/views/water-pollution/pollution-appearance.html +++ b/server/views/water-pollution/pollution-appearance.html @@ -12,6 +12,7 @@ name: "somethingElseDetail", spellcheck: false, classes: "govuk-!-width-two-third", + value: getAnswer(answers, question.answers.somethingElseDetail.answerId), label: { text: question.answers.somethingElseDetail.text } @@ -35,19 +36,23 @@ items: [ { value: question.answers.cloudy.answerId, - text: question.answers.cloudy.text + text: question.answers.cloudy.text, + checked: getAnswer(answers, question.answers.cloudy.answerId) }, { value: question.answers.rainbow.answerId, - text: question.answers.rainbow.text + text: question.answers.rainbow.text, + checked: getAnswer(answers, question.answers.rainbow.answerId) }, { value: question.answers.scum.answerId, - text: question.answers.scum.text + text: question.answers.scum.text, + checked: getAnswer(answers, question.answers.scum.answerId) }, { value: question.answers.somethingElse.answerId, text: question.answers.somethingElse.text, + checked: getAnswer(answers, question.answers.somethingElse.answerId), conditional: { html: otherHtml } diff --git a/server/views/water-pollution/pollution-area.html b/server/views/water-pollution/pollution-area.html index 4283f83e..8540ecb5 100644 --- a/server/views/water-pollution/pollution-area.html +++ b/server/views/water-pollution/pollution-area.html @@ -23,18 +23,21 @@ items: [ { value: question.answers.under500sqm.answerId, - text: question.answers.under500sqm.text + text: question.answers.under500sqm.text, + checked: getAnswer(answers, question.answers.under500sqm.answerId) }, { value: question.answers.over500sqm.answerId, - text: question.answers.over500sqm.text + text: question.answers.over500sqm.text, + checked: getAnswer(answers, question.answers.over500sqm.answerId) }, { divider: "or" }, { value: question.answers.youDoNotKnow.answerId, - text: question.answers.youDoNotKnow.text + text: question.answers.youDoNotKnow.text, + checked: getAnswer(answers, question.answers.youDoNotKnow.answerId) } ] }) }} diff --git a/server/views/water-pollution/pollution-length.html b/server/views/water-pollution/pollution-length.html index 41c24aa2..55935214 100644 --- a/server/views/water-pollution/pollution-length.html +++ b/server/views/water-pollution/pollution-length.html @@ -23,26 +23,31 @@ items: [ { value: question.answers.stretches10to100m.answerId, - text: question.answers.stretches10to100m.text + text: question.answers.stretches10to100m.text, + checked: getAnswer(answers, question.answers.stretches10to100m.answerId) }, { value: question.answers.stretches100to500m.answerId, - text: question.answers.stretches100to500m.text + text: question.answers.stretches100to500m.text, + checked: getAnswer(answers, question.answers.stretches100to500m.answerId) }, { value: question.answers.stretches500to1000m.answerId, - text: question.answers.stretches500to1000m.text + text: question.answers.stretches500to1000m.text, + checked: getAnswer(answers, question.answers.stretches500to1000m.answerId) }, { value: question.answers.over1km.answerId, - text: question.answers.over1km.text + text: question.answers.over1km.text, + checked: getAnswer(answers, question.answers.over1km.answerId) }, { divider: "or" }, { value: question.answers.youDoNotKnow.answerId, - text: question.answers.youDoNotKnow.text + text: question.answers.youDoNotKnow.text, + checked: getAnswer(answers, question.answers.youDoNotKnow.answerId) } ] }) }} diff --git a/server/views/water-pollution/pollution-substance.html b/server/views/water-pollution/pollution-substance.html index e5910d68..eb67443f 100644 --- a/server/views/water-pollution/pollution-substance.html +++ b/server/views/water-pollution/pollution-substance.html @@ -13,6 +13,7 @@ name: "somethingElseDetail", spellcheck: false, classes: "govuk-!-width-two-third", + value: getAnswer(answers, question.answers.somethingElseDetail.answerId), label: { text: questions.answers.somethingElseDetail.text } @@ -33,23 +34,28 @@ items: [ { value: question.answers.sewage.answerId, - text: question.answers.sewage.text + text: question.answers.sewage.text, + checked: getAnswer(answers, question.answers.sewage.answerId) }, { value: question.answers.chemical.answerId, - text: question.answers.chemical.text + text: question.answers.chemical.text, + checked: getAnswer(answers, question.answers.chemical.answerId) }, { value: question.answers.rural.answerId, - text: question.answers.rural.text + text: question.answers.rural.text, + checked: getAnswer(answers, question.answers.rural.answerId) }, { value: question.answers.refuse.answerId, - text: question.answers.refuse.text + text: question.answers.refuse.text, + checked: getAnswer(answers, question.answers.refuse.answerId) }, { value: question.answers.somethingElse.answerId, text: question.answers.somethingElse.text, + checked: getAnswer(answers, question.answers.somethingElse.answerId), conditional: { html: otherHtml } @@ -59,7 +65,9 @@ }, { value: question.answers.unknown.answerId, - text: question.answers.unknown.text + text: question.answers.unknown.text, + behaviour: "exclusive", + checked: getAnswer(answers, question.answers.unknown.answerId) } ] }) }} diff --git a/server/views/water-pollution/source.html b/server/views/water-pollution/source.html index e2735dff..9bfe7a88 100644 --- a/server/views/water-pollution/source.html +++ b/server/views/water-pollution/source.html @@ -10,6 +10,7 @@ id: "yesDetails", name: "yesDetails", classes: "govuk-!-width-two-third", + value: getAnswer(answers, question.answers.yesDetails.answerId), errorMessage: findErrorMessageById(errorSummary, "yesDetails"), label: { text: question.answers.yesDetails.text @@ -36,14 +37,15 @@ { value: question.answers.yes.answerId, text: question.answers.yes.text, - checked: yesChecked, + checked: getAnswer(answers, question.answers.yes.answerId), conditional: { html: yesDetailsHtml } }, { value: question.answers.no.answerId, - text: question.answers.no.text + text: question.answers.no.text, + checked: getAnswer(answers, question.answers.no.answerId) } ] }) }} diff --git a/server/views/water-pollution/water-feature.html b/server/views/water-pollution/water-feature.html index 6d1f71c2..e91ce8ad 100644 --- a/server/views/water-pollution/water-feature.html +++ b/server/views/water-pollution/water-feature.html @@ -9,10 +9,11 @@ {% set otherHtml %} {{ govukInput({ - id: "otherSource", - name: "otherSource", + id: "somethingElseDetails", + name: "somethingElseDetails", spellcheck: false, classes: "govuk-!-width-two-thirds", + value: getAnswer(answers, question.answers.somethingElseDetails.answerId), label: { text: "Give details" } @@ -33,27 +34,33 @@ items: [ { value: question.answers.river.answerId, - text: question.answers.river.text + text: question.answers.river.text, + checked: getAnswer(answers, question.answers.river.answerId) }, { value: question.answers.lakeOrReservoir.answerId, - text: question.answers.lakeOrReservoir.text + text: question.answers.lakeOrReservoir.text, + checked: getAnswer(answers, question.answers.lakeOrReservoir.answerId) }, { value: question.answers.sea.answerId, - text: question.answers.sea.text + text: question.answers.sea.text, + checked: getAnswer(answers, question.answers.sea.answerId) }, { value: question.answers.canal.answerId, - text: question.answers.canal.text + text: question.answers.canal.text, + checked: getAnswer(answers, question.answers.canal.answerId) }, { value: question.answers.smallWatercourse.answerId, - text: question.answers.smallWatercourse.text + text: question.answers.smallWatercourse.text, + checked: getAnswer(answers, question.answers.smallWatercourse.answerId) }, { value: question.answers.somethingElse.answerId, text: question.answers.somethingElse.text, + checked: getAnswer(answers, question.answers.somethingElse.answerId), conditional: { html: otherHtml } @@ -63,7 +70,8 @@ }, { value: question.answers.youDoNotKnow.answerId, - text: question.answers.youDoNotKnow.text + text: question.answers.youDoNotKnow.text, + checked: getAnswer(answers, question.answers.youDoNotKnow.answerId) } ] }) }} diff --git a/server/views/water-pollution/your-details.html b/server/views/water-pollution/your-details.html new file mode 100644 index 00000000..53367cdc --- /dev/null +++ b/server/views/water-pollution/your-details.html @@ -0,0 +1,55 @@ +{% extends 'form-layout.html' %} +{% set pageTitle = 'Your details' %} + +{% block formContent %} + +
+
+

+ {{ pageTitle }} +

+ {{ govukInput({ + id: "fullName", + name: "fullName", + value: fullName, + autocomplete: "name", + classes: "govuk-!-width-two-thirds", + spellcheck: false, + label: { + text: "Your name" + }, + errorMessage: findErrorMessageById(errorSummary, 'fullName') + }) }} + {{ govukInput({ + id: "phone", + name: "phone", + value: phone, + type: "tel", + autocomplete: "tel", + classes: "govuk-!-width-one-third", + label: { + text: "Phone number" + }, + errorMessage: findErrorMessageById(errorSummary, 'phone') + }) }} + {{ govukInput({ + id: "email", + name: "email", + value: email, + type: "email", + autocomplete: "email", + spellcheck: false, + classes: "govuk-!-width-two-thirds", + label: { + text: "Email address" + }, + errorMessage: findErrorMessageById(errorSummary, 'email') + }) }} + + {{ govukButton({ + text: "Continue" + }) }} +
+ +
+{% endblock %} diff --git a/webpack.config.js b/webpack.config.js index d03c1ad9..018da7bd 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -9,6 +9,7 @@ const inDev = env === 'development' export default { entry: { + checkYourAnswers: './client/js/pages/check-your-answers.js', core: './client/js/core.js', cookies: './client/js/pages/cookies.js', locationMap: './client/js/pages/location-map.js'