@defra-fish/connectors-lib 1.75.0-rc.2 → 1.75.0-rc.3

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defra-fish/connectors-lib",
3
- "version": "1.75.0-rc.2",
3
+ "version": "1.75.0-rc.3",
4
4
  "description": "Shared connectors",
5
5
  "type": "module",
6
6
  "engines": {
@@ -47,5 +47,5 @@
47
47
  "node-fetch": "2.7.0",
48
48
  "redlock": "4.2.0"
49
49
  },
50
- "gitHead": "4e154247f5b5a430aa7e6c26e71d75546d8d2411"
50
+ "gitHead": "0f6912bc7a73c58e2d3494529adc62ce8d65e9e5"
51
51
  }
@@ -47,7 +47,7 @@ describe('govuk-pay-api-connector', () => {
47
47
  fetch.mockImplementationOnce(() => {
48
48
  throw new Error('')
49
49
  })
50
- expect(govUkPayApi.createPayment({ cost: 0 })).rejects.toEqual(Error(''))
50
+ await expect(govUkPayApi.createPayment({ cost: 0 })).rejects.toEqual(Error(''))
51
51
  expect(fetch).toHaveBeenCalledWith('http://0.0.0.0/payment', {
52
52
  body: JSON.stringify({ cost: 0 }),
53
53
  headers: headers(),
@@ -67,6 +67,20 @@ describe('govuk-pay-api-connector', () => {
67
67
  timeout: 10000
68
68
  })
69
69
  })
70
+
71
+ it('rethrows the same error when fetch rejects', async () => {
72
+ const error = new Error('creating payment failed')
73
+ fetch.mockRejectedValueOnce(error)
74
+ await expect(govUkPayApi.createPayment('abc-123')).rejects.toBe(error)
75
+ })
76
+
77
+ it('logs an error when fetch rejects', async () => {
78
+ const error = new Error('creating payment failed')
79
+ const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn())
80
+ fetch.mockRejectedValueOnce(error)
81
+ await govUkPayApi.createPayment('abc-123').catch(() => {})
82
+ expect(consoleErrorSpy).toHaveBeenCalledWith('Error creating payment in the GOV.UK API service - payment: "abc-123"', error)
83
+ })
70
84
  })
71
85
 
72
86
  describe('fetchPaymentStatus', () => {
@@ -99,6 +113,23 @@ describe('govuk-pay-api-connector', () => {
99
113
  timeout: 10000
100
114
  })
101
115
  })
116
+
117
+ it('rethrows the same error when fetch rejects', async () => {
118
+ const error = new Error('fetching payment status failed')
119
+ fetch.mockRejectedValueOnce(error)
120
+ await expect(govUkPayApi.fetchPaymentStatus('abc-123')).rejects.toBe(error)
121
+ })
122
+
123
+ it('logs an error when fetch rejects', async () => {
124
+ const error = new Error('fetching payment status failed')
125
+ const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn())
126
+ fetch.mockRejectedValueOnce(error)
127
+ await govUkPayApi.fetchPaymentStatus('abc-123').catch(() => {})
128
+ expect(consoleErrorSpy).toHaveBeenCalledWith(
129
+ 'Error retrieving the payment status from the GOV.UK API service - paymentId: abc-123',
130
+ error
131
+ )
132
+ })
102
133
  })
103
134
 
104
135
  describe('fetchPaymentEvents', () => {
@@ -126,6 +157,23 @@ describe('govuk-pay-api-connector', () => {
126
157
  timeout: 10000
127
158
  })
128
159
  })
160
+
161
+ it('rethrows the same error when fetch rejects', async () => {
162
+ const error = new Error('fetching payments failed')
163
+ fetch.mockRejectedValueOnce(error)
164
+ await expect(govUkPayApi.fetchPaymentEvents('abc-123')).rejects.toBe(error)
165
+ })
166
+
167
+ it('logs an error when fetch rejects', async () => {
168
+ const error = new Error('fetching payments failed')
169
+ const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn())
170
+ fetch.mockRejectedValueOnce(error)
171
+ await govUkPayApi.fetchPaymentEvents('abc-123').catch(() => {})
172
+ expect(consoleErrorSpy).toHaveBeenCalledWith(
173
+ 'Error retrieving the payment events from the GOV.UK API service - paymentId: abc-123',
174
+ error
175
+ )
176
+ })
129
177
  })
130
178
 
131
179
  describe('createRecurringPaymentAgreement', () => {
@@ -145,7 +193,7 @@ describe('govuk-pay-api-connector', () => {
145
193
  fetch.mockImplementationOnce(() => {
146
194
  throw new Error('')
147
195
  })
148
- expect(govUkPayApi.createRecurringPaymentAgreement({ reference: '123' })).rejects.toEqual(Error(''))
196
+ await expect(govUkPayApi.createRecurringPaymentAgreement({ reference: '123' })).rejects.toEqual(Error(''))
149
197
  expect(fetch).toHaveBeenCalledWith('http://0.0.0.0/agreement', {
150
198
  body: JSON.stringify({ reference: '123' }),
151
199
  headers: recurringHeaders(),
@@ -282,7 +330,7 @@ describe('govuk-pay-api-connector', () => {
282
330
 
283
331
  it('logs errors', async () => {
284
332
  const error = new Error('Fail')
285
- const consoleErrorSpy = jest.spyOn(console, 'error')
333
+ const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn())
286
334
  fetch.mockImplementationOnce(() => {
287
335
  throw error
288
336
  })
@@ -291,11 +339,26 @@ describe('govuk-pay-api-connector', () => {
291
339
  } catch {}
292
340
  expect(consoleErrorSpy).toHaveBeenCalledWith('Error retrieving GovPay health status', error)
293
341
  })
342
+
343
+ it('rethrows the same error when fetch rejects', async () => {
344
+ const error = new Error('fetching GovPay health status failed')
345
+ fetch.mockRejectedValueOnce(error)
346
+ await expect(govUkPayApi.isGovPayUp()).rejects.toBe(error)
347
+ })
348
+
349
+ it('logs an error when fetch rejects', async () => {
350
+ const error = new Error('fetching GovPay health status failed')
351
+ const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn())
352
+ fetch.mockRejectedValueOnce(error)
353
+ await govUkPayApi.isGovPayUp().catch(() => {})
354
+ expect(consoleErrorSpy).toHaveBeenCalledWith('Error retrieving GovPay health status', error)
355
+ })
294
356
  })
295
357
 
296
358
  describe('getRecurringPaymentAgreementInformation', () => {
297
359
  it('retrieves recurring payment agreement information', async () => {
298
- fetch.mockReturnValue({ ok: true, status: 200, json: () => {} })
360
+ const mockResponse = { ok: true, status: 200, json: () => {} }
361
+ fetch.mockResolvedValueOnce(mockResponse)
299
362
  await expect(govUkPayApi.getRecurringPaymentAgreementInformation(123)).resolves.toEqual(
300
363
  expect.objectContaining({ ok: true, status: 200 })
301
364
  )
@@ -310,5 +373,100 @@ describe('govuk-pay-api-connector', () => {
310
373
  await expect(govUkPayApi.getRecurringPaymentAgreementInformation(123)).rejects.toEqual(Error('test event error'))
311
374
  expect(consoleErrorSpy).toHaveBeenCalled()
312
375
  })
376
+
377
+ it('rethrows the same error when fetch rejects', async () => {
378
+ const error = new Error('fetching agreement failed')
379
+ fetch.mockRejectedValueOnce(error)
380
+ await expect(govUkPayApi.getRecurringPaymentAgreementInformation('abc-123')).rejects.toBe(error)
381
+ })
382
+
383
+ it('logs an error when fetch rejects', async () => {
384
+ const error = new Error('fetching agreement failed')
385
+ const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn())
386
+ fetch.mockRejectedValueOnce(error)
387
+ await govUkPayApi.getRecurringPaymentAgreementInformation('abc-123').catch(() => {})
388
+ expect(consoleErrorSpy).toHaveBeenCalledWith(
389
+ 'Error fetching recurring payment agreement information in the GOV.UK API service - agreementId: abc-123',
390
+ error
391
+ )
392
+ })
393
+ })
394
+
395
+ describe.each(['abc-123', 'def-456', 'ghi-789'])('cancelRecurringPaymentAgreement with agreement id %s', agreementId => {
396
+ it('calls the cancel endpoint for the provided agreement id', async () => {
397
+ const mockResponse = { ok: true, status: 204 }
398
+ fetch.mockReturnValueOnce(mockResponse)
399
+ await govUkPayApi.cancelRecurringPaymentAgreement(agreementId)
400
+ expect(fetch).toHaveBeenCalledWith(`http://0.0.0.0/agreement/${agreementId}/cancel`, expect.any(Object))
401
+ })
402
+
403
+ it('sends recurring API headers', async () => {
404
+ const mockResponse = { ok: true, status: 204 }
405
+ fetch.mockResolvedValueOnce(mockResponse)
406
+ await govUkPayApi.cancelRecurringPaymentAgreement(agreementId)
407
+ expect(fetch).toHaveBeenCalledWith(
408
+ expect.any(String),
409
+ expect.objectContaining({
410
+ headers: recurringHeaders()
411
+ })
412
+ )
413
+ })
414
+
415
+ it('uses POST method', async () => {
416
+ const mockResponse = { ok: true, status: 204 }
417
+ fetch.mockResolvedValueOnce(mockResponse)
418
+ await govUkPayApi.cancelRecurringPaymentAgreement(agreementId)
419
+ expect(fetch).toHaveBeenCalledWith(
420
+ expect.any(String),
421
+ expect.objectContaining({
422
+ method: 'post'
423
+ })
424
+ )
425
+ })
426
+
427
+ it('uses the configured request timeout', async () => {
428
+ const mockResponse = { ok: true, status: 204 }
429
+ fetch.mockResolvedValueOnce(mockResponse)
430
+ await govUkPayApi.cancelRecurringPaymentAgreement(agreementId)
431
+ expect(fetch).toHaveBeenCalledWith(
432
+ expect.any(String),
433
+ expect.objectContaining({
434
+ timeout: 10000
435
+ })
436
+ )
437
+ })
438
+
439
+ it('returns the fetch response when GOV.UK Pay request succeeds', async () => {
440
+ const mockResponse = { ok: true, status: 204 }
441
+ fetch.mockResolvedValueOnce(mockResponse)
442
+ const result = await govUkPayApi.cancelRecurringPaymentAgreement(agreementId)
443
+ expect(result).toEqual({ ok: true, status: 204 })
444
+ })
445
+
446
+ it('returns non-ok responses for caller-side handling', async () => {
447
+ const mockResponse = { ok: false, status: 400, statusText: 'Bad Request' }
448
+ fetch.mockResolvedValueOnce(mockResponse)
449
+ const result = await govUkPayApi.cancelRecurringPaymentAgreement(agreementId)
450
+ expect(result).toEqual(mockResponse)
451
+ })
452
+
453
+ it('rethrows the same error when fetch rejects', async () => {
454
+ const error = new Error('cancel agreement failed')
455
+ fetch.mockRejectedValueOnce(error)
456
+
457
+ await expect(govUkPayApi.cancelRecurringPaymentAgreement(agreementId)).rejects.toBe(error)
458
+ })
459
+
460
+ it('logs an error when fetch rejects', async () => {
461
+ const error = new Error('cancel agreement failed')
462
+ const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn())
463
+ fetch.mockRejectedValueOnce(error)
464
+
465
+ await govUkPayApi.cancelRecurringPaymentAgreement(agreementId).catch(() => {})
466
+ expect(consoleErrorSpy).toHaveBeenCalledWith(
467
+ `Error cancelling recurring payment agreement in the GOV.UK API service - agreementId: ${agreementId}`,
468
+ error
469
+ )
470
+ })
313
471
  })
314
472
  })
@@ -17,7 +17,7 @@ const headers = recurring => ({
17
17
  */
18
18
  export const createRecurringPaymentAgreement = async preparedPayment => {
19
19
  try {
20
- return fetch(process.env.GOV_PAY_RCP_API_URL, {
20
+ return await fetch(process.env.GOV_PAY_RCP_API_URL, {
21
21
  headers: headers(true),
22
22
  method: 'post',
23
23
  body: JSON.stringify(preparedPayment),
@@ -64,7 +64,7 @@ export const queueRecurringPaymentStatusCheck = (paymentId, batcher) => {
64
64
  */
65
65
  export const createPayment = async (preparedPayment, recurring = false) => {
66
66
  try {
67
- return fetch(process.env.GOV_PAY_API_URL, {
67
+ return await fetch(process.env.GOV_PAY_API_URL, {
68
68
  headers: headers(recurring),
69
69
  method: 'post',
70
70
  body: JSON.stringify(preparedPayment),
@@ -83,7 +83,7 @@ export const createPayment = async (preparedPayment, recurring = false) => {
83
83
  */
84
84
  export const fetchPaymentStatus = async (paymentId, recurring = false) => {
85
85
  try {
86
- return fetch(`${process.env.GOV_PAY_API_URL}/${paymentId}`, {
86
+ return await fetch(`${process.env.GOV_PAY_API_URL}/${paymentId}`, {
87
87
  headers: headers(recurring),
88
88
  method: 'get',
89
89
  timeout: process.env.GOV_PAY_REQUEST_TIMEOUT_MS || GOV_PAY_REQUEST_TIMEOUT_MS_DEFAULT
@@ -101,7 +101,7 @@ export const fetchPaymentStatus = async (paymentId, recurring = false) => {
101
101
  */
102
102
  export const fetchPaymentEvents = async (paymentId, recurring = false) => {
103
103
  try {
104
- return fetch(`${process.env.GOV_PAY_API_URL}/${paymentId}/events`, {
104
+ return await fetch(`${process.env.GOV_PAY_API_URL}/${paymentId}/events`, {
105
105
  headers: headers(recurring),
106
106
  method: 'get',
107
107
  timeout: process.env.GOV_PAY_REQUEST_TIMEOUT_MS || GOV_PAY_REQUEST_TIMEOUT_MS_DEFAULT
@@ -128,7 +128,7 @@ export const isGovPayUp = async () => {
128
128
  */
129
129
  export const getRecurringPaymentAgreementInformation = async agreementId => {
130
130
  try {
131
- return fetch(`${process.env.GOV_PAY_RCP_API_URL}/${agreementId}`, {
131
+ return await fetch(`${process.env.GOV_PAY_RCP_API_URL}/${agreementId}`, {
132
132
  headers: headers(true),
133
133
  method: 'get',
134
134
  timeout: process.env.GOV_PAY_REQUEST_TIMEOUT_MS || GOV_PAY_REQUEST_TIMEOUT_MS_DEFAULT
@@ -138,3 +138,21 @@ export const getRecurringPaymentAgreementInformation = async agreementId => {
138
138
  throw err
139
139
  }
140
140
  }
141
+
142
+ /**
143
+ * Cancel a recurring payment agreement in GOV.UK Pay
144
+ * @param agreementId - the agreement to cancel
145
+ * @returns {Promise<*>}
146
+ */
147
+ export const cancelRecurringPaymentAgreement = async agreementId => {
148
+ try {
149
+ return await fetch(`${process.env.GOV_PAY_RCP_API_URL}/${agreementId}/cancel`, {
150
+ headers: headers(true),
151
+ method: 'post',
152
+ timeout: process.env.GOV_PAY_REQUEST_TIMEOUT_MS || GOV_PAY_REQUEST_TIMEOUT_MS_DEFAULT
153
+ })
154
+ } catch (err) {
155
+ console.error(`Error cancelling recurring payment agreement in the GOV.UK API service - agreementId: ${agreementId}`, err)
156
+ throw err
157
+ }
158
+ }