From 8358515200684b61bc54ab4521ce0cad909101f6 Mon Sep 17 00:00:00 2001 From: Scott Dormand <61588381+ScottDormand96@users.noreply.github.com> Date: Wed, 22 Nov 2023 11:37:31 +0000 Subject: [PATCH] Encourage users to choose digital reminders (#1821) * update content * move logic to route and add tests * code smells * code smell change email value setup * undo changes package.json * fix lint * refactor route and fix spelling issue * code smell --- .../gafl-webapp-service/src/locales/en.json | 20 ++-- .../contact/contact/__tests__/route.spec.js | 106 +++++++++++++++--- .../src/pages/contact/contact/contact.njk | 72 ++++++++---- .../src/pages/contact/contact/route.js | 34 +++++- 4 files changed, 182 insertions(+), 50 deletions(-) diff --git a/packages/gafl-webapp-service/src/locales/en.json b/packages/gafl-webapp-service/src/locales/en.json index 22a0a55bc4..53afbbc1ea 100644 --- a/packages/gafl-webapp-service/src/locales/en.json +++ b/packages/gafl-webapp-service/src/locales/en.json @@ -285,25 +285,31 @@ "identify_title": "Renew your rod fishing licence?", "important_info_contact_error_choose": "Choose how we should contact the licence holder", "important_info_contact_error_email": "Enter an email address in the correct format", - "important_info_contact_error_mobile": "Enter a UK mobile phone number", + "important_info_contact_error_mobile": "Enter a UK mobile number", "important_info_contact_input_email_hint": "For example name@example.com", "important_info_contact_input_email": "Email address", "important_info_contact_input_mobile_hint": "For example 07700 900 900", - "important_info_contact_input_mobile_note": "Mobile phone number", - "important_info_contact_input_mobile": "UK mobile phone number", + "important_info_contact_input_mobile_note": "UK mobile number", + "important_info_contact_input_mobile": "UK mobile number", "important_info_contact_item_email": "Email", + "important_info_contact_item_email_value": "Email ", "important_info_contact_item_txt": "Text message", + "important_info_contact_item_txt_value": "Text message to ", "important_info_contact_licence_needed": "The rod licence holder will need to confirm the licence number if asked by an enforcement officer.", "important_info_contact_none_msg": "We will show you the licence number on confirmation.", "important_info_contact_note_tip": "Make a note of the licence number", + "important_info_contact_post_hint_you": "By choosing post, you will not get a personalised link to renew your licence online before it expires.", + "important_info_contact_post_hint_other": "By choosing post, the licence holder will not get a personalised link to renew their licence online before it expires.", "important_info_contact_post_confirm_8d": "We don’t provide physical cards for 1 or 8 day licences.", "important_info_contact_post_confirm_jr": "We don’t provide physical cards for junior licences.", - "important_info_contact_post_confirm": "This is where we will send renewal reminders when the licence is ending.", - "important_info_contact_post_confirm2": "We will also send important information like byelaw updates.", + "important_info_contact_post_salmon_you": "We will send a renewal reminder before your licence expires and a reminder to report a catch return. We will also send other important updates, like rod fishing byelaw changes.", + "important_info_contact_post_not_salmon_you": "We will send a renewal reminder before your licence expires. We will also send other important updates, like rod fishing byelaw changes.", + "important_info_contact_post_salmon_other": "We will send a renewal reminder before the licence expires and a reminder to report a catch return. We will also send other important updates, like rod fishing byelaw changes.", + "important_info_contact_post_not_salmon_other": "We will send a renewal reminder before the licence expires. We will also send other important updates, like rod fishing byelaw changes.", "important_info_contact_post_msg": "If you want to fish before you receive the card you should make a note of the licence number after payment.", "important_info_contact_post": "Post", - "important_info_contact_title_other": "How should we contact the licence holder about reminders and important changes?", - "important_info_contact_title_you": "How should we contact you with reminders and important changes?", + "important_info_contact_title_other": "How should we contact the licence holder about updates affecting their licence?", + "important_info_contact_title_you": "How should we contact you about updates affecting your licence?", "licence_confirm_method_error_choose": "Choose how we should send the licence", "licence_confirm_method_how_body_item": "I will make a note of the licence number", "licence_confirm_method_how_body_text": "This is where we will send confirmation of the fishing licence", diff --git a/packages/gafl-webapp-service/src/pages/contact/contact/__tests__/route.spec.js b/packages/gafl-webapp-service/src/pages/contact/contact/__tests__/route.spec.js index 08a9e0aca9..1f2946a0bc 100644 --- a/packages/gafl-webapp-service/src/pages/contact/contact/__tests__/route.spec.js +++ b/packages/gafl-webapp-service/src/pages/contact/contact/__tests__/route.spec.js @@ -2,6 +2,7 @@ import { getData, validator } from '../route' import pageRoute from '../../../../routes/page-route.js' import { nextPage } from '../../../../routes/next-page.js' import { isPhysical } from '../../../../processors/licence-type-display.js' +import { hasJunior } from '../../../../processors/concession-helper.js' jest.mock('../../../../routes/next-page.js', () => ({ nextPage: jest.fn() @@ -15,46 +16,115 @@ jest.mock('../../../../uri.js', () => ({ } })) jest.mock('../../../../processors/licence-type-display.js') +jest.mock('../../../../processors/concession-helper.js') describe('name > route', () => { - const getMockRequest = (isLicenceForYou = true) => ({ + const getMockRequest = ({ isLicenceForYou, licenceType, email, mobilePhone }) => ({ cache: () => ({ helpers: { transaction: { getCurrentPermission: () => ({ licensee: { - birthDate: 'birthDate' + birthDate: 'birthDate', + email, + mobilePhone }, licenceLength: 'licenceLength', licenceStartDate: 'licenceStartDate', - isLicenceForYou + isLicenceForYou, + licenceType }) } } - }) + }), + i18n: { + getCatalog: () => getMessages() + } + }) + + const getMessages = () => ({ + important_info_contact_title_you: 'You title', + important_info_contact_title_other: 'Other title', + important_info_contact_item_email: 'Email', + important_info_contact_item_email_value: 'Email ', + important_info_contact_item_txt_value: 'Text to ', + important_info_contact_item_txt: 'Text', + important_info_contact_post_hint_you: 'Post hint you', + important_info_contact_post_hint_other: 'Post hint other', + important_info_contact_post_salmon_you: 'Salmon you', + important_info_contact_post_not_salmon_you: 'Not salmon you', + important_info_contact_post_salmon_other: 'Salmon other', + important_info_contact_post_not_salmon_other: 'Not salmon other' }) describe('getData', () => { - it('should return isLicenceForYou as true, if isLicenceForYou is true on the transaction cache', async () => { - const result = await getData(getMockRequest(true)) - expect(result.isLicenceForYou).toBeTruthy() + it.each([ + [true, 'You title'], + [false, 'Other title'] + ])('title return method is %s if isLicenceForYou is same', async (isLicenceForYou, expected) => { + const result = await getData(getMockRequest({ isLicenceForYou })) + expect(result.title).toBe(expected) }) - it('should return isLicenceForYou as false, if isLicenceForYou is false on the transaction cache', async () => { - const result = await getData(getMockRequest(false)) - expect(result.isLicenceForYou).toBeFalsy() + it.each([ + ['test@email.com', 'Email test@email.com'], + [null, 'Email'] + ])('emailText has correct value depending on if permission has an email', async (email, expected) => { + const result = await getData(getMockRequest({ email })) + expect(result.emailText).toBe(expected) + }) + + it.each([ + ['07123456789', 'Text to 07123456789'], + [null, 'Text'] + ])('mobileText has correct value depending on if permission has a phone number', async (mobilePhone, expected) => { + const result = await getData(getMockRequest({ mobilePhone })) + expect(result.mobileText).toBe(expected) + }) + + it.each([ + [true, 'Post hint you'], + [false, 'Post hint other'] + ])('postHint wording depending on whether isLicenceForYou is %s', async (isLicenceForYou, expected) => { + const result = await getData(getMockRequest({ isLicenceForYou })) + expect(result.postHint).toBe(expected) + }) + + it.each([ + [true, 'Salmon and sea trout', 'Salmon you'], + [true, 'Trout and coarse', 'Not salmon you'], + [false, 'Salmon and sea trout', 'Salmon other'], + [false, 'Trout and coarse', 'Not salmon other'] + ])( + 'content has correct value depending on isLicenceForYou is %s and licenceType is %s', + async (isLicenceForYou, licenceType, expected) => { + const result = await getData(getMockRequest({ isLicenceForYou, licenceType })) + expect(result.content).toBe(expected) + } + ) + + it.each([ + [true, true], + [false, false] + ])('result.isPhysical matches return method of isPhysical', async (physical, expected) => { + isPhysical.mockReturnValueOnce(physical) + const result = await getData(getMockRequest({})) + expect(result.isPhysical).toBe(expected) }) - it('return isPhysical as true, if isPhysical is true for the permission', async () => { - isPhysical.mockReturnValueOnce(true) - const result = await getData(getMockRequest()) - expect(result.isPhysical).toBeTruthy() + it.each([ + [true, true], + [false, false] + ])('isJunior matches return method of hasJunior', async (physical, expected) => { + hasJunior.mockReturnValueOnce(physical) + const result = await getData(getMockRequest({})) + expect(result.isJunior).toBe(expected) }) - it('return isPhysical as false, if isPhysical is false for the permission', async () => { - isPhysical.mockReturnValueOnce(false) - const result = await getData(getMockRequest()) - expect(result.isPhysical).toBeFalsy() + it('howContacted returns the value of HOW_CONTACTED', async () => { + const expectedValue = { email: 'Email', text: 'Text', letter: 'Letter', none: 'Prefer not to be contacted' } + const result = await getData(getMockRequest({})) + expect(result.howContacted).toEqual(expectedValue) }) }) diff --git a/packages/gafl-webapp-service/src/pages/contact/contact/contact.njk b/packages/gafl-webapp-service/src/pages/contact/contact/contact.njk index 5036fafb05..665a7217c9 100644 --- a/packages/gafl-webapp-service/src/pages/contact/contact/contact.njk +++ b/packages/gafl-webapp-service/src/pages/contact/contact/contact.njk @@ -3,7 +3,7 @@ {% from "input/macro.njk" import govukInput %} {% from "warning-text/macro.njk" import govukWarningText %} -{% set title = mssgs.important_info_contact_title_you if data.isLicenceForYou else mssgs.important_info_contact_title_other %} +{% set title = data.title %} {% set errorMsg = mssgs.important_info_contact_error_choose %} {% set emailError = mssgs.important_info_contact_error_email %} {% set mobileError = mssgs.important_info_contact_error_mobile %} @@ -52,7 +52,6 @@
{{ mssgs.important_info_contact_input_email }}
{{ data.licensee.email }} -   {{ mssgs.licence_summary_change }}
{% endset -%} @@ -81,7 +80,6 @@
{{ mssgs.important_info_contact_input_mobile_note }}
{{ data.licensee.mobilePhone }} -   {{ mssgs.licence_summary_change }}
{% endset -%} @@ -94,24 +92,48 @@

{{ mssgs.important_info_contact_none_msg }}

{% endset -%} -{% set itemsArray = [ - { - value: "email", - text: mssgs.important_info_contact_item_email, - checked: payload['how-contacted'] === 'email', - conditional: { - html: emailHtml - } - }, - { - value: "text", - text: mssgs.important_info_contact_item_txt, - checked: payload['how-contacted'] === 'text', - conditional: { - html: textMessageHtml - } - } -] %} +{% set itemsArray = [] %} +{% if data.licensee.email %} + {% set itemsArray = (itemsArray.push( + { + value: "email", + text: data.emailText, + checked: payload['how-contacted'] === 'email' + }), itemsArray) + %} +{% else %} + {% set itemsArray = (itemsArray.push( + { + value: "email", + text: data.emailText, + checked: payload['how-contacted'] === 'email', + conditional: { + html: emailHtml + } + }), itemsArray) + %} +{% endif %} + +{% if data.licensee.mobilePhone %} + {% set itemsArray = (itemsArray.push( + { + value: "text", + text: data.mobileText, + checked: payload['how-contacted'] === 'text' + }), itemsArray) + %} +{% else %} + {% set itemsArray = (itemsArray.push( + { + value: "text", + text: data.mobileText, + checked: payload['how-contacted'] === 'text', + conditional: { + html: textMessageHtml + } + }), itemsArray) + %} +{% endif %} {% if data.isPhysical %} {% if data.licensee.postalFulfilment %} @@ -119,7 +141,10 @@ { value: "none", text: mssgs.important_info_contact_post, - checked: payload['how-contacted'] === 'post' + checked: payload['how-contacted'] === 'post', + hint: { + text: data.postHint + } }), itemsArray) %} {% endif %} @@ -138,8 +163,7 @@ {% block pageContent %} {% if data.isPhysical %} -

{{ mssgs.important_info_contact_post_confirm }}

-

{{ mssgs.important_info_contact_post_confirm2 }}

+

{{ data.content }}

{% else %} {% if data.isJunior %}

{{ mssgs.important_info_contact_post_confirm_jr }}

diff --git a/packages/gafl-webapp-service/src/pages/contact/contact/route.js b/packages/gafl-webapp-service/src/pages/contact/contact/route.js index 08d82c28c0..912bc77093 100644 --- a/packages/gafl-webapp-service/src/pages/contact/contact/route.js +++ b/packages/gafl-webapp-service/src/pages/contact/contact/route.js @@ -11,6 +11,7 @@ import { mobilePhoneValidator } from '../../../processors/contact-validator.js' export const getData = async request => { const permission = await request.cache().helpers.transaction.getCurrentPermission() + const mssgs = request.i18n.getCatalog() // We need to have set the licence length, dob and start date here to determining the contact // messaging @@ -27,7 +28,11 @@ export const getData = async request => { } return { - isLicenceForYou: permission.isLicenceForYou, + title: getTitle(permission, mssgs), + postHint: getPostHint(permission, mssgs), + content: getContent(permission, mssgs), + emailText: getEmailText(permission, mssgs), + mobileText: getMobileText(permission, mssgs), licensee: permission.licensee, isPhysical: isPhysical(permission), isJunior: hasJunior(permission), @@ -35,6 +40,33 @@ export const getData = async request => { } } +const getTitle = (permission, messages) => + permission.isLicenceForYou + ? messages.important_info_contact_title_you + : messages.important_info_contact_title_other + +const getPostHint = (permission, messages) => + permission.isLicenceForYou + ? messages.important_info_contact_post_hint_you + : messages.important_info_contact_post_hint_other + +const getContent = (permission, messages) => { + if (permission.licenceType === 'Salmon and sea trout') { + return permission.isLicenceForYou ? messages.important_info_contact_post_salmon_you : messages.important_info_contact_post_salmon_other + } + return permission.isLicenceForYou ? messages.important_info_contact_post_not_salmon_you : messages.important_info_contact_post_not_salmon_other +} + +const getMobileText = (permission, messages) => + permission.licensee.mobilePhone + ? `${messages.important_info_contact_item_txt_value}${permission.licensee.mobilePhone}` + : messages.important_info_contact_item_txt + +const getEmailText = (permission, messages) => + permission.licensee.email + ? `${messages.important_info_contact_item_email_value}${permission.licensee.email}` + : messages.important_info_contact_item_email + export const validator = Joi.object({ 'how-contacted': Joi.string().valid('email', 'text', 'none').required(), email: Joi.alternatives().conditional('how-contacted', {