@defra-fish/gafl-webapp-service 1.55.0-rc.6 → 1.55.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__/agreed-handler-recurring-payments.spec.js +40 -94
- package/src/handlers/agreed-handler.js +5 -13
- package/src/locales/cy.json +3 -3
- package/src/locales/en.json +3 -3
- package/src/pages/summary/licence-summary/__tests__/__snapshots__/route.spec.js.snap +0 -121
- package/src/pages/summary/licence-summary/__tests__/route.spec.js +11 -12
- package/src/pages/summary/licence-summary/route.js +6 -7
- package/src/processors/__tests__/api-transaction.spec.js +1 -9
- package/src/processors/__tests__/payment.spec.js +8 -33
- package/src/processors/api-transaction.js +2 -3
- package/src/processors/payment.js +3 -7
- package/src/services/payment/__test__/govuk-pay-service.spec.js +1 -253
- package/src/services/payment/govuk-pay-service.js +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defra-fish/gafl-webapp-service",
|
|
3
|
-
"version": "1.55.0
|
|
3
|
+
"version": "1.55.0",
|
|
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.55.0
|
|
40
|
-
"@defra-fish/connectors-lib": "1.55.0
|
|
39
|
+
"@defra-fish/business-rules-lib": "1.55.0",
|
|
40
|
+
"@defra-fish/connectors-lib": "1.55.0",
|
|
41
41
|
"@defra/hapi-gapi": "^2.0.0",
|
|
42
42
|
"@hapi/boom": "^9.1.2",
|
|
43
43
|
"@hapi/catbox-redis": "^6.0.2",
|
|
@@ -80,5 +80,5 @@
|
|
|
80
80
|
"./gafl-jest-matchers.js"
|
|
81
81
|
]
|
|
82
82
|
},
|
|
83
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "3405322b81a2016ba22e530de8d096a49be0bea4"
|
|
84
84
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { salesApi } from '@defra-fish/connectors-lib'
|
|
2
2
|
import { COMPLETION_STATUS, RECURRING_PAYMENT } from '../../constants.js'
|
|
3
3
|
import agreedHandler from '../agreed-handler.js'
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { prepareRecurringPayment } from '../../processors/payment.js'
|
|
5
|
+
import { sendRecurringPayment } from '../../services/payment/govuk-pay-service.js'
|
|
6
6
|
import { prepareApiTransactionPayload } from '../../processors/api-transaction.js'
|
|
7
7
|
import { v4 as uuidv4 } from 'uuid'
|
|
8
8
|
import db from 'debug'
|
|
@@ -10,13 +10,7 @@ import db from 'debug'
|
|
|
10
10
|
jest.mock('@defra-fish/connectors-lib')
|
|
11
11
|
jest.mock('../../processors/payment.js')
|
|
12
12
|
jest.mock('../../services/payment/govuk-pay-service.js', () => ({
|
|
13
|
-
sendPayment: jest.fn(
|
|
14
|
-
payment_id: 'payment-id-1',
|
|
15
|
-
_links: {
|
|
16
|
-
next_url: { href: 'next-url' },
|
|
17
|
-
self: { href: 'self-url' }
|
|
18
|
-
}
|
|
19
|
-
})),
|
|
13
|
+
sendPayment: jest.fn(),
|
|
20
14
|
getPaymentStatus: jest.fn(),
|
|
21
15
|
sendRecurringPayment: jest.fn(() => ({ agreementId: 'agr-eem-ent-id1' }))
|
|
22
16
|
}))
|
|
@@ -38,12 +32,12 @@ describe('The agreed handler', () => {
|
|
|
38
32
|
})
|
|
39
33
|
beforeEach(jest.clearAllMocks)
|
|
40
34
|
|
|
41
|
-
const getMockRequest = (
|
|
35
|
+
const getMockRequest = (overrides = {}) => ({
|
|
42
36
|
cache: () => ({
|
|
43
37
|
helpers: {
|
|
44
38
|
transaction: {
|
|
45
39
|
get: async () => ({ cost: 0 }),
|
|
46
|
-
set:
|
|
40
|
+
set: async () => {}
|
|
47
41
|
},
|
|
48
42
|
status: {
|
|
49
43
|
get: async () => ({
|
|
@@ -60,7 +54,6 @@ describe('The agreed handler', () => {
|
|
|
60
54
|
})
|
|
61
55
|
|
|
62
56
|
const getRequestToolkit = () => ({
|
|
63
|
-
redirect: jest.fn(),
|
|
64
57
|
redirectWithLanguageCode: jest.fn()
|
|
65
58
|
})
|
|
66
59
|
|
|
@@ -68,20 +61,18 @@ describe('The agreed handler', () => {
|
|
|
68
61
|
it('sends the request and transaction to prepare the recurring payment', async () => {
|
|
69
62
|
const transaction = { cost: 0 }
|
|
70
63
|
const mockRequest = getMockRequest({
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
set: () => {}
|
|
75
|
-
}
|
|
64
|
+
transaction: {
|
|
65
|
+
get: async () => transaction,
|
|
66
|
+
set: () => {}
|
|
76
67
|
}
|
|
77
68
|
})
|
|
78
69
|
await agreedHandler(mockRequest, getRequestToolkit())
|
|
79
|
-
expect(
|
|
70
|
+
expect(prepareRecurringPayment).toHaveBeenCalledWith(mockRequest, transaction)
|
|
80
71
|
})
|
|
81
72
|
|
|
82
73
|
it('adds a v4 guid to the transaction as an id', async () => {
|
|
83
74
|
let transactionPayload = null
|
|
84
|
-
|
|
75
|
+
prepareRecurringPayment.mockImplementationOnce((_p1, tp) => {
|
|
85
76
|
transactionPayload = { ...tp }
|
|
86
77
|
})
|
|
87
78
|
const v4guid = Symbol('v4guid')
|
|
@@ -99,73 +90,46 @@ describe('The agreed handler', () => {
|
|
|
99
90
|
expect(transactionPayload.id).toBe(v4guid)
|
|
100
91
|
})
|
|
101
92
|
|
|
102
|
-
it('
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
describe('when there is a cost and recurringAgreement status is set to true', () => {
|
|
110
|
-
beforeEach(() => {
|
|
111
|
-
salesApi.createTransaction.mockResolvedValueOnce({
|
|
112
|
-
id: 'transaction-id-1',
|
|
113
|
-
cost: 100
|
|
114
|
-
})
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
it('calls preparePayment', async () => {
|
|
118
|
-
const transaction = { id: Symbol('transaction') }
|
|
119
|
-
const request = getMockRequest({
|
|
120
|
-
overrides: {
|
|
121
|
-
transaction: {
|
|
122
|
-
get: async () => transaction,
|
|
123
|
-
set: () => {}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
})
|
|
127
|
-
const toolkit = getRequestToolkit()
|
|
128
|
-
|
|
129
|
-
await agreedHandler(request, toolkit)
|
|
130
|
-
expect(preparePayment).toHaveBeenCalledWith(request, transaction)
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
it('calls sendPayment with recurring as true', async () => {
|
|
134
|
-
const preparedPayment = Symbol('preparedPayment')
|
|
135
|
-
preparePayment.mockReturnValueOnce(preparedPayment)
|
|
136
|
-
|
|
137
|
-
await agreedHandler(getMockRequest(), getRequestToolkit())
|
|
138
|
-
expect(sendPayment).toHaveBeenCalledWith(preparedPayment, true)
|
|
93
|
+
it("doesn't overwrite transaction id if one is already set", async () => {
|
|
94
|
+
const setTransaction = jest.fn()
|
|
95
|
+
const transactionId = 'abc-123-def-456'
|
|
96
|
+
uuidv4.mockReturnValue('def-789-ghi-012')
|
|
97
|
+
salesApi.finaliseTransaction.mockReturnValueOnce({
|
|
98
|
+
permissions: []
|
|
139
99
|
})
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const transaction = { id: '123', payment: { payment_id: id } }
|
|
144
|
-
const request = getMockRequest({
|
|
145
|
-
overrides: {
|
|
146
|
-
transaction: {
|
|
147
|
-
get: async () => transaction,
|
|
148
|
-
set: () => {}
|
|
149
|
-
},
|
|
100
|
+
const mockRequest = {
|
|
101
|
+
cache: () => ({
|
|
102
|
+
helpers: {
|
|
150
103
|
status: {
|
|
151
104
|
get: async () => ({
|
|
152
105
|
[COMPLETION_STATUS.agreed]: true,
|
|
153
|
-
[COMPLETION_STATUS.posted]:
|
|
154
|
-
[COMPLETION_STATUS.finalised]:
|
|
155
|
-
[RECURRING_PAYMENT]:
|
|
156
|
-
[COMPLETION_STATUS.paymentCreated]: true
|
|
106
|
+
[COMPLETION_STATUS.posted]: true,
|
|
107
|
+
[COMPLETION_STATUS.finalised]: false,
|
|
108
|
+
[RECURRING_PAYMENT]: false
|
|
157
109
|
}),
|
|
158
110
|
set: () => {}
|
|
111
|
+
},
|
|
112
|
+
transaction: {
|
|
113
|
+
get: async () => ({ cost: 0, id: transactionId }),
|
|
114
|
+
set: setTransaction
|
|
159
115
|
}
|
|
160
116
|
}
|
|
161
117
|
})
|
|
162
|
-
|
|
118
|
+
}
|
|
163
119
|
|
|
164
|
-
|
|
120
|
+
await agreedHandler(mockRequest, getRequestToolkit())
|
|
165
121
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
122
|
+
expect(salesApi.finaliseTransaction).toHaveBeenCalledWith(
|
|
123
|
+
transactionId,
|
|
124
|
+
undefined // prepareApiFinalisationPayload has no mocked return value
|
|
125
|
+
)
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('sends a recurring payment creation request to Gov.UK Pay', async () => {
|
|
129
|
+
const preparedPayment = Symbol('preparedPayment')
|
|
130
|
+
prepareRecurringPayment.mockResolvedValueOnce(preparedPayment)
|
|
131
|
+
await agreedHandler(getMockRequest(), getRequestToolkit())
|
|
132
|
+
expect(sendRecurringPayment).toHaveBeenCalledWith(preparedPayment)
|
|
169
133
|
})
|
|
170
134
|
|
|
171
135
|
// this doesn't really belong here, but until the other agreed handler tests are refactored to
|
|
@@ -176,7 +140,7 @@ describe('The agreed handler', () => {
|
|
|
176
140
|
|
|
177
141
|
await agreedHandler(getMockRequest(), getRequestToolkit())
|
|
178
142
|
|
|
179
|
-
expect(prepareApiTransactionPayload).toHaveBeenCalledWith(expect.any(Object), v4guid
|
|
143
|
+
expect(prepareApiTransactionPayload).toHaveBeenCalledWith(expect.any(Object), v4guid)
|
|
180
144
|
})
|
|
181
145
|
|
|
182
146
|
it.each(['zxy-098-wvu-765', '467482f1-099d-403d-b6b3-8db7e70d19e3'])(
|
|
@@ -194,23 +158,5 @@ describe('The agreed handler', () => {
|
|
|
194
158
|
expect(debugMock).toHaveBeenCalledWith(`Created agreement with id ${agreement_id}`)
|
|
195
159
|
}
|
|
196
160
|
)
|
|
197
|
-
|
|
198
|
-
it.each(['zxy-098-wvu-765', '467482f1-099d-403d-b6b3-8db7e70d19e3'])(
|
|
199
|
-
"assigns agreement id '%s' to the transaction when recurring payment agreement created",
|
|
200
|
-
async agreementId => {
|
|
201
|
-
const mockTransactionCacheSet = jest.fn()
|
|
202
|
-
sendRecurringPayment.mockResolvedValueOnce({
|
|
203
|
-
agreement_id: agreementId
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
await agreedHandler(getMockRequest({ transactionSet: mockTransactionCacheSet }), getRequestToolkit())
|
|
207
|
-
|
|
208
|
-
expect(mockTransactionCacheSet).toHaveBeenCalledWith(
|
|
209
|
-
expect.objectContaining({
|
|
210
|
-
agreementId
|
|
211
|
-
})
|
|
212
|
-
)
|
|
213
|
-
}
|
|
214
|
-
)
|
|
215
161
|
})
|
|
216
162
|
})
|
|
@@ -14,7 +14,7 @@ import db from 'debug'
|
|
|
14
14
|
import { salesApi } from '@defra-fish/connectors-lib'
|
|
15
15
|
import { prepareApiTransactionPayload, prepareApiFinalisationPayload } from '../processors/api-transaction.js'
|
|
16
16
|
import { sendPayment, getPaymentStatus, sendRecurringPayment } from '../services/payment/govuk-pay-service.js'
|
|
17
|
-
import { preparePayment,
|
|
17
|
+
import { preparePayment, prepareRecurringPayment } from '../processors/payment.js'
|
|
18
18
|
import { COMPLETION_STATUS, RECURRING_PAYMENT } from '../constants.js'
|
|
19
19
|
import { ORDER_COMPLETE, PAYMENT_CANCELLED, PAYMENT_FAILED } from '../uri.js'
|
|
20
20
|
import { PAYMENT_JOURNAL_STATUS_CODES, GOVUK_PAY_ERROR_STATUS_CODES } from '@defra-fish/business-rules-lib'
|
|
@@ -29,7 +29,7 @@ const debug = db('webapp:agreed-handler')
|
|
|
29
29
|
* @returns {Promise<*>}
|
|
30
30
|
*/
|
|
31
31
|
const sendToSalesApi = async (request, transaction, status) => {
|
|
32
|
-
const apiTransactionPayload = await prepareApiTransactionPayload(request, transaction.id
|
|
32
|
+
const apiTransactionPayload = await prepareApiTransactionPayload(request, transaction.id)
|
|
33
33
|
let response
|
|
34
34
|
try {
|
|
35
35
|
response = await salesApi.createTransaction(apiTransactionPayload)
|
|
@@ -63,7 +63,7 @@ const createRecurringPayment = async (request, transaction, status) => {
|
|
|
63
63
|
/*
|
|
64
64
|
* Prepare the payment payload
|
|
65
65
|
*/
|
|
66
|
-
const preparedPayment = await
|
|
66
|
+
const preparedPayment = await prepareRecurringPayment(request, transaction)
|
|
67
67
|
|
|
68
68
|
/*
|
|
69
69
|
* Send the prepared payment to the GOV.UK pay API using the connector
|
|
@@ -72,11 +72,7 @@ const createRecurringPayment = async (request, transaction, status) => {
|
|
|
72
72
|
|
|
73
73
|
debug(`Created agreement with id ${paymentResponse.agreement_id}`)
|
|
74
74
|
status[COMPLETION_STATUS.recurringAgreement] = true
|
|
75
|
-
|
|
76
|
-
transaction.agreementId = paymentResponse.agreement_id
|
|
77
|
-
|
|
78
75
|
await request.cache().helpers.status.set(status)
|
|
79
|
-
await request.cache().helpers.transaction.set(transaction)
|
|
80
76
|
}
|
|
81
77
|
|
|
82
78
|
/**
|
|
@@ -92,8 +88,6 @@ const createRecurringPayment = async (request, transaction, status) => {
|
|
|
92
88
|
* @returns {Promise<void>}
|
|
93
89
|
*/
|
|
94
90
|
const createPayment = async (request, transaction, status) => {
|
|
95
|
-
const recurring = status && status[COMPLETION_STATUS.recurringAgreement] === true
|
|
96
|
-
|
|
97
91
|
/*
|
|
98
92
|
* Prepare the payment payload
|
|
99
93
|
*/
|
|
@@ -102,7 +96,7 @@ const createPayment = async (request, transaction, status) => {
|
|
|
102
96
|
/*
|
|
103
97
|
* Send the prepared payment to the GOV.UK pay API using the connector
|
|
104
98
|
*/
|
|
105
|
-
const paymentResponse = await sendPayment(preparedPayment
|
|
99
|
+
const paymentResponse = await sendPayment(preparedPayment)
|
|
106
100
|
|
|
107
101
|
/*
|
|
108
102
|
* Used by the payment mop up job, create the payment journal entry which is removed when the user completes the journey
|
|
@@ -149,12 +143,10 @@ const createPayment = async (request, transaction, status) => {
|
|
|
149
143
|
* @returns {Promise<void>}
|
|
150
144
|
*/
|
|
151
145
|
const processPayment = async (request, transaction, status) => {
|
|
152
|
-
const recurring = status && status[COMPLETION_STATUS.recurringAgreement] === true
|
|
153
|
-
|
|
154
146
|
/*
|
|
155
147
|
* Get the payment status
|
|
156
148
|
*/
|
|
157
|
-
const { state } = await getPaymentStatus(transaction.payment.payment_id
|
|
149
|
+
const { state } = await getPaymentStatus(transaction.payment.payment_id)
|
|
158
150
|
|
|
159
151
|
if (!state.finished) {
|
|
160
152
|
throw Boom.forbidden('Attempt to access the agreed handler during payment journey')
|
package/src/locales/cy.json
CHANGED
|
@@ -466,11 +466,11 @@
|
|
|
466
466
|
"licence_type_payment_edge_case": "Mae’n rhaid i chi gwblhau eich taliad cyn 11:30pm ar 31 Mawrth 2024 i dalu’r pris a ddangosir",
|
|
467
467
|
"licence_type_radio_salmon_hint": "Mae'n cynnwys brithyllod a physgod bras (hyd at 3 gwialen)",
|
|
468
468
|
"licence_type_radio_salmon": "Eogiaid a brithyllod y môr",
|
|
469
|
-
"licence_type_radio_salmon_payment_summary": "
|
|
469
|
+
"licence_type_radio_salmon_payment_summary": "eogiaid a brithyllod y môr",
|
|
470
470
|
"licence_type_radio_trout_three_rod": "Brithyllod a physgod bras (hyd at 3 gwialen)",
|
|
471
|
-
"licence_type_radio_trout_three_rod_payment_summary": "
|
|
471
|
+
"licence_type_radio_trout_three_rod_payment_summary": "brithyllod a physgod bras (hyd at 3 gwialen)",
|
|
472
472
|
"licence_type_radio_trout_two_rod": "Brithyllod a physgod bras (hyd at 2 wialen)",
|
|
473
|
-
"licence_type_radio_trout_two_rod_payment_summary": "
|
|
473
|
+
"licence_type_radio_trout_two_rod_payment_summary": "brithyllod a physgod bras (hyd at 2 wialen)",
|
|
474
474
|
"licence_type_rules": "rheolau pysgota â gwialen (yn agor ar dudalen newydd)",
|
|
475
475
|
"licence_type_salmon_acr_note_1": "Yn ôl y gyfraith, mae'n rhaid i chi roi gwybod am ",
|
|
476
476
|
"licence_type_salmon_acr_note_2": " ffurflen daliadau (yn agor ar dudalen newydd)",
|
package/src/locales/en.json
CHANGED
|
@@ -466,11 +466,11 @@
|
|
|
466
466
|
"licence_type_payment_edge_case": "You must complete payment before 11:30pm on 31 March 2024 to get the price shown",
|
|
467
467
|
"licence_type_radio_salmon_hint": "Includes trout and coarse (up to 3 rods)",
|
|
468
468
|
"licence_type_radio_salmon": "Salmon and sea trout",
|
|
469
|
-
"licence_type_radio_salmon_payment_summary": "
|
|
469
|
+
"licence_type_radio_salmon_payment_summary": "salmon and sea trout",
|
|
470
470
|
"licence_type_radio_trout_three_rod": "Trout and coarse (up to 3 rods)",
|
|
471
|
-
"licence_type_radio_trout_three_rod_payment_summary": "
|
|
471
|
+
"licence_type_radio_trout_three_rod_payment_summary": "trout and coarse (up to 3 rods)",
|
|
472
472
|
"licence_type_radio_trout_two_rod": "Trout and coarse (up to 2 rods)",
|
|
473
|
-
"licence_type_radio_trout_two_rod_payment_summary": "
|
|
473
|
+
"licence_type_radio_trout_two_rod_payment_summary": "trout and coarse (up to 2 rods)",
|
|
474
474
|
"licence_type_rules": "rod fishing rules (opens in new tab)",
|
|
475
475
|
"licence_type_salmon_acr_note_1": "Licence holders must by law ",
|
|
476
476
|
"licence_type_salmon_acr_note_2": " report a catch return (opens in new tab)",
|
|
@@ -246,127 +246,6 @@ Array [
|
|
|
246
246
|
]
|
|
247
247
|
`;
|
|
248
248
|
|
|
249
|
-
exports[`licence-summary > route licence summary rows creates licence summary name rows for 1 year new three rod licence 1`] = `
|
|
250
|
-
Array [
|
|
251
|
-
Object {
|
|
252
|
-
"actions": Object {
|
|
253
|
-
"items": Array [
|
|
254
|
-
Object {
|
|
255
|
-
"attributes": Object {
|
|
256
|
-
"id": "change-name",
|
|
257
|
-
},
|
|
258
|
-
"href": "/buy/name",
|
|
259
|
-
"text": "contact_summary_change",
|
|
260
|
-
"visuallyHiddenText": "licence_summary_name",
|
|
261
|
-
},
|
|
262
|
-
],
|
|
263
|
-
},
|
|
264
|
-
"key": Object {
|
|
265
|
-
"text": "licence_summary_name",
|
|
266
|
-
},
|
|
267
|
-
"value": Object {
|
|
268
|
-
"html": "Brenin Pysgotwr",
|
|
269
|
-
},
|
|
270
|
-
},
|
|
271
|
-
Object {
|
|
272
|
-
"actions": Object {
|
|
273
|
-
"items": Array [
|
|
274
|
-
Object {
|
|
275
|
-
"attributes": Object {
|
|
276
|
-
"id": "change-birth-date",
|
|
277
|
-
},
|
|
278
|
-
"href": "/buy/date-of-birth",
|
|
279
|
-
"text": "contact_summary_change",
|
|
280
|
-
"visuallyHiddenText": "licence_summary_dob",
|
|
281
|
-
},
|
|
282
|
-
],
|
|
283
|
-
},
|
|
284
|
-
"key": Object {
|
|
285
|
-
"text": "licence_summary_dob",
|
|
286
|
-
},
|
|
287
|
-
"value": Object {
|
|
288
|
-
"html": "1st January 1946",
|
|
289
|
-
},
|
|
290
|
-
},
|
|
291
|
-
Object {
|
|
292
|
-
"actions": Object {
|
|
293
|
-
"items": Array [
|
|
294
|
-
Object {
|
|
295
|
-
"attributes": Object {
|
|
296
|
-
"id": "change-licence-type",
|
|
297
|
-
},
|
|
298
|
-
"href": "/buy/licence-type",
|
|
299
|
-
"text": "contact_summary_change",
|
|
300
|
-
"visuallyHiddenText": "licence_summary_type",
|
|
301
|
-
},
|
|
302
|
-
],
|
|
303
|
-
},
|
|
304
|
-
"key": Object {
|
|
305
|
-
"text": "licence_summary_type",
|
|
306
|
-
},
|
|
307
|
-
"value": Object {
|
|
308
|
-
"html": "Special Canal Licence, Shopping Trollies and Old Wellies",
|
|
309
|
-
},
|
|
310
|
-
},
|
|
311
|
-
Object {
|
|
312
|
-
"key": Object {
|
|
313
|
-
"text": "licence_summary_length",
|
|
314
|
-
},
|
|
315
|
-
"value": Object {
|
|
316
|
-
"html": "licence_type_12m",
|
|
317
|
-
},
|
|
318
|
-
},
|
|
319
|
-
Object {
|
|
320
|
-
"actions": Object {
|
|
321
|
-
"items": Array [
|
|
322
|
-
Object {
|
|
323
|
-
"attributes": Object {
|
|
324
|
-
"id": "change-licence-to-start",
|
|
325
|
-
},
|
|
326
|
-
"href": "/buy/start-kind",
|
|
327
|
-
"text": "contact_summary_change",
|
|
328
|
-
"visuallyHiddenText": "licence_summary_start_date",
|
|
329
|
-
},
|
|
330
|
-
],
|
|
331
|
-
},
|
|
332
|
-
"key": Object {
|
|
333
|
-
"text": "licence_summary_start_date",
|
|
334
|
-
},
|
|
335
|
-
"value": Object {
|
|
336
|
-
"html": "30licence_summary_minutes_after_payment",
|
|
337
|
-
},
|
|
338
|
-
},
|
|
339
|
-
Object {
|
|
340
|
-
"actions": Object {
|
|
341
|
-
"items": Array [
|
|
342
|
-
Object {
|
|
343
|
-
"attributes": Object {
|
|
344
|
-
"id": "change-benefit-check",
|
|
345
|
-
},
|
|
346
|
-
"href": "/buy/disability-concession",
|
|
347
|
-
"text": "contact_summary_change",
|
|
348
|
-
"visuallyHiddenText": "licence_summary_ni_num",
|
|
349
|
-
},
|
|
350
|
-
],
|
|
351
|
-
},
|
|
352
|
-
"key": Object {
|
|
353
|
-
"text": "licence_summary_ni_num",
|
|
354
|
-
},
|
|
355
|
-
"value": Object {
|
|
356
|
-
"html": "AB 12 34 56 A",
|
|
357
|
-
},
|
|
358
|
-
},
|
|
359
|
-
Object {
|
|
360
|
-
"key": Object {
|
|
361
|
-
"text": "damage",
|
|
362
|
-
},
|
|
363
|
-
"value": Object {
|
|
364
|
-
"html": "#6",
|
|
365
|
-
},
|
|
366
|
-
},
|
|
367
|
-
]
|
|
368
|
-
`;
|
|
369
|
-
|
|
370
249
|
exports[`licence-summary > route licence summary rows creates licence summary name rows for 1 year renewal 1`] = `
|
|
371
250
|
Array [
|
|
372
251
|
Object {
|
|
@@ -116,7 +116,7 @@ const getMockPermission = (licenseeOverrides = {}) => ({
|
|
|
116
116
|
licenceToStart: 'after-payment',
|
|
117
117
|
licenceStartDate: '2022-11-10',
|
|
118
118
|
licenceType: 'Trout and coarse',
|
|
119
|
-
numberOfRods: '
|
|
119
|
+
numberOfRods: '3',
|
|
120
120
|
permit: { cost: 6 }
|
|
121
121
|
})
|
|
122
122
|
|
|
@@ -372,17 +372,16 @@ describe('licence-summary > route', () => {
|
|
|
372
372
|
|
|
373
373
|
describe('licence summary rows', () => {
|
|
374
374
|
it.each`
|
|
375
|
-
desc
|
|
376
|
-
${'1 year renewal'}
|
|
377
|
-
${'1 year new licence'}
|
|
378
|
-
${'1 year senior renewal'}
|
|
379
|
-
${'8 day licence'}
|
|
380
|
-
${'1 day licence'}
|
|
381
|
-
${'Junior licence'}
|
|
382
|
-
${'Blue badge concession'}
|
|
383
|
-
${'Continuing permission'}
|
|
384
|
-
${'Another date permission'}
|
|
385
|
-
${'1 year new three rod licence '} | ${{ ...getMockNewPermission(), numberOfRods: '3' }}
|
|
375
|
+
desc | currentPermission
|
|
376
|
+
${'1 year renewal'} | ${getMockPermission()}
|
|
377
|
+
${'1 year new licence'} | ${getMockNewPermission()}
|
|
378
|
+
${'1 year senior renewal'} | ${getMockSeniorPermission()}
|
|
379
|
+
${'8 day licence'} | ${{ ...getMockNewPermission(), licenceLength: '8D' }}
|
|
380
|
+
${'1 day licence'} | ${{ ...getMockNewPermission(), licenceLength: '1D' }}
|
|
381
|
+
${'Junior licence'} | ${getMockJuniorPermission()}
|
|
382
|
+
${'Blue badge concession'} | ${getMockBlueBadgePermission()}
|
|
383
|
+
${'Continuing permission'} | ${getMockContinuingPermission()}
|
|
384
|
+
${'Another date permission'} | ${{ ...getMockPermission(), licenceToStart: 'another-date' }}
|
|
386
385
|
`('creates licence summary name rows for $desc', async ({ currentPermission }) => {
|
|
387
386
|
const mockRequest = getMockRequest({ currentPermission })
|
|
388
387
|
const data = await getData(mockRequest)
|
|
@@ -113,13 +113,12 @@ class RowGenerator {
|
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
generateLicenceLengthRow () {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return this.generateStandardRow(...args)
|
|
116
|
+
return this.generateStandardRow(
|
|
117
|
+
'licence_summary_length',
|
|
118
|
+
this.labels[`licence_type_${this.permission.licenceLength.toLowerCase()}`],
|
|
119
|
+
LICENCE_LENGTH.uri,
|
|
120
|
+
'change-licence-length'
|
|
121
|
+
)
|
|
123
122
|
}
|
|
124
123
|
}
|
|
125
124
|
|
|
@@ -63,7 +63,7 @@ describe('prepareApiTransactionPayload', () => {
|
|
|
63
63
|
})
|
|
64
64
|
})
|
|
65
65
|
|
|
66
|
-
it('adds
|
|
66
|
+
it('adds transaction id to payload', async () => {
|
|
67
67
|
const transactionId = Symbol('transactionId')
|
|
68
68
|
|
|
69
69
|
const payload = await prepareApiTransactionPayload(getMockRequest(), transactionId)
|
|
@@ -71,14 +71,6 @@ describe('prepareApiTransactionPayload', () => {
|
|
|
71
71
|
expect(payload.transactionId).toBe(transactionId)
|
|
72
72
|
})
|
|
73
73
|
|
|
74
|
-
it('adds agreementId to payload', async () => {
|
|
75
|
-
const agreementId = Symbol('agreementId')
|
|
76
|
-
|
|
77
|
-
const payload = await prepareApiTransactionPayload(getMockRequest(), 'transaction_id', agreementId)
|
|
78
|
-
|
|
79
|
-
expect(payload.agreementId).toBe(agreementId)
|
|
80
|
-
})
|
|
81
|
-
|
|
82
74
|
const getMockRequest = (overrides = {}, state = {}) => ({
|
|
83
75
|
cache: () => ({
|
|
84
76
|
helpers: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { preparePayment,
|
|
1
|
+
import { preparePayment, prepareRecurringPayment } from '../payment.js'
|
|
2
2
|
import { licenceTypeAndLengthDisplay } from '../licence-type-display.js'
|
|
3
3
|
import { addLanguageCodeToUri } from '../uri-helper.js'
|
|
4
4
|
import { AGREED } from '../../uri.js'
|
|
@@ -20,16 +20,9 @@ const createRequest = (opts = {}, catalog = {}) => ({
|
|
|
20
20
|
server: { info: { protocol: opts.protocol || '' } }
|
|
21
21
|
})
|
|
22
22
|
|
|
23
|
-
const createTransaction = ({
|
|
24
|
-
isLicenceForYou = true,
|
|
25
|
-
additionalPermissions = [],
|
|
26
|
-
cost = 12,
|
|
27
|
-
licenseeOverrides = {},
|
|
28
|
-
agreementId
|
|
29
|
-
} = {}) => ({
|
|
23
|
+
const createTransaction = ({ isLicenceForYou = true, additionalPermissions = [], cost = 12, licenseeOverrides = {} } = {}) => ({
|
|
30
24
|
id: 'transaction-id',
|
|
31
25
|
cost,
|
|
32
|
-
agreementId,
|
|
33
26
|
permissions: [
|
|
34
27
|
{
|
|
35
28
|
id: 'permission-id',
|
|
@@ -56,7 +49,7 @@ describe('preparePayment', () => {
|
|
|
56
49
|
it.each(['http', 'https'])('uses SSL when "x-forwarded-proto" header is present, proto "%s"', proto => {
|
|
57
50
|
addLanguageCodeToUri.mockReturnValue(proto + '://localhost:1234/buy/agreed')
|
|
58
51
|
const request = createRequest({ headers: { 'x-forwarded-proto': proto } })
|
|
59
|
-
const result = preparePayment(request, createTransaction()
|
|
52
|
+
const result = preparePayment(request, createTransaction())
|
|
60
53
|
|
|
61
54
|
expect(result.return_url).toBe(`${proto}://localhost:1234/buy/agreed`)
|
|
62
55
|
})
|
|
@@ -218,30 +211,12 @@ describe('preparePayment', () => {
|
|
|
218
211
|
expect(result.email).toBe(undefined)
|
|
219
212
|
})
|
|
220
213
|
})
|
|
221
|
-
|
|
222
|
-
describe('if agreementId is not present', () => {
|
|
223
|
-
it('does not include set_up_agreement', () => {
|
|
224
|
-
const result = preparePayment(createRequest(), createTransaction())
|
|
225
|
-
expect(result.set_up_agreement).toBe(undefined)
|
|
226
|
-
})
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
describe('if agreementId is present', () => {
|
|
230
|
-
it('set_up_agreement is set to agreementId', () => {
|
|
231
|
-
const agreementId = 'foo'
|
|
232
|
-
const recurringPaymentTransaction = createTransaction({ agreementId })
|
|
233
|
-
|
|
234
|
-
const result = preparePayment(createRequest(), recurringPaymentTransaction)
|
|
235
|
-
|
|
236
|
-
expect(result.set_up_agreement).toBe(agreementId)
|
|
237
|
-
})
|
|
238
|
-
})
|
|
239
214
|
})
|
|
240
215
|
|
|
241
|
-
describe('
|
|
216
|
+
describe('prepareRecurringPayment', () => {
|
|
242
217
|
it('reference equals transaction.id', async () => {
|
|
243
218
|
const transaction = createTransaction()
|
|
244
|
-
const result = await
|
|
219
|
+
const result = await prepareRecurringPayment(createRequest(), transaction)
|
|
245
220
|
expect(result.reference).toBe(transaction.id)
|
|
246
221
|
})
|
|
247
222
|
|
|
@@ -252,7 +227,7 @@ describe('prepareRecurringPaymentAgreement', () => {
|
|
|
252
227
|
const request = createRequest({}, mockCatalog)
|
|
253
228
|
const transaction = createTransaction()
|
|
254
229
|
|
|
255
|
-
const result = await
|
|
230
|
+
const result = await prepareRecurringPayment(request, transaction)
|
|
256
231
|
expect(result.description).toBe(mockCatalog.recurring_payment_description)
|
|
257
232
|
})
|
|
258
233
|
|
|
@@ -260,7 +235,7 @@ describe('prepareRecurringPaymentAgreement', () => {
|
|
|
260
235
|
const transaction = createTransaction()
|
|
261
236
|
const request = createRequest()
|
|
262
237
|
|
|
263
|
-
const result = await
|
|
264
|
-
expect(debug).toHaveBeenCalledWith('Creating prepared recurring payment
|
|
238
|
+
const result = await prepareRecurringPayment(request, transaction)
|
|
239
|
+
expect(debug).toHaveBeenCalledWith('Creating prepared recurring payment %o', result)
|
|
265
240
|
})
|
|
266
241
|
})
|
|
@@ -7,7 +7,7 @@ import { countries } from './refdata-helper.js'
|
|
|
7
7
|
import { salesApi } from '@defra-fish/connectors-lib'
|
|
8
8
|
import { licenceToStart } from '../pages/licence-details/licence-to-start/update-transaction.js'
|
|
9
9
|
|
|
10
|
-
export const prepareApiTransactionPayload = async (request, transactionId
|
|
10
|
+
export const prepareApiTransactionPayload = async (request, transactionId) => {
|
|
11
11
|
const transactionCache = await request.cache().helpers.transaction.get()
|
|
12
12
|
const concessions = await salesApi.concessions.getAll()
|
|
13
13
|
const countryList = await countries.getAll()
|
|
@@ -63,8 +63,7 @@ export const prepareApiTransactionPayload = async (request, transactionId, agree
|
|
|
63
63
|
request.state && request.state[process.env.OIDC_SESSION_COOKIE_NAME]
|
|
64
64
|
? request.state[process.env.OIDC_SESSION_COOKIE_NAME].oid
|
|
65
65
|
: undefined,
|
|
66
|
-
transactionId
|
|
67
|
-
agreementId
|
|
66
|
+
transactionId
|
|
68
67
|
}
|
|
69
68
|
}
|
|
70
69
|
|
|
@@ -50,21 +50,17 @@ export const preparePayment = (request, transaction) => {
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
if (transaction.agreementId) {
|
|
54
|
-
result.set_up_agreement = transaction.agreementId
|
|
55
|
-
}
|
|
56
|
-
|
|
57
53
|
debug('Creating prepared payment %o', result)
|
|
58
54
|
return result
|
|
59
55
|
}
|
|
60
56
|
|
|
61
|
-
export const
|
|
57
|
+
export const prepareRecurringPayment = async (request, transaction) => {
|
|
62
58
|
debug('Preparing recurring payment %s', JSON.stringify(transaction, undefined, '\t'))
|
|
63
|
-
// The recurring card payment
|
|
59
|
+
// The recurring card payment for your rod fishing licence
|
|
64
60
|
const result = {
|
|
65
61
|
reference: transaction.id,
|
|
66
62
|
description: request.i18n.getCatalog().recurring_payment_description
|
|
67
63
|
}
|
|
68
|
-
debug('Creating prepared recurring payment
|
|
64
|
+
debug('Creating prepared recurring payment %o', result)
|
|
69
65
|
return result
|
|
70
66
|
}
|
|
@@ -2,7 +2,7 @@ import mockTransaction from './data/mock-transaction.js'
|
|
|
2
2
|
import { preparePayment } from '../../../processors/payment.js'
|
|
3
3
|
import { AGREED } from '../../../uri.js'
|
|
4
4
|
import { addLanguageCodeToUri } from '../../../processors/uri-helper.js'
|
|
5
|
-
import {
|
|
5
|
+
import { sendRecurringPayment } from '../govuk-pay-service.js'
|
|
6
6
|
import { govUkPayApi } from '@defra-fish/connectors-lib'
|
|
7
7
|
import db from 'debug'
|
|
8
8
|
const { value: debug } = db.mock.results[db.mock.calls.findIndex(c => c[0] === 'webapp:govuk-pay-service')]
|
|
@@ -158,142 +158,6 @@ describe('The govuk-pay-service', () => {
|
|
|
158
158
|
console.log(preparedPayment)
|
|
159
159
|
})
|
|
160
160
|
|
|
161
|
-
describe('sendPayment', () => {
|
|
162
|
-
const preparedPayment = {
|
|
163
|
-
id: '1234',
|
|
164
|
-
user_identifier: 'test-user'
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
beforeEach(() => {
|
|
168
|
-
jest.clearAllMocks()
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
it.each([
|
|
172
|
-
[true, true],
|
|
173
|
-
[false, false],
|
|
174
|
-
[false, undefined]
|
|
175
|
-
])('should call the govUkPayApi with recurring as %s if the argument is %s', async (expected, value) => {
|
|
176
|
-
const mockResponse = {
|
|
177
|
-
ok: true,
|
|
178
|
-
json: jest.fn().mockResolvedValue({ success: true, paymentId: 'abc123' })
|
|
179
|
-
}
|
|
180
|
-
govUkPayApi.createPayment.mockResolvedValue(mockResponse)
|
|
181
|
-
const unique = Symbol('payload')
|
|
182
|
-
const payload = { unique }
|
|
183
|
-
await sendPayment(payload, value)
|
|
184
|
-
expect(govUkPayApi.createPayment).toHaveBeenCalledWith(payload, expected)
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
it('should send provided payload data to Gov.UK Pay', async () => {
|
|
188
|
-
const mockResponse = {
|
|
189
|
-
ok: true,
|
|
190
|
-
json: jest.fn().mockResolvedValue({ success: true, paymentId: 'abc123' })
|
|
191
|
-
}
|
|
192
|
-
govUkPayApi.createPayment.mockResolvedValue(mockResponse)
|
|
193
|
-
const unique = Symbol('payload')
|
|
194
|
-
const payload = {
|
|
195
|
-
reference: 'd81f1a2b-6508-468f-8342-b6770f60f7cd',
|
|
196
|
-
description: 'Fishing permission',
|
|
197
|
-
user_identifier: '1218c1c5-38e4-4bf3-81ea-9cbce3994d30',
|
|
198
|
-
unique
|
|
199
|
-
}
|
|
200
|
-
await sendPayment(payload)
|
|
201
|
-
expect(govUkPayApi.createPayment).toHaveBeenCalledWith(payload, false)
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
it('should return response body when payment creation is successful', async () => {
|
|
205
|
-
const mockResponse = {
|
|
206
|
-
ok: true,
|
|
207
|
-
json: jest.fn().mockResolvedValue({ success: true, paymentId: 'abc123' })
|
|
208
|
-
}
|
|
209
|
-
govUkPayApi.createPayment.mockResolvedValue(mockResponse)
|
|
210
|
-
|
|
211
|
-
const result = await sendPayment(preparedPayment)
|
|
212
|
-
|
|
213
|
-
expect(result).toEqual({ success: true, paymentId: 'abc123' })
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
it('should log debug message when response.ok is true', async () => {
|
|
217
|
-
const mockResponse = {
|
|
218
|
-
ok: true,
|
|
219
|
-
json: jest.fn().mockResolvedValue({ success: true, paymentId: 'abc123' })
|
|
220
|
-
}
|
|
221
|
-
govUkPayApi.createPayment.mockResolvedValue(mockResponse)
|
|
222
|
-
|
|
223
|
-
await sendPayment(preparedPayment)
|
|
224
|
-
|
|
225
|
-
expect(debug).toHaveBeenCalledWith('Successful payment creation response: %o', { success: true, paymentId: 'abc123' })
|
|
226
|
-
})
|
|
227
|
-
|
|
228
|
-
it('should log error message when response.ok is false', async () => {
|
|
229
|
-
const mockResponse = {
|
|
230
|
-
ok: false,
|
|
231
|
-
status: 500,
|
|
232
|
-
json: jest.fn().mockResolvedValue({ message: 'Server error' })
|
|
233
|
-
}
|
|
234
|
-
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
|
|
235
|
-
govUkPayApi.createPayment.mockResolvedValue(mockResponse)
|
|
236
|
-
|
|
237
|
-
try {
|
|
238
|
-
await sendPayment(preparedPayment)
|
|
239
|
-
} catch (error) {
|
|
240
|
-
expect(consoleErrorSpy).toHaveBeenCalledWith('Failure creating payment in the GOV.UK API service', {
|
|
241
|
-
transactionId: preparedPayment.id,
|
|
242
|
-
method: 'POST',
|
|
243
|
-
payload: preparedPayment,
|
|
244
|
-
status: mockResponse.status,
|
|
245
|
-
response: { message: 'Server error' }
|
|
246
|
-
})
|
|
247
|
-
}
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
it('should throw error when API call fails with network issue', async () => {
|
|
251
|
-
const mockError = new Error('Network error')
|
|
252
|
-
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn())
|
|
253
|
-
govUkPayApi.createPayment.mockRejectedValue(mockError)
|
|
254
|
-
|
|
255
|
-
try {
|
|
256
|
-
await sendPayment(preparedPayment)
|
|
257
|
-
} catch (error) {
|
|
258
|
-
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
259
|
-
`Error creating payment in the GOV.UK API service - tid: ${preparedPayment.id}`,
|
|
260
|
-
mockError
|
|
261
|
-
)
|
|
262
|
-
}
|
|
263
|
-
})
|
|
264
|
-
|
|
265
|
-
it('should throw error for when rate limit is breached', async () => {
|
|
266
|
-
const mockResponse = {
|
|
267
|
-
ok: false,
|
|
268
|
-
status: 429,
|
|
269
|
-
json: jest.fn().mockResolvedValue({ message: 'Rate limit exceeded' })
|
|
270
|
-
}
|
|
271
|
-
const consoleErrorSpy = jest.spyOn(console, 'info').mockImplementation(jest.fn())
|
|
272
|
-
govUkPayApi.createPayment.mockResolvedValue(mockResponse)
|
|
273
|
-
|
|
274
|
-
try {
|
|
275
|
-
await sendPayment(preparedPayment)
|
|
276
|
-
} catch (error) {
|
|
277
|
-
expect(consoleErrorSpy).toHaveBeenCalledWith(`GOV.UK Pay API rate limit breach - tid: ${preparedPayment.id}`)
|
|
278
|
-
}
|
|
279
|
-
})
|
|
280
|
-
|
|
281
|
-
it('should throw error for unexpected response status', async () => {
|
|
282
|
-
const mockResponse = {
|
|
283
|
-
ok: false,
|
|
284
|
-
status: 500,
|
|
285
|
-
json: jest.fn().mockResolvedValue({ message: 'Server error' })
|
|
286
|
-
}
|
|
287
|
-
govUkPayApi.createPayment.mockResolvedValue(mockResponse)
|
|
288
|
-
|
|
289
|
-
try {
|
|
290
|
-
await sendPayment(preparedPayment)
|
|
291
|
-
} catch (error) {
|
|
292
|
-
expect(error.message).toBe('Unexpected response from GOV.UK pay API')
|
|
293
|
-
}
|
|
294
|
-
})
|
|
295
|
-
})
|
|
296
|
-
|
|
297
161
|
describe('sendRecurringPayment', () => {
|
|
298
162
|
const preparedPayment = {
|
|
299
163
|
id: '1234',
|
|
@@ -413,120 +277,4 @@ describe('The govuk-pay-service', () => {
|
|
|
413
277
|
}
|
|
414
278
|
})
|
|
415
279
|
})
|
|
416
|
-
|
|
417
|
-
describe('getPaymentStatus', () => {
|
|
418
|
-
const paymentId = '1234'
|
|
419
|
-
|
|
420
|
-
beforeEach(() => {
|
|
421
|
-
jest.clearAllMocks()
|
|
422
|
-
})
|
|
423
|
-
|
|
424
|
-
it.each([
|
|
425
|
-
[true, true],
|
|
426
|
-
[false, false],
|
|
427
|
-
[false, undefined]
|
|
428
|
-
])('should call the govUkPayApi with recurring as %s if the argument is %s', async (expected, value) => {
|
|
429
|
-
const mockResponse = { ok: true, status: 200, json: () => {} }
|
|
430
|
-
govUkPayApi.fetchPaymentStatus.mockResolvedValue(mockResponse)
|
|
431
|
-
await getPaymentStatus(paymentId, value)
|
|
432
|
-
expect(govUkPayApi.fetchPaymentStatus).toHaveBeenCalledWith(paymentId, expected)
|
|
433
|
-
})
|
|
434
|
-
|
|
435
|
-
it('should send provided paymentId to Gov.UK Pay', async () => {
|
|
436
|
-
const mockResponse = { ok: true, status: 200, json: () => {} }
|
|
437
|
-
govUkPayApi.fetchPaymentStatus.mockResolvedValue(mockResponse)
|
|
438
|
-
await getPaymentStatus(paymentId)
|
|
439
|
-
expect(govUkPayApi.fetchPaymentStatus).toHaveBeenCalledWith(paymentId, false)
|
|
440
|
-
})
|
|
441
|
-
|
|
442
|
-
it('should return response body when payment status check is successful', async () => {
|
|
443
|
-
const resBody = Symbol('body')
|
|
444
|
-
const mockResponse = { ok: true, status: 200, json: jest.fn().mockResolvedValue(resBody) }
|
|
445
|
-
govUkPayApi.fetchPaymentStatus.mockResolvedValue(mockResponse)
|
|
446
|
-
|
|
447
|
-
const result = await getPaymentStatus(paymentId)
|
|
448
|
-
|
|
449
|
-
expect(result).toEqual(resBody)
|
|
450
|
-
})
|
|
451
|
-
|
|
452
|
-
it('should log debug message when response.ok is true', async () => {
|
|
453
|
-
const resBody = Symbol('body')
|
|
454
|
-
const mockResponse = { ok: true, status: 200, json: jest.fn().mockResolvedValue(resBody) }
|
|
455
|
-
govUkPayApi.fetchPaymentStatus.mockResolvedValue(mockResponse)
|
|
456
|
-
|
|
457
|
-
await getPaymentStatus(paymentId)
|
|
458
|
-
|
|
459
|
-
expect(debug).toHaveBeenCalledWith('Payment status response: %o', resBody)
|
|
460
|
-
})
|
|
461
|
-
|
|
462
|
-
it('should log error message when response.ok is false', async () => {
|
|
463
|
-
const mockResponse = {
|
|
464
|
-
ok: false,
|
|
465
|
-
status: 500,
|
|
466
|
-
json: jest.fn().mockResolvedValue({ message: 'Server error' })
|
|
467
|
-
}
|
|
468
|
-
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
|
|
469
|
-
govUkPayApi.fetchPaymentStatus.mockResolvedValue(mockResponse)
|
|
470
|
-
|
|
471
|
-
try {
|
|
472
|
-
await getPaymentStatus(paymentId)
|
|
473
|
-
} catch (error) {
|
|
474
|
-
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
475
|
-
`Error retrieving the payment status from the GOV.UK API service - tid: ${paymentId}`,
|
|
476
|
-
{
|
|
477
|
-
method: 'GET',
|
|
478
|
-
paymentId: paymentId,
|
|
479
|
-
status: mockResponse.status,
|
|
480
|
-
response: { message: 'Server error' }
|
|
481
|
-
}
|
|
482
|
-
)
|
|
483
|
-
}
|
|
484
|
-
})
|
|
485
|
-
|
|
486
|
-
it('should throw error when API call fails with network issue', async () => {
|
|
487
|
-
const mockError = new Error('Network error')
|
|
488
|
-
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn())
|
|
489
|
-
govUkPayApi.fetchPaymentStatus.mockRejectedValue(mockError)
|
|
490
|
-
|
|
491
|
-
try {
|
|
492
|
-
await getPaymentStatus(paymentId)
|
|
493
|
-
} catch (error) {
|
|
494
|
-
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
495
|
-
`Error retrieving the payment status from the GOV.UK API service - paymentId: ${paymentId}`,
|
|
496
|
-
mockError
|
|
497
|
-
)
|
|
498
|
-
}
|
|
499
|
-
})
|
|
500
|
-
|
|
501
|
-
it('should throw error for when rate limit is breached', async () => {
|
|
502
|
-
const mockResponse = {
|
|
503
|
-
ok: false,
|
|
504
|
-
status: 429,
|
|
505
|
-
json: jest.fn().mockResolvedValue({ message: 'Rate limit exceeded' })
|
|
506
|
-
}
|
|
507
|
-
const consoleErrorSpy = jest.spyOn(console, 'info').mockImplementation(jest.fn())
|
|
508
|
-
govUkPayApi.fetchPaymentStatus.mockResolvedValue(mockResponse)
|
|
509
|
-
|
|
510
|
-
try {
|
|
511
|
-
await getPaymentStatus(paymentId)
|
|
512
|
-
} catch (error) {
|
|
513
|
-
expect(consoleErrorSpy).toHaveBeenCalledWith(`GOV.UK Pay API rate limit breach - paymentId: ${paymentId}`)
|
|
514
|
-
}
|
|
515
|
-
})
|
|
516
|
-
|
|
517
|
-
it('should throw error for unexpected response status', async () => {
|
|
518
|
-
const mockResponse = {
|
|
519
|
-
ok: false,
|
|
520
|
-
status: 500,
|
|
521
|
-
json: jest.fn().mockResolvedValue({ message: 'Server error' })
|
|
522
|
-
}
|
|
523
|
-
govUkPayApi.fetchPaymentStatus.mockResolvedValue(mockResponse)
|
|
524
|
-
|
|
525
|
-
try {
|
|
526
|
-
await getPaymentStatus(paymentId)
|
|
527
|
-
} catch (error) {
|
|
528
|
-
expect(error.message).toBe('Unexpected response from GOV.UK pay API')
|
|
529
|
-
}
|
|
530
|
-
})
|
|
531
|
-
})
|
|
532
280
|
})
|
|
@@ -46,10 +46,10 @@ const getTransactionErrorMessage = async (transactionId, payload, response) => (
|
|
|
46
46
|
* @param preparedPayment - the prepared payload for the payment. See in processors/payment.js
|
|
47
47
|
* @returns {Promise<*>}
|
|
48
48
|
*/
|
|
49
|
-
export const sendPayment = async
|
|
49
|
+
export const sendPayment = async preparedPayment => {
|
|
50
50
|
let response
|
|
51
51
|
try {
|
|
52
|
-
response = await govUkPayApi.createPayment(preparedPayment
|
|
52
|
+
response = await govUkPayApi.createPayment(preparedPayment)
|
|
53
53
|
} catch (err) {
|
|
54
54
|
/*
|
|
55
55
|
* Potentially errors caught here (unreachable, timeouts) may be retried - set origin on the error to indicate
|
|
@@ -78,11 +78,11 @@ export const sendPayment = async (preparedPayment, recurring = false) => {
|
|
|
78
78
|
* @param paymentId - the paymentId
|
|
79
79
|
* @returns {Promise<any>}
|
|
80
80
|
*/
|
|
81
|
-
export const getPaymentStatus = async
|
|
81
|
+
export const getPaymentStatus = async paymentId => {
|
|
82
82
|
debug(`Get payment status for paymentId: ${paymentId}`)
|
|
83
83
|
let response
|
|
84
84
|
try {
|
|
85
|
-
response = await govUkPayApi.fetchPaymentStatus(paymentId
|
|
85
|
+
response = await govUkPayApi.fetchPaymentStatus(paymentId)
|
|
86
86
|
} catch (err) {
|
|
87
87
|
/*
|
|
88
88
|
* Errors caught here (unreachable, timeouts) may be retried - set origin on the error to indicate
|