@defra-fish/gafl-webapp-service 1.64.0-rc.8 → 1.65.0-rc.0
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.
- package/package.json +4 -4
- package/src/handlers/__tests__/cancel-recurring-payment-authentication-handler.spec.js +214 -0
- package/src/handlers/cancel-recurring-payment-authentication-handler.js +60 -0
- package/src/locales/cy.json +21 -2
- package/src/locales/en.json +21 -2
- package/src/pages/guidance/accessibility-statement.njk +5 -5
- package/src/pages/recurring-payments/cancel/details/__tests__/route.spec.js +131 -0
- package/src/pages/recurring-payments/cancel/details/cancel-rp-details.njk +57 -9
- package/src/pages/recurring-payments/cancel/details/route.js +22 -1
- package/src/pages/recurring-payments/cancel/identify/__tests__/route.spec.js +174 -0
- package/src/pages/recurring-payments/cancel/identify/cancel-rp-identify.njk +171 -4
- package/src/pages/recurring-payments/cancel/identify/route.js +51 -6
- package/src/processors/__tests__/recurring-payments-write-cache.spec.js +121 -0
- package/src/processors/recurring-payments-write-cache.js +16 -0
- package/src/routes/journey-definition.js +2 -1
- package/src/routes/misc-routes.js +1 -1
- package/src/handlers/__tests__/cancel-rp-authentication-handler.spec.js +0 -18
- package/src/handlers/cancel-rp-authentication-handler.js +0 -6
- package/src/pages/recurring-payments/cancel/details/__tests__/route.test.js +0 -106
- package/src/pages/recurring-payments/cancel/identify/__tests__/route.test.js +0 -106
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import pageRoute from '../../../../../routes/page-route.js'
|
|
2
|
+
import { CANCEL_RP_IDENTIFY } from '../../../../../uri.js'
|
|
3
|
+
import { addLanguageCodeToUri } from '../../../../../processors/uri-helper.js'
|
|
4
|
+
import { getData, validator } from '../route.js'
|
|
5
|
+
import { dateOfBirthValidator, getDateErrorFlags } from '../../../../../schema/validators/validators.js'
|
|
6
|
+
import { validation } from '@defra-fish/business-rules-lib'
|
|
7
|
+
import GetDataRedirect from '../../../../../handlers/get-data-redirect.js'
|
|
8
|
+
|
|
9
|
+
require('../route.js')
|
|
10
|
+
|
|
11
|
+
jest.mock('../../../../../routes/page-route.js')
|
|
12
|
+
jest.mock('../../../../../uri.js', () => ({
|
|
13
|
+
...jest.requireActual('../../../../../uri.js'),
|
|
14
|
+
CANCEL_RP_IDENTIFY: { page: 'cancel-rp identify page', uri: Symbol('cancel-rp identify uri') },
|
|
15
|
+
CANCEL_RP_AUTHENTICATE: { uri: 'cancel-rp-authenticate uri' }
|
|
16
|
+
}))
|
|
17
|
+
jest.mock('../../../../../processors/uri-helper.js')
|
|
18
|
+
jest.mock('../../../../../schema/validators/validators.js')
|
|
19
|
+
|
|
20
|
+
describe('cancel recurring payment identify route', () => {
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
jest.restoreAllMocks()
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('getData', () => {
|
|
26
|
+
const getMockRequest = (referenceNumber, pageGet = async () => ({})) => ({
|
|
27
|
+
cache: () => ({
|
|
28
|
+
helpers: {
|
|
29
|
+
transaction: {
|
|
30
|
+
getCurrentPermission: () => ({
|
|
31
|
+
referenceNumber
|
|
32
|
+
}),
|
|
33
|
+
setCurrentPermission: jest.fn()
|
|
34
|
+
},
|
|
35
|
+
page: {
|
|
36
|
+
getCurrentPermission: pageGet
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}),
|
|
40
|
+
i18n: {
|
|
41
|
+
getCatalog: () => [],
|
|
42
|
+
getLocales: () => []
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('passes correct page name when getting page cache', async () => {
|
|
47
|
+
const pageGet = jest.fn(() => ({}))
|
|
48
|
+
await getData(getMockRequest(undefined, pageGet))
|
|
49
|
+
expect(pageGet).toHaveBeenCalledWith(CANCEL_RP_IDENTIFY.page)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it.each([['09F6VF'], ['013AH6'], ['LK563F']])('returns referenceNumber when permission includes %s', async referenceNumber => {
|
|
53
|
+
const result = await getData(getMockRequest(referenceNumber))
|
|
54
|
+
expect(result.referenceNumber).toEqual(referenceNumber)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('throws redirect when permission number fails validation', async () => {
|
|
58
|
+
const spy = jest
|
|
59
|
+
.spyOn(validation.permission, 'permissionNumberUniqueComponentValidator')
|
|
60
|
+
.mockReturnValue({ validate: () => ({ error: true }) })
|
|
61
|
+
const request = getMockRequest('BAD123')
|
|
62
|
+
request.cache().helpers.transaction.setCurrentPermission = jest.fn()
|
|
63
|
+
await expect(getData(request)).rejects.toBeInstanceOf(GetDataRedirect)
|
|
64
|
+
spy.mockRestore()
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('adds return value of getErrorFlags to the page data', async () => {
|
|
68
|
+
const errorFlags = { unique: Symbol('error-flags') }
|
|
69
|
+
getDateErrorFlags.mockReturnValueOnce(errorFlags)
|
|
70
|
+
const result = await getData(getMockRequest())
|
|
71
|
+
expect(result).toEqual(expect.objectContaining(errorFlags))
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('passes error to getErrorFlags', async () => {
|
|
75
|
+
const error = Symbol('error')
|
|
76
|
+
await getData(getMockRequest(undefined, async () => ({ error })))
|
|
77
|
+
expect(getDateErrorFlags).toHaveBeenCalledWith(error)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it.each([
|
|
81
|
+
['full-date', 'object.missing'],
|
|
82
|
+
['day', 'any.required']
|
|
83
|
+
])('adds error details (%s: %s) to the page data', async (errorKey, errorValue) => {
|
|
84
|
+
const pageGet = async () => ({
|
|
85
|
+
error: { [errorKey]: errorValue }
|
|
86
|
+
})
|
|
87
|
+
const result = await getData(getMockRequest(undefined, pageGet))
|
|
88
|
+
expect(result.error).toEqual({ errorKey, errorValue })
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('omits error if there is no error', async () => {
|
|
92
|
+
const result = await getData(getMockRequest())
|
|
93
|
+
expect(result.error).toBeUndefined()
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
describe('pageRoute', () => {
|
|
98
|
+
it('passes CANCEL_RP_IDENTIFY.page as the first argument to pageRoute', () => {
|
|
99
|
+
expect(pageRoute.mock.calls[0][0]).toBe(CANCEL_RP_IDENTIFY.page)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('passes CANCEL_RP_IDENTIFY.uri as the second argument to pageRoute', () => {
|
|
103
|
+
expect(pageRoute.mock.calls[0][1]).toBe(CANCEL_RP_IDENTIFY.uri)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('calls pageRoute with validator, nextPage function, and getData', () => {
|
|
107
|
+
expect(pageRoute).toBeCalledWith(CANCEL_RP_IDENTIFY.page, CANCEL_RP_IDENTIFY.uri, validator, expect.any(Function), getData)
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
describe('page route next', () => {
|
|
112
|
+
const getNextPage = () => pageRoute.mock.calls[0][3]
|
|
113
|
+
|
|
114
|
+
it('passes a function', () => {
|
|
115
|
+
const nextPage = getNextPage()
|
|
116
|
+
expect(typeof nextPage).toBe('function')
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('calls addLanguageCodeToUri', () => {
|
|
120
|
+
const nextPage = getNextPage()
|
|
121
|
+
nextPage()
|
|
122
|
+
expect(addLanguageCodeToUri).toHaveBeenCalled()
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
it('passes request to addLanguageCodeToUri', () => {
|
|
126
|
+
const request = Symbol('request')
|
|
127
|
+
const nextPage = getNextPage()
|
|
128
|
+
nextPage(request)
|
|
129
|
+
expect(addLanguageCodeToUri).toHaveBeenCalledWith(request, expect.anything())
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
it('returns result of addLanguageCodeToUri', () => {
|
|
133
|
+
const expectedResult = Symbol('add language code to uri')
|
|
134
|
+
const nextPage = getNextPage()
|
|
135
|
+
addLanguageCodeToUri.mockReturnValueOnce(expectedResult)
|
|
136
|
+
expect(nextPage()).toBe(expectedResult)
|
|
137
|
+
})
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
describe('validator', () => {
|
|
141
|
+
const getMockPayload = (postcode = 'AA1 1AA', referenceNumber = 'A1B2C3') => ({
|
|
142
|
+
postcode,
|
|
143
|
+
referenceNumber
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
it('fails if dateOfBirthValidator throws', () => {
|
|
147
|
+
const expectedError = new Error('expected error')
|
|
148
|
+
dateOfBirthValidator.mockImplementationOnce(() => {
|
|
149
|
+
throw expectedError
|
|
150
|
+
})
|
|
151
|
+
expect(() => validator(getMockPayload())).toThrow(expectedError)
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it('passes if dateOfBirthValidator succeeds', () => {
|
|
155
|
+
expect(() => validator(getMockPayload())).not.toThrow()
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
it('passes payload to dateOfBirthValidator', () => {
|
|
159
|
+
const p = getMockPayload()
|
|
160
|
+
validator(p)
|
|
161
|
+
expect(dateOfBirthValidator).toHaveBeenCalledWith(p)
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
it('fails if permission number is invalid', () => {
|
|
165
|
+
jest.spyOn(validation.permission, 'permissionNumberUniqueComponentValidator').mockReturnValue({ validate: () => ({ error: 'bad' }) })
|
|
166
|
+
expect(() => validator({ referenceNumber: 'BAD', postcode: 'AA1 1AA' })).toThrow()
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
it('fails if postcode is invalid', () => {
|
|
170
|
+
jest.spyOn(validation.contact, 'createOverseasPostcodeValidator').mockReturnValue({ validate: () => ({ error: 'bad' }) })
|
|
171
|
+
expect(() => validator({ referenceNumber: 'ABC123', postcode: 'ZZZ' })).toThrow()
|
|
172
|
+
})
|
|
173
|
+
})
|
|
174
|
+
})
|
|
@@ -1,15 +1,175 @@
|
|
|
1
1
|
{% extends "layout.njk" %}
|
|
2
2
|
|
|
3
|
+
{% from "fieldset/macro.njk" import govukFieldset %}
|
|
3
4
|
{% from "button/macro.njk" import govukButton %}
|
|
4
5
|
{% from "page-title.njk" import pageTitle %}
|
|
6
|
+
{% from "date-input/macro.njk" import govukDateInput %}
|
|
7
|
+
{% from "input/macro.njk" import govukInput %}
|
|
8
|
+
{% from "error-summary.njk" import errorSummary %}
|
|
9
|
+
|
|
10
|
+
{% set title = mssgs.cancel_rp_identify_title %}
|
|
5
11
|
|
|
6
|
-
{% set title = mssgs.rp_cancel_identify_title %}
|
|
7
12
|
{% block pageTitle %}{{ pageTitle(title, error, mssgs) }}{% endblock %}
|
|
8
13
|
|
|
14
|
+
{%
|
|
15
|
+
set errorMap = {
|
|
16
|
+
'referenceNumber' : {
|
|
17
|
+
'string.empty': { text: mssgs.cancel_rp_identify_ref_number_error, ref: '#ref' },
|
|
18
|
+
'string.pattern.base': { text: mssgs.cancel_rp_identify_ref_pattern, ref: '#ref' }
|
|
19
|
+
},
|
|
20
|
+
'postcode': {
|
|
21
|
+
'string.empty': { ref: '#postcode', text: mssgs.cancel_rp_identify_postcode_error },
|
|
22
|
+
'string.pattern.base': { ref: '#postcode', text: mssgs.cancel_rp_identify_postcode_pattern }
|
|
23
|
+
},
|
|
24
|
+
'full-date': {
|
|
25
|
+
'object.missing': { ref: '#date-of-birth-day', text: mssgs.dob_error }
|
|
26
|
+
},
|
|
27
|
+
'day-and-month': {
|
|
28
|
+
'object.missing': { ref: '#date-of-birth-day', text: mssgs.dob_error_missing_day_and_month }
|
|
29
|
+
},
|
|
30
|
+
'day-and-year': {
|
|
31
|
+
'object.missing': { ref: '#date-of-birth-day', text: mssgs.dob_error_missing_day_and_year }
|
|
32
|
+
},
|
|
33
|
+
'month-and-year': {
|
|
34
|
+
'object.missing': { ref: '#date-of-birth-month', text: mssgs.dob_error_missing_month_and_year }
|
|
35
|
+
},
|
|
36
|
+
'day': {
|
|
37
|
+
'any.required': { ref: '#date-of-birth-day', text: mssgs.dob_error_missing_day }
|
|
38
|
+
},
|
|
39
|
+
'month': {
|
|
40
|
+
'any.required': { ref: '#date-of-birth-month', text: mssgs.dob_error_missing_month }
|
|
41
|
+
},
|
|
42
|
+
'year': {
|
|
43
|
+
'any.required': { ref: '#date-of-birth-year', text: mssgs.dob_error_missing_year }
|
|
44
|
+
},
|
|
45
|
+
'non-numeric': {
|
|
46
|
+
'number.base': { ref: '#date-of-birth-day', text: mssgs.dob_error_non_numeric }
|
|
47
|
+
},
|
|
48
|
+
'invalid-date': {
|
|
49
|
+
'any.custom': { ref: '#date-of-birth-day', text: mssgs.dob_error_date_real }
|
|
50
|
+
},
|
|
51
|
+
'date-range': {
|
|
52
|
+
'date.min': { ref: '#date-of-birth-day', text: mssgs.dob_error_year_min },
|
|
53
|
+
'date.max': { ref: '#date-of-birth-day', text: mssgs.dob_error_year_max }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
%}
|
|
57
|
+
|
|
58
|
+
{% set dateInputItems = [
|
|
59
|
+
{
|
|
60
|
+
label: mssgs.date_day,
|
|
61
|
+
name: "day",
|
|
62
|
+
classes: "govuk-input--width-2 govuk-input--error" if data.isDayError else "govuk-input--width-2",
|
|
63
|
+
value: payload['date-of-birth-day'],
|
|
64
|
+
attributes: { maxlength : 2 }
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
label: mssgs.date_month,
|
|
68
|
+
name: "month",
|
|
69
|
+
classes: "govuk-input--width-2 govuk-input--error" if data.isMonthError else "govuk-input--width-2",
|
|
70
|
+
value: payload['date-of-birth-month'],
|
|
71
|
+
attributes: { maxlength : 2 }
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
label: mssgs.date_year,
|
|
75
|
+
name: "year",
|
|
76
|
+
classes: "govuk-input--width-4 govuk-input--error" if data.isYearError else "govuk-input--width-4",
|
|
77
|
+
value: payload['date-of-birth-year'],
|
|
78
|
+
attributes: { maxlength : 4 }
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
%}
|
|
82
|
+
|
|
9
83
|
{% block content %}
|
|
10
84
|
<div class="govuk-grid-row">
|
|
11
|
-
|
|
12
|
-
|
|
85
|
+
<div class="govuk-grid-column-two-thirds">
|
|
86
|
+
{{ errorSummary(error, errorMap, mssgs.there_is_a_problem) }}
|
|
87
|
+
<form method="post" class="govuk-!-margin-bottom-6">
|
|
88
|
+
|
|
89
|
+
{% set legendHtml %}
|
|
90
|
+
<span class="govuk-caption-l">{{ mssgs.cancel_rp_identify_caption }}</span>
|
|
91
|
+
{{ title }}
|
|
92
|
+
{% endset %}
|
|
93
|
+
|
|
94
|
+
{% call govukFieldset({
|
|
95
|
+
describedBy: "ref-hint date-of-birth-hint postcode-hint",
|
|
96
|
+
legend: {
|
|
97
|
+
html: legendHtml,
|
|
98
|
+
classes: "govuk-fieldset__legend--l govuk-!-margin-bottom-3",
|
|
99
|
+
isPageHeading: true
|
|
100
|
+
}
|
|
101
|
+
}) %}
|
|
102
|
+
|
|
103
|
+
<p class="govuk-body-m">{{ mssgs.cancel_rp_identify_body }}</p>
|
|
104
|
+
|
|
105
|
+
{{ govukInput({
|
|
106
|
+
id: "ref",
|
|
107
|
+
name: "referenceNumber",
|
|
108
|
+
type: "text",
|
|
109
|
+
classes: "govuk-input--width-10",
|
|
110
|
+
errorMessage: { text: mssgs.cancel_rp_identify_ref_number_error } if error['referenceNumber'],
|
|
111
|
+
label: {
|
|
112
|
+
text: mssgs.cancel_rp_identify_ref_number,
|
|
113
|
+
classes: "govuk-!-font-weight-bold"
|
|
114
|
+
},
|
|
115
|
+
hint: {
|
|
116
|
+
text: mssgs.cancel_rp_identify_ref_number_hint
|
|
117
|
+
},
|
|
118
|
+
attributes: {
|
|
119
|
+
spellcheck: "false",
|
|
120
|
+
maxlength: "6"
|
|
121
|
+
},
|
|
122
|
+
value: payload.referenceNumber
|
|
123
|
+
}) }}
|
|
124
|
+
|
|
125
|
+
{{ govukDateInput({
|
|
126
|
+
id: "date-of-birth",
|
|
127
|
+
namePrefix: "date-of-birth",
|
|
128
|
+
items: dateInputItems,
|
|
129
|
+
fieldset: {
|
|
130
|
+
legend: {
|
|
131
|
+
text: mssgs.cancel_rp_identify_dob,
|
|
132
|
+
isPageHeading: false,
|
|
133
|
+
classes: "govuk-!-font-weight-bold govuk-label"
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
errorMessage: ({
|
|
137
|
+
text: errorMap[data.error.errorKey][data.error.errorValue].text }
|
|
138
|
+
if data.error and data.error.errorKey in [
|
|
139
|
+
'full-date',
|
|
140
|
+
'day-and-month',
|
|
141
|
+
'day-and-year',
|
|
142
|
+
'month-and-year',
|
|
143
|
+
'day',
|
|
144
|
+
'month',
|
|
145
|
+
'year',
|
|
146
|
+
'non-numeric',
|
|
147
|
+
'invalid-date',
|
|
148
|
+
'date-range'
|
|
149
|
+
]
|
|
150
|
+
),
|
|
151
|
+
hint: {
|
|
152
|
+
text: mssgs.cancel_rp_identify_dob_hint
|
|
153
|
+
}
|
|
154
|
+
}) }}
|
|
155
|
+
|
|
156
|
+
{{ govukInput({
|
|
157
|
+
label: {
|
|
158
|
+
text: mssgs.cancel_rp_identify_postcode,
|
|
159
|
+
classes: "govuk-!-font-weight-bold"
|
|
160
|
+
},
|
|
161
|
+
id: "postcode",
|
|
162
|
+
name: "postcode",
|
|
163
|
+
hint: { text: mssgs.cancel_rp_identify_postcode_hint },
|
|
164
|
+
value: payload['postcode'],
|
|
165
|
+
autocomplete: 'postal-code',
|
|
166
|
+
classes: "govuk-input--width-10",
|
|
167
|
+
attributes: { maxlength: 10 },
|
|
168
|
+
errorMessage: { text: mssgs.cancel_rp_identify_postcode_error } if error['postcode']
|
|
169
|
+
}) }}
|
|
170
|
+
|
|
171
|
+
{% endcall %}
|
|
172
|
+
|
|
13
173
|
{{ govukButton({
|
|
14
174
|
attributes: { id: 'continue' },
|
|
15
175
|
preventDoubleClick: true,
|
|
@@ -21,4 +181,11 @@
|
|
|
21
181
|
</form>
|
|
22
182
|
</div>
|
|
23
183
|
</div>
|
|
24
|
-
{% endblock %}
|
|
184
|
+
{% endblock %}
|
|
185
|
+
|
|
186
|
+
{% block bodyEnd %}
|
|
187
|
+
<script type="module" nonce="{{ nonce }}">
|
|
188
|
+
import { initAll } from '/public/javascript/govuk-frontend-min.js'
|
|
189
|
+
initAll()
|
|
190
|
+
</script>
|
|
191
|
+
{% endblock %}
|
|
@@ -1,13 +1,58 @@
|
|
|
1
|
-
import pageRoute from '../../../../routes/page-route.js'
|
|
2
1
|
import { CANCEL_RP_AUTHENTICATE, CANCEL_RP_IDENTIFY } from '../../../../uri.js'
|
|
2
|
+
import pageRoute from '../../../../routes/page-route.js'
|
|
3
|
+
import Joi from 'joi'
|
|
4
|
+
import { validation } from '@defra-fish/business-rules-lib'
|
|
3
5
|
import { addLanguageCodeToUri } from '../../../../processors/uri-helper.js'
|
|
6
|
+
import GetDataRedirect from '../../../../handlers/get-data-redirect.js'
|
|
7
|
+
import { dateOfBirthValidator, getDateErrorFlags } from '../../../../schema/validators/validators.js'
|
|
8
|
+
|
|
9
|
+
export const getData = async request => {
|
|
10
|
+
const permission = await request.cache().helpers.transaction.getCurrentPermission()
|
|
11
|
+
const page = await request.cache().helpers.page.getCurrentPermission(CANCEL_RP_IDENTIFY.page)
|
|
12
|
+
|
|
13
|
+
if (permission.referenceNumber) {
|
|
14
|
+
const validatePermissionNumber = validation.permission
|
|
15
|
+
.permissionNumberUniqueComponentValidator(Joi)
|
|
16
|
+
.validate(permission.referenceNumber)
|
|
17
|
+
if (validatePermissionNumber.error) {
|
|
18
|
+
await request.cache().helpers.transaction.setCurrentPermission({ referenceNumber: null })
|
|
19
|
+
throw new GetDataRedirect(addLanguageCodeToUri(request, CANCEL_RP_IDENTIFY.uri))
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const pageData = {
|
|
24
|
+
referenceNumber: permission.referenceNumber,
|
|
25
|
+
...getDateErrorFlags(page?.error)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (page?.error) {
|
|
29
|
+
const [errorKey] = Object.keys(page.error)
|
|
30
|
+
const errorValue = page.error[errorKey]
|
|
31
|
+
pageData.error = { errorKey, errorValue }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return pageData
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const validator = payload => {
|
|
38
|
+
dateOfBirthValidator(payload)
|
|
39
|
+
|
|
40
|
+
Joi.assert(
|
|
41
|
+
{
|
|
42
|
+
postcode: payload.postcode,
|
|
43
|
+
referenceNumber: payload.referenceNumber
|
|
44
|
+
},
|
|
45
|
+
Joi.object({
|
|
46
|
+
referenceNumber: validation.permission.permissionNumberUniqueComponentValidator(Joi),
|
|
47
|
+
postcode: validation.contact.createOverseasPostcodeValidator(Joi)
|
|
48
|
+
}).options({ abortEarly: false })
|
|
49
|
+
)
|
|
50
|
+
}
|
|
4
51
|
|
|
5
52
|
export default pageRoute(
|
|
6
53
|
CANCEL_RP_IDENTIFY.page,
|
|
7
54
|
CANCEL_RP_IDENTIFY.uri,
|
|
8
|
-
|
|
9
|
-
request =>
|
|
10
|
-
|
|
11
|
-
},
|
|
12
|
-
() => {}
|
|
55
|
+
validator,
|
|
56
|
+
request => addLanguageCodeToUri(request, CANCEL_RP_AUTHENTICATE.uri),
|
|
57
|
+
getData
|
|
13
58
|
)
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { setupCancelRecurringPaymentCacheFromAuthResult } from '../recurring-payments-write-cache.js'
|
|
2
|
+
|
|
3
|
+
describe('setUpCancelRecurringPaymentCacheFromAuthenticationResult', () => {
|
|
4
|
+
const getSampleAuthResult = overrides => {
|
|
5
|
+
const defaults = {
|
|
6
|
+
referenceNumber: '23270624-2WC3FSD-ABNCY4',
|
|
7
|
+
endDate: '2024-12-31',
|
|
8
|
+
licensee: { firstName: 'Brenin', lastName: 'Pysgotwr' },
|
|
9
|
+
permit: { description: 'Coarse 6 month 15 Rod Licence (Half)' },
|
|
10
|
+
recurringPayment: { lastDigitsCardNumbers: '5678' }
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
permission: {
|
|
15
|
+
referenceNumber: overrides.referenceNumber || defaults.referenceNumber,
|
|
16
|
+
endDate: overrides.endDate || defaults.endDate,
|
|
17
|
+
licensee: {
|
|
18
|
+
...defaults.licensee,
|
|
19
|
+
...(overrides.licensee ? overrides.licensee : {})
|
|
20
|
+
},
|
|
21
|
+
permit: {
|
|
22
|
+
...defaults.permit,
|
|
23
|
+
...(overrides.permit ? overrides.permit : {})
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
recurringPayment: {
|
|
27
|
+
...defaults.recurringPayment,
|
|
28
|
+
...(overrides.recurringPayment ? overrides.recurringPayment : {})
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const getSampleRequest = setCurrentPermission => ({
|
|
34
|
+
cache: () => ({
|
|
35
|
+
helpers: {
|
|
36
|
+
transaction: {
|
|
37
|
+
setCurrentPermission
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
describe('permission caching', () => {
|
|
44
|
+
it.each([
|
|
45
|
+
['referenceNumber', '23270624-2WC3FSD-ABNCY4'],
|
|
46
|
+
['endDate', '2024-12-31'],
|
|
47
|
+
['licensee', { firstName: 'John', lastName: 'Bull' }],
|
|
48
|
+
['permit', { description: 'Coarse 12 month 2 Rod Licence (Full)' }]
|
|
49
|
+
])("Adds permission %s, value '%s', to transaction cache", async (fieldName, fieldValue) => {
|
|
50
|
+
const setCurrentPermission = jest.fn()
|
|
51
|
+
const mockRequest = getSampleRequest(setCurrentPermission)
|
|
52
|
+
const authResult = getSampleAuthResult({ [fieldName]: fieldValue })
|
|
53
|
+
|
|
54
|
+
await setupCancelRecurringPaymentCacheFromAuthResult(mockRequest, authResult)
|
|
55
|
+
|
|
56
|
+
expect(setCurrentPermission).toHaveBeenCalledWith(
|
|
57
|
+
expect.objectContaining({
|
|
58
|
+
permission: expect.objectContaining({
|
|
59
|
+
[fieldName]: fieldValue
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it.each([
|
|
66
|
+
['licensee', { anotherProperty: 'Should not be there' }],
|
|
67
|
+
['permit', { altProp: 'Should not be here' }]
|
|
68
|
+
])('Omits extraneous properties from permission %s', async (fieldName, fieldValue) => {
|
|
69
|
+
const setCurrentPermission = jest.fn()
|
|
70
|
+
const mockRequest = getSampleRequest(setCurrentPermission)
|
|
71
|
+
|
|
72
|
+
const authResult = getSampleAuthResult({ [fieldName]: fieldValue })
|
|
73
|
+
|
|
74
|
+
await setupCancelRecurringPaymentCacheFromAuthResult(mockRequest, authResult)
|
|
75
|
+
|
|
76
|
+
expect(setCurrentPermission).toHaveBeenCalledWith(
|
|
77
|
+
expect.objectContaining({
|
|
78
|
+
permission: expect.not.objectContaining({
|
|
79
|
+
[fieldName]: fieldValue
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
)
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
describe('recurring payment caching', () => {
|
|
87
|
+
it('adds recurring payment payment card number last digits to transaction cache', async () => {
|
|
88
|
+
const setCurrentPermission = jest.fn()
|
|
89
|
+
const mockRequest = getSampleRequest(setCurrentPermission)
|
|
90
|
+
|
|
91
|
+
const authResult = getSampleAuthResult({ recurringPayment: { lastDigitsCardNumbers: '1234' } })
|
|
92
|
+
|
|
93
|
+
await setupCancelRecurringPaymentCacheFromAuthResult(mockRequest, authResult)
|
|
94
|
+
|
|
95
|
+
expect(setCurrentPermission).toHaveBeenCalledWith(
|
|
96
|
+
expect.objectContaining({
|
|
97
|
+
recurringPayment: expect.objectContaining({
|
|
98
|
+
lastDigitsCardNumbers: '1234'
|
|
99
|
+
})
|
|
100
|
+
})
|
|
101
|
+
)
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
it('omits extraneous properties from recurring payment', async () => {
|
|
105
|
+
const setCurrentPermission = jest.fn()
|
|
106
|
+
const mockRequest = getSampleRequest(setCurrentPermission)
|
|
107
|
+
|
|
108
|
+
const authResult = getSampleAuthResult({ recurringPayment: { someOtherProp: 'Should not be here' } })
|
|
109
|
+
|
|
110
|
+
await setupCancelRecurringPaymentCacheFromAuthResult(mockRequest, authResult)
|
|
111
|
+
|
|
112
|
+
expect(setCurrentPermission).toHaveBeenCalledWith(
|
|
113
|
+
expect.objectContaining({
|
|
114
|
+
recurringPayment: expect.not.objectContaining({
|
|
115
|
+
someOtherProp: 'Should not be here'
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
)
|
|
119
|
+
})
|
|
120
|
+
})
|
|
121
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const setupCancelRecurringPaymentCacheFromAuthResult = async (request, authenticationResult) => {
|
|
2
|
+
const { permission, recurringPayment } = authenticationResult
|
|
3
|
+
const { referenceNumber, endDate, licensee, permit } = permission
|
|
4
|
+
|
|
5
|
+
await request.cache().helpers.transaction.setCurrentPermission({
|
|
6
|
+
permission: {
|
|
7
|
+
referenceNumber,
|
|
8
|
+
endDate,
|
|
9
|
+
licensee: { firstName: licensee.firstName, lastName: licensee.lastName },
|
|
10
|
+
permit: { description: permit.description }
|
|
11
|
+
},
|
|
12
|
+
recurringPayment: {
|
|
13
|
+
lastDigitsCardNumbers: recurringPayment.lastDigitsCardNumbers
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
}
|
|
@@ -33,7 +33,7 @@ import authenticationHandler from '../handlers/authentication-handler.js'
|
|
|
33
33
|
import { addLanguageCodeToUri } from '../processors/uri-helper.js'
|
|
34
34
|
import analytics, { checkAnalyticsCookiesPage } from '../handlers/analytics-handler.js'
|
|
35
35
|
import { welshEnabledAndApplied } from '../processors/page-language-helper.js'
|
|
36
|
-
import cancelRPAuthenticationhander from '../handlers/cancel-
|
|
36
|
+
import cancelRPAuthenticationhander from '../handlers/cancel-recurring-payment-authentication-handler.js'
|
|
37
37
|
|
|
38
38
|
const gtmContainerIdOrNull = () => process.env.GTM_CONTAINER_ID || false
|
|
39
39
|
|
|
@@ -1,18 +0,0 @@
|
|
|
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
|
-
})
|