@defra-fish/gafl-webapp-service 1.59.0-rc.7 → 1.59.0-rc.8

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/gafl-webapp-service",
3
- "version": "1.59.0-rc.7",
3
+ "version": "1.59.0-rc.8",
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.59.0-rc.7",
40
- "@defra-fish/connectors-lib": "1.59.0-rc.7",
39
+ "@defra-fish/business-rules-lib": "1.59.0-rc.8",
40
+ "@defra-fish/connectors-lib": "1.59.0-rc.8",
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": "1c25db53364eccaad0d24eb7f1f7fc3bb2e48014"
83
+ "gitHead": "7b7ed5b4ba22c0fdf406fb206649a312b3ab72e0"
84
84
  }
@@ -600,6 +600,7 @@
600
600
  "payment_cancelled_title": "Mae eich taliad wedi cael ei ganslo",
601
601
  "payment_failed_expired": "Ni chafodd y taliad ei gwblhau o fewn 90 munud o greu’r cais",
602
602
  "payment_failed_not_taken": "Nid oes unrhyw arian wedi cael ei dynnu o’ch cyfrif.",
603
+ "payment_failed_not_taken_recurring": "Nid oes unrhyw arian wedi cael ei dynnu o’ch cyfrif ac nid yw eich manylion talu wedi cael eu harbed ar gyfer y taliad cerdyn sy’n ailadrodd.",
603
604
  "payment_failed_rejected": "Mae’r taliad wedi cael ei wrthod gan ddarparwr y taliad. Sicrhewch eich bod wedi mewnbynnu manylion eich cerdyn yn gywir a bod digon o arian ar gael yn eich cyfrif",
604
605
  "payment_failed_title_1": "Mae eich cais i dalu wedi dod i ben",
605
606
  "payment_failed_title_2": "Mae eich taliad wedi cael ei wrthod",
@@ -603,6 +603,7 @@
603
603
  "payment_cancelled_title": "Your payment has been cancelled",
604
604
  "payment_failed_expired": "The payment was not completed within 90 minutes of being created",
605
605
  "payment_failed_not_taken": "No money has been taken from your account.",
606
+ "payment_failed_not_taken_recurring": "No money has been taken from your account and your payment details have not been saved for the recurring card payment.",
606
607
  "payment_failed_rejected": "The payment was rejected by the payment provider. Please ensure that you entered your card details correctly and that you have sufficient funds in your account",
607
608
  "payment_failed_title_1": "Your payment has expired",
608
609
  "payment_failed_title_2": "Your payment was rejected",
@@ -5,6 +5,7 @@ import { COMPLETION_STATUS, FEEDBACK_URI_DEFAULT } from '../../../../constants.j
5
5
  import { displayStartTime } from '../../../../processors/date-and-time-display.js'
6
6
  import { LICENCE_TYPE } from '../../../../processors/mapping-constants.js'
7
7
  import { displayPrice } from '../../../../processors/price-display.js'
8
+ import { isRecurringPayment } from '../../../../processors/recurring-pay-helper.js'
8
9
 
9
10
  jest.mock('../../../../processors/recurring-pay-helper.js')
10
11
  jest.mock('../../../../processors/date-and-time-display.js')
@@ -61,6 +62,11 @@ const getSamplePermission = ({
61
62
  isRecurringPayment
62
63
  })
63
64
 
65
+ const getSampleTransaction = ({ transactionCost = 1, agreementId } = {}) => ({
66
+ cost: transactionCost,
67
+ agreementId
68
+ })
69
+
64
70
  const getSampleCompletionStatus = ({ agreed = true, posted = true, finalised = true, setUpPayment = true } = {}) => ({
65
71
  [COMPLETION_STATUS.agreed]: agreed,
66
72
  [COMPLETION_STATUS.posted]: posted,
@@ -102,11 +108,12 @@ const getMessages = () => ({
102
108
  const getSampleRequest = ({
103
109
  completionStatus = getSampleCompletionStatus(),
104
110
  permission = getSamplePermission(),
111
+ transactionCost = 1,
112
+ agreementId,
113
+ transaction = getSampleTransaction({ transactionCost, agreementId }),
105
114
  statusSet = () => {},
106
115
  statusSetCurrentPermission = () => {},
107
- transactionCost = 1,
108
- messages = getMessages(),
109
- agreementId
116
+ messages = getMessages()
110
117
  } = {}) => ({
111
118
  cache: () => ({
112
119
  helpers: {
@@ -116,10 +123,7 @@ const getSampleRequest = ({
116
123
  set: statusSet
117
124
  },
118
125
  transaction: {
119
- get: async () => ({
120
- cost: transactionCost,
121
- agreementId
122
- }),
126
+ get: async () => transaction,
123
127
  getCurrentPermission: () => permission
124
128
  }
125
129
  }
@@ -206,25 +210,6 @@ describe('The order completion handler', () => {
206
210
  expect(displayStartTime).toHaveBeenCalledWith(request, permission)
207
211
  })
208
212
 
209
- it.each`
210
- show | agreementId | expected
211
- ${true} | ${'foo123'} | ${true}
212
- ${true} | ${undefined} | ${false}
213
- ${false} | ${'foo123'} | ${false}
214
- ${false} | ${undefined} | ${false}
215
- `(
216
- 'recurringPayment returns $expected when SHOW_RECURRING_PAYMENTS is $show and the transaction agreementId is $agreementId',
217
- async ({ show, agreementId, expected }) => {
218
- process.env.SHOW_RECURRING_PAYMENTS = show
219
- const request = getSampleRequest({ agreementId })
220
- const { recurringPayment } = await getData(request)
221
-
222
- expect(recurringPayment).toBe(expected)
223
-
224
- delete process.env.SHOW_RECURRING_PAYMENTS
225
- }
226
- )
227
-
228
213
  it('uses displayStartTime to generate startTimeStringTitle', async () => {
229
214
  const startTime = Symbol('one minute to midnight')
230
215
  displayStartTime.mockReturnValueOnce(startTime)
@@ -232,6 +217,20 @@ describe('The order completion handler', () => {
232
217
  expect(startTimeStringTitle).toBe(startTime)
233
218
  })
234
219
 
220
+ it('passes transaction to isRecurringPayment', async () => {
221
+ const transaction = getSampleTransaction({ agreementId: Symbol('agreement') })
222
+ const request = getSampleRequest({ transaction })
223
+ await getData(request)
224
+ expect(isRecurringPayment).toHaveBeenCalledWith(transaction)
225
+ })
226
+
227
+ it('uses isRecurringPayment to generate recurringPayment', async () => {
228
+ const expectedValue = Symbol('yep!')
229
+ isRecurringPayment.mockReturnValueOnce(expectedValue)
230
+ const { recurringPayment } = await getData(getSampleRequest())
231
+ expect(recurringPayment).toBe(expectedValue)
232
+ })
233
+
235
234
  it.each`
236
235
  permission | expectedValue
237
236
  ${getSamplePermission()} | ${false}
@@ -8,6 +8,7 @@ import { nextPage } from '../../../routes/next-page.js'
8
8
  import { addLanguageCodeToUri } from '../../../processors/uri-helper.js'
9
9
  import { displayPrice } from '../../../processors/price-display.js'
10
10
  import { HOW_CONTACTED } from '../../../processors/mapping-constants.js'
11
+ import { isRecurringPayment } from '../../../processors/recurring-pay-helper.js'
11
12
 
12
13
  export const getData = async request => {
13
14
  const status = await request.cache().helpers.status.get()
@@ -58,8 +59,6 @@ const postalFulfilment = permission => {
58
59
  }
59
60
  }
60
61
 
61
- const isRecurringPayment = transaction => process.env.SHOW_RECURRING_PAYMENTS?.toLowerCase() === 'true' && !!transaction.agreementId
62
-
63
62
  const digitalConfirmation = permission =>
64
63
  permission.licensee.preferredMethodOfConfirmation === HOW_CONTACTED.email ||
65
64
  permission.licensee.preferredMethodOfConfirmation === HOW_CONTACTED.text
@@ -1,18 +1,27 @@
1
1
  import { NEW_TRANSACTION } from '../../../../uri.js'
2
2
  import { addLanguageCodeToUri } from '../../../../processors/uri-helper.js'
3
+ import { isRecurringPayment } from '../../../../processors/recurring-pay-helper.js'
3
4
  import { getData } from '../route.js'
4
5
  import { COMPLETION_STATUS } from '../../../../constants.js'
5
6
 
6
7
  beforeEach(jest.clearAllMocks)
7
8
  jest.mock('../../../../processors/uri-helper.js')
9
+ jest.mock('../../../../processors/recurring-pay-helper.js')
8
10
 
9
- const getMockRequest = () => ({
11
+ const getMockTransaction = agreementId => ({
12
+ agreementId
13
+ })
14
+
15
+ const getMockRequest = ({ transaction = getMockTransaction() } = {}) => ({
10
16
  cache: () => ({
11
17
  helpers: {
12
18
  status: {
13
19
  get: () => ({
14
20
  [COMPLETION_STATUS.paymentCreated]: true
15
21
  })
22
+ },
23
+ transaction: {
24
+ get: async () => transaction
16
25
  }
17
26
  }
18
27
  })
@@ -32,4 +41,18 @@ describe('getData', () => {
32
41
  const result = await getData(getMockRequest())
33
42
  expect(result.uri.new).toEqual(expectedUri)
34
43
  })
44
+
45
+ it('passes transaction to isRecurringPayment', async () => {
46
+ const transaction = getMockTransaction(Symbol('agreement'))
47
+ const request = getMockRequest({ transaction })
48
+ await getData(request)
49
+ expect(isRecurringPayment).toHaveBeenCalledWith(transaction)
50
+ })
51
+
52
+ it('uses isRecurringPayment to generate recurringPayment', async () => {
53
+ const expectedValue = Symbol('yep!')
54
+ isRecurringPayment.mockReturnValueOnce(expectedValue)
55
+ const { recurringPayment } = await getData(getMockRequest())
56
+ expect(recurringPayment).toBe(expectedValue)
57
+ })
35
58
  })
@@ -18,7 +18,11 @@
18
18
  }
19
19
  }) %}
20
20
 
21
- <p class="govuk-body-m">{{ mssgs.payment_failed_not_taken }}</p>
21
+ {% if data.recurringPayment %}
22
+ <p class="govuk-body-m">{{ mssgs.payment_failed_not_taken_recurring }}</p>
23
+ {% else %}
24
+ <p class="govuk-body-m">{{ mssgs.payment_failed_not_taken }}</p>
25
+ {% endif %}
22
26
 
23
27
  {% endcall %}
24
28
 
@@ -3,11 +3,13 @@ import pageRoute from '../../../routes/page-route.js'
3
3
  import { PAYMENT_CANCELLED, NEW_TRANSACTION } from '../../../uri.js'
4
4
  import { nextPage } from '../../../routes/next-page.js'
5
5
  import { addLanguageCodeToUri } from '../../../processors/uri-helper.js'
6
+ import { isRecurringPayment } from '../../../processors/recurring-pay-helper.js'
6
7
 
7
8
  import { COMPLETION_STATUS } from '../../../constants.js'
8
9
 
9
10
  export const getData = async request => {
10
11
  const status = await request.cache().helpers.status.get()
12
+ const transaction = await request.cache().helpers.transaction.get()
11
13
 
12
14
  // If the payment created flag is not set to true then throw an exception
13
15
  if (!status[COMPLETION_STATUS.paymentCreated]) {
@@ -15,6 +17,7 @@ export const getData = async request => {
15
17
  }
16
18
 
17
19
  return {
20
+ recurringPayment: isRecurringPayment(transaction),
18
21
  uri: {
19
22
  new: addLanguageCodeToUri(request, NEW_TRANSACTION.uri)
20
23
  }
@@ -1,13 +1,19 @@
1
1
  import { NEW_TRANSACTION } from '../../../../uri.js'
2
2
  import { addLanguageCodeToUri } from '../../../../processors/uri-helper.js'
3
+ import { isRecurringPayment } from '../../../../processors/recurring-pay-helper.js'
3
4
  import { getData } from '../route.js'
4
5
  import { COMPLETION_STATUS } from '../../../../constants.js'
5
6
  import { GOVUK_PAY_ERROR_STATUS_CODES } from '@defra-fish/business-rules-lib'
6
7
 
7
8
  beforeEach(jest.clearAllMocks)
8
9
  jest.mock('../../../../processors/uri-helper.js')
10
+ jest.mock('../../../../processors/recurring-pay-helper.js')
9
11
 
10
- const getMockRequest = code => ({
12
+ const getMockTransaction = agreementId => ({
13
+ agreementId
14
+ })
15
+
16
+ const getMockRequest = ({ code, transaction = getMockTransaction() } = {}) => ({
11
17
  cache: () => ({
12
18
  helpers: {
13
19
  status: {
@@ -17,6 +23,9 @@ const getMockRequest = code => ({
17
23
  code: code
18
24
  }
19
25
  })
26
+ },
27
+ transaction: {
28
+ get: async () => transaction
20
29
  }
21
30
  }
22
31
  })
@@ -38,7 +47,7 @@ describe('getData', () => {
38
47
  })
39
48
 
40
49
  it.each(['738483', '123454', '2983923'])('returns correct failure code', async failureCode => {
41
- const result = await getData(getMockRequest(failureCode))
50
+ const result = await getData(getMockRequest({ code: failureCode }))
42
51
  expect(result['failure-code']).toEqual(failureCode)
43
52
  })
44
53
 
@@ -46,4 +55,18 @@ describe('getData', () => {
46
55
  const result = await getData(getMockRequest())
47
56
  expect(result.codes).toEqual(GOVUK_PAY_ERROR_STATUS_CODES)
48
57
  })
58
+
59
+ it('passes transaction to isRecurringPayment', async () => {
60
+ const transaction = getMockTransaction(Symbol('agreement'))
61
+ const request = getMockRequest({ transaction })
62
+ await getData(request)
63
+ expect(isRecurringPayment).toHaveBeenCalledWith(transaction)
64
+ })
65
+
66
+ it('uses isRecurringPayment to generate recurringPayment', async () => {
67
+ const expectedValue = Symbol('yep!')
68
+ isRecurringPayment.mockReturnValueOnce(expectedValue)
69
+ const { recurringPayment } = await getData(getMockRequest())
70
+ expect(recurringPayment).toBe(expectedValue)
71
+ })
49
72
  })
@@ -31,7 +31,12 @@
31
31
  {% elseif data['failure-code'] === data.codes.REJECTED %}
32
32
  <p class="govuk-body-m">{{ mssgs.payment_failed_rejected }}</p>
33
33
  {% endif %}
34
- <p class="govuk-body-m">{{ mssgs.payment_failed_not_taken }}</p>
34
+
35
+ {% if data.recurringPayment %}
36
+ <p class="govuk-body-m">{{ mssgs.payment_failed_not_taken_recurring }}</p>
37
+ {% else %}
38
+ <p class="govuk-body-m">{{ mssgs.payment_failed_not_taken }}</p>
39
+ {% endif %}
35
40
 
36
41
  {% endcall %}
37
42
 
@@ -5,9 +5,11 @@ import { COMPLETION_STATUS } from '../../../constants.js'
5
5
  import { PAYMENT_FAILED, NEW_TRANSACTION } from '../../../uri.js'
6
6
  import { nextPage } from '../../../routes/next-page.js'
7
7
  import { addLanguageCodeToUri } from '../../../processors/uri-helper.js'
8
+ import { isRecurringPayment } from '../../../processors/recurring-pay-helper.js'
8
9
 
9
10
  export const getData = async request => {
10
11
  const status = await request.cache().helpers.status.get()
12
+ const transaction = await request.cache().helpers.transaction.get()
11
13
 
12
14
  // If the cancelled flag is not set to true then throw an exception
13
15
  if (!status[COMPLETION_STATUS.paymentFailed]) {
@@ -17,6 +19,7 @@ export const getData = async request => {
17
19
  return {
18
20
  codes: GOVUK_PAY_ERROR_STATUS_CODES,
19
21
  'failure-code': status.payment.code,
22
+ recurringPayment: isRecurringPayment(transaction),
20
23
  uri: {
21
24
  new: addLanguageCodeToUri(request, NEW_TRANSACTION.uri)
22
25
  }
@@ -1,4 +1,4 @@
1
- import { recurringPayReminderDisplay, validForRecurringPayment } from '../recurring-pay-helper.js'
1
+ import { isRecurringPayment, recurringPayReminderDisplay, validForRecurringPayment } from '../recurring-pay-helper.js'
2
2
 
3
3
  const getCatalog = () => ({
4
4
  recurring_payment_set_up_bulletpoint_5_email: 'we will send you an email showing the cost before the next payment is taken',
@@ -29,13 +29,13 @@ describe('recurringPayReminderDisplay', () => {
29
29
 
30
30
  describe('validForRecurringPayment', () => {
31
31
  test.each`
32
- expected | length | licenceFor | recurring | telesales | birthDate
33
- ${true} | ${'12M'} | ${true} | ${true} | ${'not telesales'} | ${'1946-01-01'}
34
- ${false} | ${'8D'} | ${true} | ${true} | ${'not telesales'} | ${'1946-01-01'}
35
- ${false} | ${'12M'} | ${false} | ${true} | ${'not telesales'} | ${'1946-01-01'}
36
- ${false} | ${'12M'} | ${true} | ${false} | ${'not telesales'} | ${'1946-01-01'}
37
- ${false} | ${'12M'} | ${true} | ${true} | ${'telesales'} | ${'1946-01-01'}
38
- ${false} | ${'12M'} | ${true} | ${true} | ${'not telesales'} | ${'2010-01-01'}
32
+ expected | length | licenceFor | recurring | telesales | birthDate
33
+ ${true} | ${'12M'} | ${true} | ${true} | ${'not telesales'} | ${'1946-01-01'}
34
+ ${false} | ${'8D'} | ${true} | ${true} | ${'not telesales'} | ${'1946-01-01'}
35
+ ${false} | ${'12M'} | ${false} | ${true} | ${'not telesales'} | ${'1946-01-01'}
36
+ ${false} | ${'12M'} | ${true} | ${false} | ${'not telesales'} | ${'1946-01-01'}
37
+ ${false} | ${'12M'} | ${true} | ${true} | ${'telesales'} | ${'1946-01-01'}
38
+ ${false} | ${'12M'} | ${true} | ${true} | ${'not telesales'} | ${'2010-01-01'}
39
39
  `(
40
40
  'should return %s as licence length is %s, licence for you is %s, SHOW_RECURRING_PAYMENTS is %s, journey is %s, and birthDate is %s',
41
41
  ({ expected, length, licenceFor, recurring, telesales, birthDate }) => {
@@ -47,3 +47,23 @@ describe('validForRecurringPayment', () => {
47
47
  }
48
48
  )
49
49
  })
50
+
51
+ describe('isRecurringPayment', () => {
52
+ it.each`
53
+ show | agreementId | expected
54
+ ${true} | ${'foo123'} | ${true}
55
+ ${true} | ${undefined} | ${false}
56
+ ${false} | ${'foo123'} | ${false}
57
+ ${false} | ${undefined} | ${false}
58
+ `(
59
+ 'recurringPayment returns $expected when SHOW_RECURRING_PAYMENTS is $show and the transaction agreementId is $agreementId',
60
+ async ({ show, agreementId, expected }) => {
61
+ process.env.SHOW_RECURRING_PAYMENTS = show
62
+ const transaction = { agreementId }
63
+
64
+ expect(isRecurringPayment(transaction)).toBe(expected)
65
+
66
+ delete process.env.SHOW_RECURRING_PAYMENTS
67
+ }
68
+ )
69
+ })
@@ -21,3 +21,5 @@ export const validForRecurringPayment = permission => {
21
21
  process.env.CHANNEL?.toLowerCase() !== 'telesales'
22
22
  )
23
23
  }
24
+
25
+ export const isRecurringPayment = transaction => process.env.SHOW_RECURRING_PAYMENTS?.toLowerCase() === 'true' && !!transaction.agreementId