@defra-fish/gafl-webapp-service 1.63.0 → 1.64.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/README.md +2 -1
  2. package/package.json +4 -4
  3. package/src/handlers/__tests__/cancel-rp-authentication-handler.spec.js +18 -0
  4. package/src/handlers/cancel-rp-authentication-handler.js +6 -0
  5. package/src/locales/cy.json +5 -0
  6. package/src/locales/en.json +5 -0
  7. package/src/pages/contact/contact/__tests__/route.spec.js +6 -5
  8. package/src/pages/contact/contact/route.js +12 -5
  9. package/src/pages/recurring-payments/cancel/complete/__tests__/route.test.js +80 -0
  10. package/src/pages/recurring-payments/cancel/complete/cancel-rp-complete.njk +16 -0
  11. package/src/pages/recurring-payments/cancel/complete/route.js +10 -0
  12. package/src/pages/recurring-payments/cancel/confirm/__tests__/route.test.js +106 -0
  13. package/src/pages/recurring-payments/cancel/confirm/cancel-rp-confirm.njk +24 -0
  14. package/src/pages/recurring-payments/cancel/confirm/route.js +11 -0
  15. package/src/pages/recurring-payments/cancel/details/__tests__/route.test.js +106 -0
  16. package/src/pages/recurring-payments/cancel/details/cancel-rp-details.njk +24 -0
  17. package/src/pages/recurring-payments/cancel/details/route.js +11 -0
  18. package/src/pages/recurring-payments/cancel/identify/__tests__/route.test.js +106 -0
  19. package/src/pages/recurring-payments/cancel/identify/cancel-rp-identify.njk +24 -0
  20. package/src/pages/recurring-payments/cancel/identify/route.js +13 -0
  21. package/src/routes/__tests__/__snapshots__/telesales-routes.spec.js.snap +185 -0
  22. package/src/routes/__tests__/telesales-routes.spec.js +29 -0
  23. package/src/routes/journey-definition.js +31 -1
  24. package/src/routes/misc-routes.js +8 -1
  25. package/src/routes/telesales-routes.js +13 -1
  26. package/src/uri.js +6 -0
package/README.md CHANGED
@@ -38,7 +38,8 @@ To run from this directory:
38
38
  | SHOW_WELSH_CONTENT | Display option to change to welsh language | no | | |
39
39
  | ENABLE_ANALYTICS_OPT_IN_DEBUGGING | Set log if analytics been checked in non-production | no | | |
40
40
  | ERROR_PAGE_ROUTE | Display error pages to support welsh language | no | | |
41
- | SHOW_RECURRING_PAYMENTS | Display option to show recurring payments joruney | no | | |
41
+ | SHOW_RECURRING_PAYMENTS | Display option to show recurring payments journey | no | | |
42
+ | SHOW_CANCELLATION_JOURNEY | Display option to show recurring payments cancellation journey | no | | |
42
43
 
43
44
  ## OS Places address lookup
44
45
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defra-fish/gafl-webapp-service",
3
- "version": "1.63.0",
3
+ "version": "1.64.0-rc.1",
4
4
  "description": "The websales frontend for the GAFL service",
5
5
  "type": "module",
6
6
  "engines": {
@@ -36,8 +36,8 @@
36
36
  "prepare": "gulp --gulpfile build/gulpfile.cjs"
37
37
  },
38
38
  "dependencies": {
39
- "@defra-fish/business-rules-lib": "1.63.0",
40
- "@defra-fish/connectors-lib": "1.63.0",
39
+ "@defra-fish/business-rules-lib": "1.64.0-rc.1",
40
+ "@defra-fish/connectors-lib": "1.64.0-rc.1",
41
41
  "@defra/hapi-gapi": "^2.0.0",
42
42
  "@hapi/boom": "^9.1.2",
43
43
  "@hapi/catbox-redis": "^6.0.2",
@@ -79,5 +79,5 @@
79
79
  "./gafl-jest-matchers.js"
80
80
  ]
81
81
  },
82
- "gitHead": "7cfb8ef668002fc340b755dd3aaa4572063e115c"
82
+ "gitHead": "2d114ca497f84cd7ede12c2f93965a7044d2f39a"
83
83
  }
@@ -0,0 +1,18 @@
1
+ import cancelRpAuthenticationHandler from '../cancel-rp-authentication-handler'
2
+ import { CONTROLLER } from '../../uri.js'
3
+
4
+ jest.mock('../../uri.js', () => ({
5
+ CONTROLLER: { uri: Symbol('controller-uri') }
6
+ }))
7
+
8
+ const getSampleResponseToolkit = () => ({
9
+ redirectWithLanguageCode: jest.fn()
10
+ })
11
+
12
+ describe('Cancel RP Authentication Handler', () => {
13
+ it('redirects with language code to CONTROLLER.uri', () => {
14
+ const sampleResponseToolkit = getSampleResponseToolkit()
15
+ cancelRpAuthenticationHandler(undefined, sampleResponseToolkit)
16
+ expect(sampleResponseToolkit.redirectWithLanguageCode).toHaveBeenCalledWith(CONTROLLER.uri)
17
+ })
18
+ })
@@ -0,0 +1,6 @@
1
+ import { CONTROLLER } from '../uri.js'
2
+
3
+ export default async (_request, h) => {
4
+ console.log('cancel rp authenticate handler', h.redirectWithLanguageCode)
5
+ return h.redirectWithLanguageCode(CONTROLLER.uri)
6
+ }
@@ -350,6 +350,7 @@
350
350
  "identify_title": "Adnewyddu eich trwydded bysgota?",
351
351
  "important_info_contact_content_salmon": "Byddwn yn defnyddio’r cyfeiriad e-bost neu’r rhif symudol hwn i anfon nodyn atgoffa i anfon adroddiad daliad. Mae’n bosibl y byddwn hefyd yn anfon gwybodaeth bwysig arall, megis newidiadau sy’n effeithio ar y drwydded neu is-ddeddfau pysgota.",
352
352
  "important_info_contact_content_not_salmon": "Mae’n bosibl y byddwn hefyd yn defnyddio’r cyfeiriad e-bost neu’r rhif symudol hwn i anfon gwybodaeth bwysig, megis newidiadau sy’n effeithio ar y drwydded neu’r is-ddeddfau pysgota.",
353
+ "important_info_contact_content_junior_12_months": "Byddwn hefyd yn defnyddio’r cyfeiriad e-bost neu’r rhif symudol hwn i anfon nodyn atgoffa am adnewyddu neu ddiweddariadau pwysig eraill, fel newidiadau i is-ddeddfau pysgota.",
353
354
  "important_info_contact_error_choose_short": "Dewiswch i ble y dylem anfon y drwydded bysgota",
354
355
  "important_info_contact_error_choose": "Dewiswch sut y dylem gysylltu â deiliad y drwydded",
355
356
  "important_info_contact_error_email": "Rhowch gyfeiriad e-bost yn y fformat cywir",
@@ -771,6 +772,10 @@
771
772
  "role_required_body_1": "You were successfully signed in but you do not have the correct role assigned to access the telesales application.",
772
773
  "role_required_body_2": "Please contact your Microsoft Dynamics administrator to request access.",
773
774
  "role_required_title": "Role required",
775
+ "rp_cancel_complete_title": "Cancel your recurring card payment agreement - complete",
776
+ "rp_cancel_confirm_title": "Cancel your recurring card payment agreement - confirm",
777
+ "rp_cancel_details_title": "Cancel your recurring card payment agreement - details",
778
+ "rp_cancel_identify_title": "Cancel your recurring card payment agreement - identify",
774
779
  "save_changes": "Cadw newidiadau",
775
780
  "server_error_title_suffix": " - GOV.UK",
776
781
  "server_error_bulletpoint_1": "Os ydych chi wedi gofyn am hysbysiad dros e-bost neu neges destun, dylai’r hysbysiad gyrraedd o fewn 3 awr os bydd y taliad wedi cael ei gymryd.",
@@ -350,6 +350,7 @@
350
350
  "identify_title": "Renew your rod fishing licence?",
351
351
  "important_info_contact_content_salmon": "We will use this email or mobile number to send a reminder to report a catch return. We may also send other important information, such as changes affecting the licence or the fishing byelaws.",
352
352
  "important_info_contact_content_not_salmon": "We may also use this email or mobile number to send important information, such as changes affecting the licence or the fishing byelaws.",
353
+ "important_info_contact_content_junior_12_months": "We will also use this email or mobile number to send renewal reminders and other important updates, like changes to rod fishing byelaws.",
353
354
  "important_info_contact_error_choose_short": "Choose where we should send the fishing licence",
354
355
  "important_info_contact_error_choose": "Choose how we should contact the licence holder",
355
356
  "important_info_contact_error_email": "Enter an email address in the correct format",
@@ -771,6 +772,10 @@
771
772
  "role_required_body_1": "You were successfully signed in but you do not have the correct role assigned to access the telesales application.",
772
773
  "role_required_body_2": "Please contact your Microsoft Dynamics administrator to request access.",
773
774
  "role_required_title": "Role required",
775
+ "rp_cancel_complete_title": "Cancel your recurring card payment agreement - complete",
776
+ "rp_cancel_confirm_title": "Cancel your recurring card payment agreement - confirm",
777
+ "rp_cancel_details_title": "Cancel your recurring card payment agreement - details",
778
+ "rp_cancel_identify_title": "Cancel your recurring card payment agreement - identify",
774
779
  "save_changes": "Save changes",
775
780
  "server_error_title_suffix": " - GOV.UK",
776
781
  "server_error_bulletpoint_1": "If you have requested an email or text notification, this should be delivered in 3 hours if a payment has been taken.",
@@ -56,7 +56,8 @@ describe('name > route', () => {
56
56
  important_info_contact_content_salmon: 'Salmon content',
57
57
  important_info_contact_content_not_salmon: 'Not salmon content',
58
58
  licence_confirm_method_where_title_you: 'Where send you',
59
- licence_confirm_method_where_title_other: 'Where send other'
59
+ licence_confirm_method_where_title_other: 'Where send other',
60
+ important_info_contact_content_junior_12_months: 'Junior content'
60
61
  })
61
62
 
62
63
  describe('getData', () => {
@@ -149,10 +150,10 @@ describe('name > route', () => {
149
150
  [true, 'Trout and coarse', '8D', false, 'Not salmon content'],
150
151
  [false, 'Salmon and sea trout', '1D', false, 'Salmon content'],
151
152
  [false, 'Trout and coarse', '1D', false, 'Not salmon content'],
152
- [true, 'Salmon and sea trout', '12M', true, 'Salmon content'],
153
- [true, 'Trout and coarse', '12M', true, 'Not salmon content'],
154
- [false, 'Salmon and sea trout', '12M', true, 'Salmon content'],
155
- [false, 'Trout and coarse', '12M', true, 'Not salmon content']
153
+ [true, 'Salmon and sea trout', '12M', true, 'Junior content'],
154
+ [true, 'Trout and coarse', '12M', true, 'Junior content'],
155
+ [false, 'Salmon and sea trout', '12M', true, 'Junior content'],
156
+ [false, 'Trout and coarse', '12M', true, 'Junior content']
156
157
  ])(
157
158
  'content has correct value depending on isLicenceForYou is %s, licenceType is %s, licenceLength is %s and junior is %s',
158
159
  async (isLicenceForYou, licenceType, licenceLength, junior, expected) => {
@@ -13,8 +13,7 @@ export const getData = async request => {
13
13
  const permission = await request.cache().helpers.transaction.getCurrentPermission()
14
14
  const mssgs = request.i18n.getCatalog()
15
15
 
16
- // We need to have set the licence length, dob and start date here to determining the contact
17
- // messaging
16
+ // We need to have set the licence length, dob and start date here to determine the contact messaging
18
17
  if (!permission.licensee.birthDate) {
19
18
  throw new GetDataRedirect(DATE_OF_BIRTH.uri)
20
19
  }
@@ -29,11 +28,12 @@ export const getData = async request => {
29
28
 
30
29
  const junior = hasJunior(permission)
31
30
  const twelveMonthNonJuniorLicence = !junior && permission.licenceLength === '12M'
31
+ const twelveMonthJuniorLicence = junior && permission.licenceLength === '12M'
32
32
 
33
33
  return {
34
34
  title: getTitle(permission, mssgs, twelveMonthNonJuniorLicence),
35
35
  postHint: getPostHint(permission, mssgs),
36
- content: getContent(permission, mssgs, twelveMonthNonJuniorLicence),
36
+ content: getContent(permission, mssgs, twelveMonthNonJuniorLicence, twelveMonthJuniorLicence),
37
37
  emailConfirmation: permission.licensee.preferredMethodOfConfirmation === HOW_CONTACTED.email,
38
38
  emailText: getEmailText(permission, mssgs, twelveMonthNonJuniorLicence),
39
39
  mobileConfirmation: permission.licensee.preferredMethodOfConfirmation === HOW_CONTACTED.text,
@@ -41,7 +41,8 @@ export const getData = async request => {
41
41
  licensee: permission.licensee,
42
42
  isPhysical: isPhysical(permission),
43
43
  errorMessage: getErrorText(mssgs, twelveMonthNonJuniorLicence),
44
- twelveMonthNonJuniorLicence
44
+ twelveMonthNonJuniorLicence,
45
+ twelveMonthJuniorLicence
45
46
  }
46
47
  }
47
48
 
@@ -55,8 +56,9 @@ const getTitle = (permission, messages, twelveMonthNonJuniorLicence) => {
55
56
  const getPostHint = (permission, messages) =>
56
57
  permission.isLicenceForYou ? messages.important_info_contact_post_hint_you : messages.important_info_contact_post_hint_other
57
58
 
58
- const getContent = (permission, messages, twelveMonthNonJuniorLicence) => {
59
+ const getContent = (permission, messages, twelveMonthNonJuniorLicence, twelveMonthJuniorLicence) => {
59
60
  const isSalmonLicense = permission.licenceType === 'Salmon and sea trout'
61
+
60
62
  if (twelveMonthNonJuniorLicence) {
61
63
  if (isSalmonLicense) {
62
64
  return permission.isLicenceForYou
@@ -67,6 +69,11 @@ const getContent = (permission, messages, twelveMonthNonJuniorLicence) => {
67
69
  ? messages.important_info_contact_post_not_salmon_you
68
70
  : messages.important_info_contact_post_not_salmon_other
69
71
  }
72
+
73
+ if (twelveMonthJuniorLicence) {
74
+ return messages.important_info_contact_content_junior_12_months
75
+ }
76
+
70
77
  return isSalmonLicense ? messages.important_info_contact_content_salmon : messages.important_info_contact_content_not_salmon
71
78
  }
72
79
 
@@ -0,0 +1,80 @@
1
+ import pageRoute from '../../../../../routes/page-route.js'
2
+ import { CANCEL_RP_COMPLETE } from '../../../../../uri.js'
3
+
4
+ require('../route.js')
5
+ // eslint-disable-next-line no-unused-vars
6
+ const [[_v, _p, validator, completion, getData]] = pageRoute.mock.calls
7
+
8
+ jest.mock('../../../../../routes/page-route.js')
9
+ jest.mock('../../../../../uri.js', () => ({
10
+ ...jest.requireActual('../../../../../uri.js'),
11
+ CANCEL_RP_COMPLETE: { page: Symbol('cancel-rp-complete-page'), uri: Symbol('cancel-rp-complete-uri') }
12
+ }))
13
+ jest.mock('../../../../../processors/uri-helper.js')
14
+
15
+ describe('pageRoute receives expected arguments', () => {
16
+ it('passes CANCEL_RP_COMPLETE.page as the view name', () => {
17
+ jest.isolateModules(() => {
18
+ require('../route.js')
19
+ expect(pageRoute).toHaveBeenCalledWith(
20
+ CANCEL_RP_COMPLETE.page,
21
+ expect.anything(),
22
+ expect.anything(),
23
+ expect.anything(),
24
+ expect.anything()
25
+ )
26
+ })
27
+ })
28
+
29
+ it('passes CANCEL_RP_COMPLETE.uri as the path', () => {
30
+ jest.isolateModules(() => {
31
+ require('../route.js')
32
+ expect(pageRoute).toHaveBeenCalledWith(
33
+ expect.anything(),
34
+ CANCEL_RP_COMPLETE.uri,
35
+ expect.anything(),
36
+ expect.anything(),
37
+ expect.anything()
38
+ )
39
+ })
40
+ })
41
+
42
+ it('passes a function as the validator', () => {
43
+ jest.isolateModules(() => {
44
+ require('../route.js')
45
+ expect(pageRoute).toHaveBeenCalledWith(
46
+ expect.anything(),
47
+ expect.anything(),
48
+ expect.any(Function),
49
+ expect.anything(),
50
+ expect.anything()
51
+ )
52
+ })
53
+ })
54
+
55
+ it('passes a function to generate redirect location on completion', () => {
56
+ jest.isolateModules(() => {
57
+ require('../route.js')
58
+ expect(pageRoute).toHaveBeenCalledWith(
59
+ expect.anything(),
60
+ expect.anything(),
61
+ expect.anything(),
62
+ expect.any(Function),
63
+ expect.anything()
64
+ )
65
+ })
66
+ })
67
+
68
+ it('passes a function to get the page data', () => {
69
+ jest.isolateModules(() => {
70
+ require('../route.js')
71
+ expect(pageRoute).toHaveBeenCalledWith(
72
+ expect.anything(),
73
+ expect.anything(),
74
+ expect.anything(),
75
+ expect.anything(),
76
+ expect.any(Function)
77
+ )
78
+ })
79
+ })
80
+ })
@@ -0,0 +1,16 @@
1
+ {% extends "layout.njk" %}
2
+
3
+ {% from "page-title.njk" import pageTitle %}
4
+
5
+ {% set title = mssgs.rp_cancel_complete_title %}
6
+ {% block pageTitle %}{{ pageTitle(title, error, mssgs) }}{% endblock %}
7
+
8
+ {% block content %}
9
+ <div class="govuk-grid-row">
10
+ <div class="govuk-grid-column-two-thirds">
11
+ <form method="post" class="govuk-!-margin-bottom-6">
12
+ {{ csrf() }}
13
+ </form>
14
+ </div>
15
+ </div>
16
+ {% endblock %}
@@ -0,0 +1,10 @@
1
+ import pageRoute from '../../../../routes/page-route.js'
2
+ import { CANCEL_RP_COMPLETE } from '../../../../uri.js'
3
+
4
+ export default pageRoute(
5
+ CANCEL_RP_COMPLETE.page,
6
+ CANCEL_RP_COMPLETE.uri,
7
+ () => {},
8
+ () => {},
9
+ () => {}
10
+ )
@@ -0,0 +1,106 @@
1
+ import pageRoute from '../../../../../routes/page-route.js'
2
+ import { CANCEL_RP_CONFIRM, CANCEL_RP_COMPLETE } from '../../../../../uri.js'
3
+ import { addLanguageCodeToUri } from '../../../../../processors/uri-helper.js'
4
+
5
+ require('../route.js')
6
+ // eslint-disable-next-line no-unused-vars
7
+ const [[_v, _p, validator, completion, getData]] = pageRoute.mock.calls
8
+
9
+ jest.mock('../../../../../routes/page-route.js')
10
+ jest.mock('../../../../../uri.js', () => ({
11
+ ...jest.requireActual('../../../../../uri.js'),
12
+ CANCEL_RP_CONFIRM: { page: Symbol('cancel-rp-confirm-page'), uri: Symbol('cancel-rp-confirm-uri') },
13
+ CANCEL_RP_COMPLETE: { uri: Symbol('cancel-rp-complete-uri') }
14
+ }))
15
+ jest.mock('../../../../../processors/uri-helper.js')
16
+
17
+ describe('pageRoute receives expected arguments', () => {
18
+ it('passes CANCEL_RP_CONFIRM.page as the view name', () => {
19
+ jest.isolateModules(() => {
20
+ require('../route.js')
21
+ expect(pageRoute).toHaveBeenCalledWith(
22
+ CANCEL_RP_CONFIRM.page,
23
+ expect.anything(),
24
+ expect.anything(),
25
+ expect.anything(),
26
+ expect.anything()
27
+ )
28
+ })
29
+ })
30
+
31
+ it('passes CANCEL_RP_CONFIRM.uri as the path', () => {
32
+ jest.isolateModules(() => {
33
+ require('../route.js')
34
+ expect(pageRoute).toHaveBeenCalledWith(
35
+ expect.anything(),
36
+ CANCEL_RP_CONFIRM.uri,
37
+ expect.anything(),
38
+ expect.anything(),
39
+ expect.anything()
40
+ )
41
+ })
42
+ })
43
+
44
+ it('passes a function as the validator', () => {
45
+ jest.isolateModules(() => {
46
+ require('../route.js')
47
+ expect(pageRoute).toHaveBeenCalledWith(
48
+ expect.anything(),
49
+ expect.anything(),
50
+ expect.any(Function),
51
+ expect.anything(),
52
+ expect.anything()
53
+ )
54
+ })
55
+ })
56
+
57
+ it('passes a function to generate redirect location on completion', () => {
58
+ jest.isolateModules(() => {
59
+ require('../route.js')
60
+ expect(pageRoute).toHaveBeenCalledWith(
61
+ expect.anything(),
62
+ expect.anything(),
63
+ expect.anything(),
64
+ expect.any(Function),
65
+ expect.anything()
66
+ )
67
+ })
68
+ })
69
+
70
+ it('passes a function to get the page data', () => {
71
+ jest.isolateModules(() => {
72
+ require('../route.js')
73
+ expect(pageRoute).toHaveBeenCalledWith(
74
+ expect.anything(),
75
+ expect.anything(),
76
+ expect.anything(),
77
+ expect.anything(),
78
+ expect.any(Function)
79
+ )
80
+ })
81
+ })
82
+ })
83
+
84
+ describe('completion function', () => {
85
+ beforeEach(jest.clearAllMocks)
86
+
87
+ it('calls addLanguageCodeToUri with request object', () => {
88
+ const sampleRequest = Symbol('sample request')
89
+ completion(sampleRequest)
90
+ expect(addLanguageCodeToUri).toHaveBeenCalledWith(sampleRequest, expect.anything())
91
+ })
92
+
93
+ it('calls addLanguageCodeToUri with CANCEL_RP_AUTHENTICATE uri', () => {
94
+ completion({})
95
+ expect(addLanguageCodeToUri).toHaveBeenCalledWith(expect.anything(), CANCEL_RP_COMPLETE.uri)
96
+ })
97
+
98
+ it('returns the value of addLanguageCodeToUri', () => {
99
+ const expectedCompletionRedirect = Symbol('expected-completion-redirect')
100
+ addLanguageCodeToUri.mockReturnValueOnce(expectedCompletionRedirect)
101
+
102
+ const completionRedirect = completion({})
103
+
104
+ expect(completionRedirect).toBe(expectedCompletionRedirect)
105
+ })
106
+ })
@@ -0,0 +1,24 @@
1
+ {% extends "layout.njk" %}
2
+
3
+ {% from "button/macro.njk" import govukButton %}
4
+ {% from "page-title.njk" import pageTitle %}
5
+
6
+ {% set title = mssgs.rp_cancel_confirm_title %}
7
+ {% block pageTitle %}{{ pageTitle(title, error, mssgs) }}{% endblock %}
8
+
9
+ {% block content %}
10
+ <div class="govuk-grid-row">
11
+ <div class="govuk-grid-column-two-thirds">
12
+ <form method="post" class="govuk-!-margin-bottom-6">
13
+ {{ govukButton({
14
+ attributes: { id: 'continue' },
15
+ preventDoubleClick: true,
16
+ name: "continue",
17
+ text: mssgs.continue,
18
+ classes: "govuk-!-margin-top-1"
19
+ }) }}
20
+ {{ csrf() }}
21
+ </form>
22
+ </div>
23
+ </div>
24
+ {% endblock %}
@@ -0,0 +1,11 @@
1
+ import pageRoute from '../../../../routes/page-route.js'
2
+ import { CANCEL_RP_CONFIRM, CANCEL_RP_COMPLETE } from '../../../../uri.js'
3
+ import { addLanguageCodeToUri } from '../../../../processors/uri-helper.js'
4
+
5
+ export default pageRoute(
6
+ CANCEL_RP_CONFIRM.page,
7
+ CANCEL_RP_CONFIRM.uri,
8
+ () => {},
9
+ request => addLanguageCodeToUri(request, CANCEL_RP_COMPLETE.uri),
10
+ () => {}
11
+ )
@@ -0,0 +1,106 @@
1
+ import pageRoute from '../../../../../routes/page-route.js'
2
+ import { CANCEL_RP_DETAILS, CANCEL_RP_CONFIRM } from '../../../../../uri.js'
3
+ import { addLanguageCodeToUri } from '../../../../../processors/uri-helper.js'
4
+
5
+ require('../route.js')
6
+ // eslint-disable-next-line no-unused-vars
7
+ const [[_v, _p, validator, completion, getData]] = pageRoute.mock.calls
8
+
9
+ jest.mock('../../../../../routes/page-route.js')
10
+ jest.mock('../../../../../uri.js', () => ({
11
+ ...jest.requireActual('../../../../../uri.js'),
12
+ CANCEL_RP_DETAILS: { page: Symbol('cancel-rp-details-page'), uri: Symbol('cancel-rp-details-uri') },
13
+ CANCEL_RP_CONFIRM: { uri: Symbol('cancel-rp-confirm-uri') }
14
+ }))
15
+ jest.mock('../../../../../processors/uri-helper.js')
16
+
17
+ describe('pageRoute receives expected arguments', () => {
18
+ it('passes CANCEL_RP_DETAILS.page as the view name', () => {
19
+ jest.isolateModules(() => {
20
+ require('../route.js')
21
+ expect(pageRoute).toHaveBeenCalledWith(
22
+ CANCEL_RP_DETAILS.page,
23
+ expect.anything(),
24
+ expect.anything(),
25
+ expect.anything(),
26
+ expect.anything()
27
+ )
28
+ })
29
+ })
30
+
31
+ it('passes CANCEL_RP_DETAILS.uri as the path', () => {
32
+ jest.isolateModules(() => {
33
+ require('../route.js')
34
+ expect(pageRoute).toHaveBeenCalledWith(
35
+ expect.anything(),
36
+ CANCEL_RP_DETAILS.uri,
37
+ expect.anything(),
38
+ expect.anything(),
39
+ expect.anything()
40
+ )
41
+ })
42
+ })
43
+
44
+ it('passes a function as the validator', () => {
45
+ jest.isolateModules(() => {
46
+ require('../route.js')
47
+ expect(pageRoute).toHaveBeenCalledWith(
48
+ expect.anything(),
49
+ expect.anything(),
50
+ expect.any(Function),
51
+ expect.anything(),
52
+ expect.anything()
53
+ )
54
+ })
55
+ })
56
+
57
+ it('passes a function to generate redirect location on completion', () => {
58
+ jest.isolateModules(() => {
59
+ require('../route.js')
60
+ expect(pageRoute).toHaveBeenCalledWith(
61
+ expect.anything(),
62
+ expect.anything(),
63
+ expect.anything(),
64
+ expect.any(Function),
65
+ expect.anything()
66
+ )
67
+ })
68
+ })
69
+
70
+ it('passes a function to get the page data', () => {
71
+ jest.isolateModules(() => {
72
+ require('../route.js')
73
+ expect(pageRoute).toHaveBeenCalledWith(
74
+ expect.anything(),
75
+ expect.anything(),
76
+ expect.anything(),
77
+ expect.anything(),
78
+ expect.any(Function)
79
+ )
80
+ })
81
+ })
82
+ })
83
+
84
+ describe('completion function', () => {
85
+ beforeEach(jest.clearAllMocks)
86
+
87
+ it('calls addLanguageCodeToUri with request object', () => {
88
+ const sampleRequest = Symbol('sample request')
89
+ completion(sampleRequest)
90
+ expect(addLanguageCodeToUri).toHaveBeenCalledWith(sampleRequest, expect.anything())
91
+ })
92
+
93
+ it('calls addLanguageCodeToUri with CANCEL_RP_AUTHENTICATE uri', () => {
94
+ completion({})
95
+ expect(addLanguageCodeToUri).toHaveBeenCalledWith(expect.anything(), CANCEL_RP_CONFIRM.uri)
96
+ })
97
+
98
+ it('returns the value of addLanguageCodeToUri', () => {
99
+ const expectedCompletionRedirect = Symbol('expected-completion-redirect')
100
+ addLanguageCodeToUri.mockReturnValueOnce(expectedCompletionRedirect)
101
+
102
+ const completionRedirect = completion({})
103
+
104
+ expect(completionRedirect).toBe(expectedCompletionRedirect)
105
+ })
106
+ })
@@ -0,0 +1,24 @@
1
+ {% extends "layout.njk" %}
2
+
3
+ {% from "button/macro.njk" import govukButton %}
4
+ {% from "page-title.njk" import pageTitle %}
5
+
6
+ {% set title = mssgs.rp_cancel_details_title %}
7
+ {% block pageTitle %}{{ pageTitle(title, error, mssgs) }}{% endblock %}
8
+
9
+ {% block content %}
10
+ <div class="govuk-grid-row">
11
+ <div class="govuk-grid-column-two-thirds">
12
+ <form method="post" class="govuk-!-margin-bottom-6">
13
+ {{ govukButton({
14
+ attributes: { id: 'continue' },
15
+ preventDoubleClick: true,
16
+ name: "continue",
17
+ text: mssgs.continue,
18
+ classes: "govuk-!-margin-top-1"
19
+ }) }}
20
+ {{ csrf() }}
21
+ </form>
22
+ </div>
23
+ </div>
24
+ {% endblock %}
@@ -0,0 +1,11 @@
1
+ import pageRoute from '../../../../routes/page-route.js'
2
+ import { CANCEL_RP_DETAILS, CANCEL_RP_CONFIRM } from '../../../../uri.js'
3
+ import { addLanguageCodeToUri } from '../../../../processors/uri-helper.js'
4
+
5
+ export default pageRoute(
6
+ CANCEL_RP_DETAILS.page,
7
+ CANCEL_RP_DETAILS.uri,
8
+ () => {},
9
+ request => addLanguageCodeToUri(request, CANCEL_RP_CONFIRM.uri),
10
+ () => {}
11
+ )
@@ -0,0 +1,106 @@
1
+ import pageRoute from '../../../../../routes/page-route.js'
2
+ import { CANCEL_RP_AUTHENTICATE, CANCEL_RP_IDENTIFY } from '../../../../../uri.js'
3
+ import { addLanguageCodeToUri } from '../../../../../processors/uri-helper.js'
4
+
5
+ require('../route.js')
6
+ // eslint-disable-next-line no-unused-vars
7
+ const [[_v, _p, validator, completion, getData]] = pageRoute.mock.calls
8
+
9
+ jest.mock('../../../../../routes/page-route.js')
10
+ jest.mock('../../../../../uri.js', () => ({
11
+ ...jest.requireActual('../../../../../uri.js'),
12
+ CANCEL_RP_IDENTIFY: { page: Symbol('cancel-rp-identify'), uri: Symbol('cancel-rp-identify-uri') },
13
+ CANCEL_RP_AUTHENTICATE: { uri: Symbol('cancel-rp-authenticate-uri') }
14
+ }))
15
+ jest.mock('../../../../../processors/uri-helper.js')
16
+
17
+ describe('pageRoute receives expected arguments', () => {
18
+ it('passes CANCEL_RP_IDENTIFY.page as the view name', () => {
19
+ jest.isolateModules(() => {
20
+ require('../route.js')
21
+ expect(pageRoute).toHaveBeenCalledWith(
22
+ CANCEL_RP_IDENTIFY.page,
23
+ expect.anything(),
24
+ expect.anything(),
25
+ expect.anything(),
26
+ expect.anything()
27
+ )
28
+ })
29
+ })
30
+
31
+ it('passes CANCEL_RP_IDENTIFY.uri as the path', () => {
32
+ jest.isolateModules(() => {
33
+ require('../route.js')
34
+ expect(pageRoute).toHaveBeenCalledWith(
35
+ expect.anything(),
36
+ CANCEL_RP_IDENTIFY.uri,
37
+ expect.anything(),
38
+ expect.anything(),
39
+ expect.anything()
40
+ )
41
+ })
42
+ })
43
+
44
+ it('passes a function as the validator', () => {
45
+ jest.isolateModules(() => {
46
+ require('../route.js')
47
+ expect(pageRoute).toHaveBeenCalledWith(
48
+ expect.anything(),
49
+ expect.anything(),
50
+ expect.any(Function),
51
+ expect.anything(),
52
+ expect.anything()
53
+ )
54
+ })
55
+ })
56
+
57
+ it('passes a function to generate redirect location on completion', () => {
58
+ jest.isolateModules(() => {
59
+ require('../route.js')
60
+ expect(pageRoute).toHaveBeenCalledWith(
61
+ expect.anything(),
62
+ expect.anything(),
63
+ expect.anything(),
64
+ expect.any(Function),
65
+ expect.anything()
66
+ )
67
+ })
68
+ })
69
+
70
+ it('passes a function to get the page data', () => {
71
+ jest.isolateModules(() => {
72
+ require('../route.js')
73
+ expect(pageRoute).toHaveBeenCalledWith(
74
+ expect.anything(),
75
+ expect.anything(),
76
+ expect.anything(),
77
+ expect.anything(),
78
+ expect.any(Function)
79
+ )
80
+ })
81
+ })
82
+ })
83
+
84
+ describe('completion function', () => {
85
+ beforeEach(jest.clearAllMocks)
86
+
87
+ it('calls addLanguageCodeToUri with request', () => {
88
+ const sampleRequest = Symbol('sample request')
89
+ completion(sampleRequest)
90
+ expect(addLanguageCodeToUri).toHaveBeenCalledWith(sampleRequest, expect.anything())
91
+ })
92
+
93
+ it('calls addLanguageCodeToUri with CANCEL_RP_AUTHENTICATE uri', () => {
94
+ completion({})
95
+ expect(addLanguageCodeToUri).toHaveBeenCalledWith(expect.anything(), CANCEL_RP_AUTHENTICATE.uri)
96
+ })
97
+
98
+ it('returns the value of addLanguageCodeToUri', () => {
99
+ const expectedCompletionRedirect = Symbol('expected-completion-redirect')
100
+ addLanguageCodeToUri.mockReturnValueOnce(expectedCompletionRedirect)
101
+
102
+ const completionRedirect = completion({})
103
+
104
+ expect(completionRedirect).toBe(expectedCompletionRedirect)
105
+ })
106
+ })
@@ -0,0 +1,24 @@
1
+ {% extends "layout.njk" %}
2
+
3
+ {% from "button/macro.njk" import govukButton %}
4
+ {% from "page-title.njk" import pageTitle %}
5
+
6
+ {% set title = mssgs.rp_cancel_identify_title %}
7
+ {% block pageTitle %}{{ pageTitle(title, error, mssgs) }}{% endblock %}
8
+
9
+ {% block content %}
10
+ <div class="govuk-grid-row">
11
+ <div class="govuk-grid-column-two-thirds">
12
+ <form method="post" class="govuk-!-margin-bottom-6">
13
+ {{ govukButton({
14
+ attributes: { id: 'continue' },
15
+ preventDoubleClick: true,
16
+ name: "continue",
17
+ text: mssgs.continue,
18
+ classes: "govuk-!-margin-top-1"
19
+ }) }}
20
+ {{ csrf() }}
21
+ </form>
22
+ </div>
23
+ </div>
24
+ {% endblock %}
@@ -0,0 +1,13 @@
1
+ import pageRoute from '../../../../routes/page-route.js'
2
+ import { CANCEL_RP_AUTHENTICATE, CANCEL_RP_IDENTIFY } from '../../../../uri.js'
3
+ import { addLanguageCodeToUri } from '../../../../processors/uri-helper.js'
4
+
5
+ export default pageRoute(
6
+ CANCEL_RP_IDENTIFY.page,
7
+ CANCEL_RP_IDENTIFY.uri,
8
+ () => {},
9
+ request => {
10
+ return addLanguageCodeToUri(request, CANCEL_RP_AUTHENTICATE.uri)
11
+ },
12
+ () => {}
13
+ )
@@ -0,0 +1,185 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`cancellation route journey behaves as expected adds the cancellation route journey if SHOW_CANCELLATION_JOURNEY is set to true 1`] = `
4
+ Object {
5
+ "default": Array [
6
+ Object {
7
+ "handler": [Function],
8
+ "method": Array [
9
+ "POST",
10
+ ],
11
+ "options": Object {
12
+ "auth": false,
13
+ "plugins": Object {
14
+ "crumb": false,
15
+ },
16
+ },
17
+ "path": "/oidc/signin",
18
+ },
19
+ Object {
20
+ "handler": [Function],
21
+ "method": Array [
22
+ "GET",
23
+ ],
24
+ "options": Object {
25
+ "auth": false,
26
+ },
27
+ "path": "/oidc/account-disabled",
28
+ },
29
+ Object {
30
+ "handler": [Function],
31
+ "method": Array [
32
+ "GET",
33
+ ],
34
+ "options": Object {
35
+ "auth": false,
36
+ },
37
+ "path": "/oidc/role-required",
38
+ },
39
+ Object {
40
+ "handler": [Function],
41
+ "method": "GET",
42
+ "path": "/buy/cancel-recurring-payment/identify",
43
+ },
44
+ Object {
45
+ "handler": [Function],
46
+ "method": "POST",
47
+ "options": Object {
48
+ "validate": Object {
49
+ "failAction": [Function],
50
+ "payload": [Function],
51
+ },
52
+ },
53
+ "path": "/buy/cancel-recurring-payment/identify",
54
+ },
55
+ Object {
56
+ "handler": [Function],
57
+ "method": "GET",
58
+ "path": "/buy/cancel-recurring-payment/details",
59
+ },
60
+ Object {
61
+ "handler": [Function],
62
+ "method": "POST",
63
+ "options": Object {
64
+ "validate": Object {
65
+ "failAction": [Function],
66
+ "payload": [Function],
67
+ },
68
+ },
69
+ "path": "/buy/cancel-recurring-payment/details",
70
+ },
71
+ Object {
72
+ "handler": [Function],
73
+ "method": "GET",
74
+ "path": "/buy/cancel-recurring-payment/confirm",
75
+ },
76
+ Object {
77
+ "handler": [Function],
78
+ "method": "POST",
79
+ "options": Object {
80
+ "validate": Object {
81
+ "failAction": [Function],
82
+ "payload": [Function],
83
+ },
84
+ },
85
+ "path": "/buy/cancel-recurring-payment/confirm",
86
+ },
87
+ Object {
88
+ "handler": [Function],
89
+ "method": "GET",
90
+ "path": "/buy/cancel-recurring-payment/complete",
91
+ },
92
+ Object {
93
+ "handler": [Function],
94
+ "method": "POST",
95
+ "options": Object {
96
+ "validate": Object {
97
+ "failAction": [Function],
98
+ "payload": [Function],
99
+ },
100
+ },
101
+ "path": "/buy/cancel-recurring-payment/complete",
102
+ },
103
+ ],
104
+ }
105
+ `;
106
+
107
+ exports[`cancellation route journey behaves as expected omits the cancellation route journey if SHOW_CANCELLATION_JOURNEY is not present 1`] = `
108
+ Object {
109
+ "default": Array [
110
+ Object {
111
+ "handler": [Function],
112
+ "method": Array [
113
+ "POST",
114
+ ],
115
+ "options": Object {
116
+ "auth": false,
117
+ "plugins": Object {
118
+ "crumb": false,
119
+ },
120
+ },
121
+ "path": "/oidc/signin",
122
+ },
123
+ Object {
124
+ "handler": [Function],
125
+ "method": Array [
126
+ "GET",
127
+ ],
128
+ "options": Object {
129
+ "auth": false,
130
+ },
131
+ "path": "/oidc/account-disabled",
132
+ },
133
+ Object {
134
+ "handler": [Function],
135
+ "method": Array [
136
+ "GET",
137
+ ],
138
+ "options": Object {
139
+ "auth": false,
140
+ },
141
+ "path": "/oidc/role-required",
142
+ },
143
+ ],
144
+ }
145
+ `;
146
+
147
+ exports[`cancellation route journey behaves as expected omits the cancellation route journey if SHOW_CANCELLATION_JOURNEY is set to false 1`] = `
148
+ Object {
149
+ "default": Array [
150
+ Object {
151
+ "handler": [Function],
152
+ "method": Array [
153
+ "POST",
154
+ ],
155
+ "options": Object {
156
+ "auth": false,
157
+ "plugins": Object {
158
+ "crumb": false,
159
+ },
160
+ },
161
+ "path": "/oidc/signin",
162
+ },
163
+ Object {
164
+ "handler": [Function],
165
+ "method": Array [
166
+ "GET",
167
+ ],
168
+ "options": Object {
169
+ "auth": false,
170
+ },
171
+ "path": "/oidc/account-disabled",
172
+ },
173
+ Object {
174
+ "handler": [Function],
175
+ "method": Array [
176
+ "GET",
177
+ ],
178
+ "options": Object {
179
+ "auth": false,
180
+ },
181
+ "path": "/oidc/role-required",
182
+ },
183
+ ],
184
+ }
185
+ `;
@@ -1,4 +1,5 @@
1
1
  import { setupEnvironment } from '../../__mocks__/openid-client.js'
2
+
2
3
  jest.mock('@defra-fish/connectors-lib')
3
4
 
4
5
  let TestUtils = null
@@ -43,3 +44,31 @@ describe('Telesales route handlers', () => {
43
44
  expect(data.statusCode).toBe(200)
44
45
  })
45
46
  })
47
+
48
+ describe('cancellation route journey behaves as expected', () => {
49
+ beforeEach(jest.clearAllMocks)
50
+
51
+ it('adds the cancellation route journey if SHOW_CANCELLATION_JOURNEY is set to true', () => {
52
+ process.env.SHOW_CANCELLATION_JOURNEY = 'true'
53
+ jest.isolateModules(() => {
54
+ const telesalesRoutes = require('../telesales-routes.js')
55
+ expect(telesalesRoutes).toMatchSnapshot()
56
+ })
57
+ })
58
+
59
+ it('omits the cancellation route journey if SHOW_CANCELLATION_JOURNEY is set to false', () => {
60
+ process.env.SHOW_CANCELLATION_JOURNEY = 'false'
61
+ jest.isolateModules(() => {
62
+ const telesalesRoutes = require('../telesales-routes.js')
63
+ expect(telesalesRoutes).toMatchSnapshot()
64
+ })
65
+ })
66
+
67
+ it('omits the cancellation route journey if SHOW_CANCELLATION_JOURNEY is not present', () => {
68
+ delete process.env.SHOW_CANCELLATION_JOURNEY
69
+ jest.isolateModules(() => {
70
+ const telesalesRoutes = require('../telesales-routes.js')
71
+ expect(telesalesRoutes).toMatchSnapshot()
72
+ })
73
+ })
74
+ })
@@ -29,7 +29,11 @@ import {
29
29
  RENEWAL_START_DATE,
30
30
  CHOOSE_PAYMENT,
31
31
  SET_UP_PAYMENT,
32
- LICENCE_NOT_FOUND
32
+ LICENCE_NOT_FOUND,
33
+ CANCEL_RP_IDENTIFY,
34
+ CANCEL_RP_DETAILS,
35
+ CANCEL_RP_CONFIRM,
36
+ CANCEL_RP_COMPLETE
33
37
  } from '../uri.js'
34
38
 
35
39
  import { CommonResults, CONTACT_SUMMARY_SEEN, ShowDigitalLicencePages } from '../constants.js'
@@ -426,5 +430,31 @@ export default [
426
430
  {
427
431
  current: RENEWAL_START_DATE,
428
432
  backLink: LICENCE_SUMMARY.uri
433
+ },
434
+
435
+ // cancel RP journey
436
+ {
437
+ current: CANCEL_RP_IDENTIFY,
438
+ next: {
439
+ [CommonResults.OK]: {
440
+ page: CANCEL_RP_DETAILS
441
+ }
442
+ }
443
+ },
444
+ {
445
+ current: CANCEL_RP_DETAILS,
446
+ next: {
447
+ [CommonResults.OK]: {
448
+ page: CANCEL_RP_CONFIRM
449
+ }
450
+ }
451
+ },
452
+ {
453
+ current: CANCEL_RP_CONFIRM,
454
+ next: {
455
+ [CommonResults.OK]: {
456
+ page: CANCEL_RP_COMPLETE
457
+ }
458
+ }
429
459
  }
430
460
  ]
@@ -13,7 +13,8 @@ import {
13
13
  OS_TERMS,
14
14
  PROCESS_ANALYTICS_PREFERENCES,
15
15
  NEW_PRICES,
16
- RECURRING_TERMS_CONDITIONS
16
+ RECURRING_TERMS_CONDITIONS,
17
+ CANCEL_RP_AUTHENTICATE
17
18
  } from '../uri.js'
18
19
 
19
20
  import {
@@ -32,6 +33,7 @@ import authenticationHandler from '../handlers/authentication-handler.js'
32
33
  import { addLanguageCodeToUri } from '../processors/uri-helper.js'
33
34
  import analytics, { checkAnalyticsCookiesPage } from '../handlers/analytics-handler.js'
34
35
  import { welshEnabledAndApplied } from '../processors/page-language-helper.js'
36
+ import cancelRPAuthenticationhander from '../handlers/cancel-rp-authentication-handler.js'
35
37
 
36
38
  const gtmContainerIdOrNull = () => process.env.GTM_CONTAINER_ID || false
37
39
 
@@ -221,6 +223,11 @@ export default [
221
223
  })
222
224
  }
223
225
  },
226
+ {
227
+ method: 'GET',
228
+ path: CANCEL_RP_AUTHENTICATE.uri,
229
+ handler: cancelRPAuthenticationhander
230
+ },
224
231
  simpleView(ACCESSIBILITY_STATEMENT),
225
232
  simpleView(REFUND_POLICY),
226
233
  simpleView(OS_TERMS)
@@ -1,7 +1,11 @@
1
1
  import { OIDC_SIGNIN, OIDC_ACCOUNT_DISABLED, OIDC_ROLE_REQUIRED, CONTROLLER } from '../uri.js'
2
2
  import { signIn } from '../handlers/oidc-handler.js'
3
+ import cancelRPIdentify from '../pages/recurring-payments/cancel/identify/route.js'
4
+ import cancelRPDetails from '../pages/recurring-payments/cancel/details/route.js'
5
+ import cancelRPConfirm from '../pages/recurring-payments/cancel/confirm/route.js'
6
+ import cancelRPComplete from '../pages/recurring-payments/cancel/complete/route.js'
3
7
 
4
- export default [
8
+ const telesalesRoutes = [
5
9
  {
6
10
  method: ['POST'],
7
11
  path: OIDC_SIGNIN.uri,
@@ -26,3 +30,11 @@ export default [
26
30
  options: { auth: false }
27
31
  }
28
32
  ]
33
+
34
+ if (process.env.SHOW_CANCELLATION_JOURNEY === 'true') {
35
+ telesalesRoutes.push(...cancelRPIdentify)
36
+ telesalesRoutes.push(...cancelRPDetails)
37
+ telesalesRoutes.push(...cancelRPConfirm)
38
+ telesalesRoutes.push(...cancelRPComplete)
39
+ }
40
+ export default telesalesRoutes
package/src/uri.js CHANGED
@@ -62,6 +62,12 @@ export const ERROR_TESTING = { uri: '/buy/throw-error' }
62
62
  export const CHOOSE_PAYMENT = { uri: '/buy/choose-payment', page: 'choose-payment' }
63
63
  export const SET_UP_PAYMENT = { uri: '/buy/set-up-recurring-card-payment', page: 'set-up-payment' }
64
64
 
65
+ export const CANCEL_RP_IDENTIFY = { uri: '/buy/cancel-recurring-payment/identify', page: 'cancel-rp-identify' }
66
+ export const CANCEL_RP_AUTHENTICATE = { uri: '/buy/cancel-recurring-payment/authenticate' }
67
+ export const CANCEL_RP_DETAILS = { uri: '/buy/cancel-recurring-payment/details', page: 'cancel-rp-details' }
68
+ export const CANCEL_RP_CONFIRM = { uri: '/buy/cancel-recurring-payment/confirm', page: 'cancel-rp-confirm' }
69
+ export const CANCEL_RP_COMPLETE = { uri: '/buy/cancel-recurring-payment/complete', page: 'cancel-rp-complete' }
70
+
65
71
  /**
66
72
  * These are informational static pages
67
73
  */