@defra-fish/gafl-webapp-service 1.59.0-rc.1 → 1.59.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/gafl-webapp-service",
3
- "version": "1.59.0-rc.1",
3
+ "version": "1.59.0-rc.3",
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.1",
40
- "@defra-fish/connectors-lib": "1.59.0-rc.1",
39
+ "@defra-fish/business-rules-lib": "1.59.0-rc.3",
40
+ "@defra-fish/connectors-lib": "1.59.0-rc.3",
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": "c77fb64b7adae9c187d4d3cbbad06c5b0203be9e"
83
+ "gitHead": "ba5b2afbe6d3c096d813ce3445c39db2c088523d"
84
84
  }
@@ -478,8 +478,8 @@
478
478
  "licence_type_12m": "12 mis",
479
479
  "licence_type_1d": "1 diwrnod",
480
480
  "licence_type_8d": "8 niwrnod",
481
- "licence_type_attended_rods_note": "Dim ond deiliaid y drwydded all defnyddio’r wialen, ac mae’n rhaid cadw golwg ar y wialen drwy’r amser.",
482
- "licence_type_byelaws": "is-ddeddfau pysgota lleol (yn agor ar dudalen newydd)",
481
+ "licence_type_attended_rods_note": "Dim ond deiliad y drwydded all ddefnyddio’r wialen ac mae’n rhaid cadw golwg ar y wialen drwy’r amser. Mae’n rhaid i ddeiliaid y drwydded ddilyn yr ",
482
+ "licence_type_byelaws": "is-ddeddfau pysgota â gwialen (yn agor mewn tab newydd)",
483
483
  "licence_type_error_choose": "Dewiswch un o’r mathau o drwyddedau pysgota",
484
484
  "licence_type_na": "Nid oes cyfnodau byrrach ar gael ar gyfer y math hwn o drwydded.",
485
485
  "licence_type_payment_edge_case": "Mae’n rhaid i chi gwblhau eich taliad cyn 11:30pm ar 31 Mawrth 2025 i dalu’r pris a ddangosir",
@@ -491,15 +491,17 @@
491
491
  "licence_type_radio_trout_two_rod": "Brithyllod a physgod bras (hyd at 2 wialen)",
492
492
  "licence_type_radio_trout_two_rod_payment_summary": "Brithyllod a physgod bras (hyd at 2 wialen)",
493
493
  "licence_type_rules": "rheolau pysgota â gwialen (yn agor ar dudalen newydd)",
494
- "licence_type_salmon_acr_note_1": "Yn ôl y gyfraith, mae'n rhaid i chi roi gwybod am ",
495
- "licence_type_salmon_acr_note_2": " ffurflen daliadau (yn agor ar dudalen newydd)",
496
- "licence_type_salmon_acr_note_3": " o'ch gweithgarwch pysgota eog a brithyllod môr blynyddol yng Nghymru a Lloegr, hyd yn oed os nad ydych yn dal unrhyw beth neu os nad ydych yn pysgota.",
497
- "licence_type_salmon_acr_warning": "Bydd angen i chi gyflwyno ffurflen dalfa flynyddol",
494
+ "licence_type_salmon_acr_note_1": "Mae’n cwmpasu pysgota ar gyfer eogiaid a brithyllod y môr gan ddefnyddio hyd at 2 wialen, yn ogystal â brithyllod anfudol a physgod dŵr croyw gan ddefnyddio hyd at 3 gwialen.",
495
+ "licence_type_salmon_acr_note_2": "Mae’n rhaid i chi ",
496
+ "licence_type_salmon_acr_note_3": " pan fyddwch wedi gorffen pysgota am y flwyddyn, hyd yn oed os nad ydych wedi dal unrhyw eogiaid na brithyllod y môr.",
497
+ "licence_type_salmon_acr_note_2_BOBO": "Mae’n rhaid iddynt ",
498
+ "licence_type_salmon_acr_note_3_BOBO": " pan fyddant wedi gorffen pysgota am y flwyddyn, hyd yn oed os nad ydynt wedi dal unrhyw eogiaid na brithyllod y môr.",
499
+ "licence_type_salmon_acr_note_link": "gyflwyno ffurflen ddalfa flynyddol (yn agor mewn tab newydd)",
498
500
  "licence_type_salmon_junior": "You’ll only need this licence if you are specifically fishing for salmon or sea trout.",
499
- "licence_type_title_other": "Pa fath o drwydded yr hoffent ei chael?",
500
- "licence_type_title_you": "Pa drwydded hoffech chi ei chael?",
501
- "licence_type_troute_three_rod": "Dim ond trwydded tair gwialen y bydd ei hangen arnoch os ydych yn bwriadu pysgota â thair gwialen ar yr un pryd. Gall hyn fod ar gyfer pysgota cerpynnod arbenigol, er enghraifft. Bydd hyn yn addas ar gyfer pob math o bysgota â gwialen ac yn gadael i chi bysgota brithyllod anfudol a physgod bras, yn amodol ar y ",
502
- "licence_type_troute_two_rod": "Y drwydded pysgod bras â dwy wialen ywr drwydded wialen symlaf. Bydd hyn yn eich gwarchod ar gyfer pob math o bysgota gyda gwialen ac yn gadael i chi bysgota brithyllod anfudol a physgod bras. Bydd yn caniatáu i chi bysgota gydag un neu ddwy wialen ar yr un pryd, yn amodol ar y ",
501
+ "licence_type_title_other": "Pa fath o drwydded sydd ei hangen arnynt?",
502
+ "licence_type_title_you": "Pa fath o drwydded sydd ei hangen arnoch?",
503
+ "licence_type_trout_three_rod": "Mae’n cwmpasu brithyllod anfudol a phob pysgodyn dŵr croyw, ond nid eogiaid na brithyllod y môr. Mae’r holl ddulliau pysgota gan ddefnyddio hyd at 3 gwialen wedi’u cwmpasu. Er enghraifft pysgota arbenigol ar gyfer carp gan ddefnyddio 3 gwialen ar yr un pryd.",
504
+ "licence_type_trout_two_rod": "Maen cwmpasu brithyllod anfudol a phob pysgodyn dŵr croyw, ond nid eogiaid na brithyllod y môr. Mae’r holl ddulliau pysgota gan ddefnyddio hyd at 2 wialen wedi’u cwmpasu.",
503
505
  "name_abbr_hint": "Peidiwch â defnyddio byrfoddau na llysenwau",
504
506
  "name_first_empty_error_msg": "Rhowch yr enw cyntaf",
505
507
  "name_first_empty_error": "Rhowch enw cyntaf deiliad y drwydded",
@@ -743,7 +745,7 @@
743
745
  "renewal_inactive_title_4": "You can ",
744
746
  "renewal_inactive_title_link": "buy a new licence.",
745
747
  "renewal_start_date_error_format": "Nid yw hwn yn ddyddiad dilys. Rhowch y dyddied yr hoffech i’r drwydded ddechrau gan gynnwys y diwrnod, mis a’r flwyddyn",
746
- "renewal_start_date_error_hint_1": "Rhowch ddyddiad rhwng ",
748
+ "renewal_start_date_error_hint": "Rhowch ddyddiad rhwng ",
747
749
  "renewal_start_date_error_max_1": "Mae’n rhaid i’r trwydded newydd ddechrau o fewn ",
748
750
  "renewal_start_date_error_max_2": " diwrnod i ddyddiad terfyn eich trwydded bresennol. Rhowch ddyddiad hyd at a gan gynnwys ",
749
751
  "renewal_start_date_error_min": "Ni all y drwydded ddechrau cyn i’ch trwydded bresennol ddod i ben",
@@ -478,8 +478,8 @@
478
478
  "licence_type_12m": "12 months",
479
479
  "licence_type_1d": "1 day",
480
480
  "licence_type_8d": "8 days",
481
- "licence_type_attended_rods_note": "Rods are for use by the licence holder only and must be attended at all times.",
482
- "licence_type_byelaws": "local fishing byelaws (opens in new tab)",
481
+ "licence_type_attended_rods_note": "Rods must only be used by the licence holder and must be attended at all times. You must follow the ",
482
+ "licence_type_byelaws": "rod fishing byelaws (opens in new tab)",
483
483
  "licence_type_error_choose": "Choose one of the fishing licence types",
484
484
  "licence_type_na": "Shorter lengths are not available for this licence type",
485
485
  "licence_type_payment_edge_case": "You must complete payment before 11:30pm on 31 March 2025 to get the price shown",
@@ -491,15 +491,17 @@
491
491
  "licence_type_radio_trout_two_rod": "Trout and coarse (up to 2 rods)",
492
492
  "licence_type_radio_trout_two_rod_payment_summary": "Trout and coarse (up to 2 rods)",
493
493
  "licence_type_rules": "rod fishing rules (opens in new tab)",
494
- "licence_type_salmon_acr_note_1": "Licence holders must by law ",
495
- "licence_type_salmon_acr_note_2": " report a catch return (opens in new tab)",
496
- "licence_type_salmon_acr_note_3": "of yearly salmon and sea trout fishing activity in England and Wales, even if they did not fish or catch anything.",
497
- "licence_type_salmon_acr_warning": "Salmon and sea trout licence holders will need to submit an annual catch return",
494
+ "licence_type_salmon_acr_note_1": "Covers salmon and sea trout using up to 2 rods and also non-migratory trout and all freshwater fish using up to 3 rods.",
495
+ "licence_type_salmon_acr_note_2": "You must ",
496
+ "licence_type_salmon_acr_note_3": " when you have finished fishing for the year, even if you did not catch any salmon or sea trout or did not go fishing.",
497
+ "licence_type_salmon_acr_note_2_BOBO": "The licence holder must ",
498
+ "licence_type_salmon_acr_note_3_BOBO": " when they have finished fishing for the year, even if they did not catch any salmon or sea trout or did not go fishing.",
499
+ "licence_type_salmon_acr_note_link": "report an annual catch return (opens in new tab)",
498
500
  "licence_type_salmon_junior": "You’ll only need this licence if you are specifically fishing for salmon or sea trout.",
499
- "licence_type_title_other": "Which type of licence do they want?",
500
- "licence_type_title_you": "Which type of licence do you want?",
501
- "licence_type_troute_three_rod": "This licence will suit anglers planning to fish with 3 rods at the same time. This may be for specialist carp fishing for example. This will cover the licence holder for all the forms of fishing with a rod and allow non-migratory trout and coarse fishing, subject to the ",
502
- "licence_type_troute_two_rod": "The 2 rods coarse licence is the simplest fishing licence. This will cover all the forms of fishing with a rod and let the licence holder fish non-migratory trout and coarse fish. It will allow the licence holder to fish with 1 or 2 rods at the same time, subject to the ",
501
+ "licence_type_title_other": "Which type of licence do they need?",
502
+ "licence_type_title_you": "Which type of licence do you need?",
503
+ "licence_type_trout_three_rod": "Covers non-migratory trout and all freshwater fish, but not salmon or sea trout. All rod fishing methods using up to 3 rods are covered. For example, specialist carp fishing using 3 rods at the same time.",
504
+ "licence_type_trout_two_rod": "Covers non-migratory trout and all freshwater fish, but not salmon or sea trout. All rod fishing methods using up to 2 rods are covered.",
503
505
  "name_abbr_hint": "Do not use abbreviations or nicknames",
504
506
  "name_first_empty_error_msg": "Enter the first name",
505
507
  "name_first_empty_error": "Enter the licence holder’s first name",
@@ -743,7 +745,7 @@
743
745
  "renewal_inactive_title_4": "You can ",
744
746
  "renewal_inactive_title_link": "buy a new licence.",
745
747
  "renewal_start_date_error_format": "Not a valid date. Enter the date you want the licence to start on and include a day, month and year",
746
- "renewal_start_date_error_hint_1": "Enter a date between ",
748
+ "renewal_start_date_error_hint": "Enter a date between ",
747
749
  "renewal_start_date_error_max_1": "Your new licence must start within ",
748
750
  "renewal_start_date_error_max_2": " days of your current licence expiring. Enter a date up to and including ",
749
751
  "renewal_start_date_error_min": "The licence must not start before your current licence has expired",
@@ -15,29 +15,26 @@
15
15
  %}
16
16
 
17
17
  {% set troutAndCoarse2Rod %}
18
- <p class="govuk-body-m">
19
- {{ mssgs.licence_type_troute_two_rod }}
20
- <a class="govuk-link" rel="noreferrer noopener" target="_blank" href="{{ data.uri.freshWaterFishingRules }}">{{ mssgs.licence_type_rules }}</a>{{ mssgs.and }}<a class="govuk-link" rel="noreferrer noopener" target="_blank" href="{{ data.uri.localByelaws }}">{{ mssgs.licence_type_byelaws }}</a>{{ mssgs.full_stop }}
21
- </p>
18
+ <p class="govuk-body-m"> {{ mssgs.licence_type_trout_two_rod }}</p>
22
19
  {% endset -%}
23
20
 
24
21
  {% set troutAndCoarse3Rod %}
25
- <p class="govuk-body-m">
26
- {{ mssgs.licence_type_troute_three_rod }}
27
- <a class="govuk-link" rel="noreferrer noopener" target="_blank" href="{{ data.uri.freshWaterFishingRules }}">{{ mssgs.licence_type_rules }}</a>{{ mssgs.and }}<a class="govuk-link" rel="noreferrer noopener" target="_blank" href="{{ data.uri.localByelaws }}">{{ mssgs.licence_type_byelaws }}</a>{{ mssgs.full_stop }}
28
- </p>
22
+ <p class="govuk-body-m"> {{ mssgs.licence_type_trout_three_rod }}</p>
29
23
  {% endset -%}
30
24
 
31
25
  {% set salmonAndSeaTrout %}
32
26
  {% if data.hasJunior %}<p class="govuk-body-m">{{ mssgs.licence_type_salmon_junior }}</p>{% endif %}
33
- {{ govukWarningText({
34
- text: mssgs.licence_type_salmon_acr_warning,
35
- iconFallbackText: "Warning",
36
- classes: "govuk-!-margin-top-6"
37
- }) }}
38
27
  <p class="govuk-body-m">
39
- {{ mssgs.licence_type_salmon_acr_note_1 }}<a class="govuk-link" rel="noreferrer noopener" target="_blank" href="https://www.gov.uk/catch-return">{{ mssgs.licence_type_salmon_acr_note_2 }}</a>
40
- {{ mssgs.licence_type_salmon_acr_note_3 }}</p>
28
+ {{ mssgs.licence_type_salmon_acr_note_1 }}</p>
29
+ <p class="govuk-body-m">
30
+ {% if data.isLicenceForYou %}
31
+ {{ mssgs.licence_type_salmon_acr_note_2 }} <a class="govuk-link" rel="noreferrer noopener" target="_blank" href="{{ data.uri.catchReturn }}">{{ mssgs.licence_type_salmon_acr_note_link }}</a>
32
+ {{ mssgs.licence_type_salmon_acr_note_3 }}
33
+ {% else %}
34
+ {{ mssgs.licence_type_salmon_acr_note_2_BOBO }} <a class="govuk-link" rel="noreferrer noopener" target="_blank" href="{{ data.uri.catchReturn }}">{{ mssgs.licence_type_salmon_acr_note_link }}</a>
35
+ {{ mssgs.licence_type_salmon_acr_note_3_BOBO }}
36
+ {% endif %}
37
+ </p>
41
38
  {% endset -%}
42
39
 
43
40
  {% set items = [
@@ -59,7 +56,6 @@
59
56
  id: 'selector-' + data.licenseTypes.salmonAndSeaTrout,
60
57
  text: mssgs.licence_type_radio_salmon,
61
58
  value: "salmon-and-sea-trout",
62
- hint: { text: mssgs.licence_type_radio_salmon_hint },
63
59
  checked: payload['licence-type'] === data.licenseTypes.salmonAndSeaTrout,
64
60
  conditional: { html: salmonAndSeaTrout }
65
61
  }
@@ -67,7 +63,8 @@
67
63
  %}
68
64
 
69
65
  {% block pageContent %}
70
- <p class="govuk-body-m">{{ mssgs.licence_type_attended_rods_note }}</p>
66
+ <p class="govuk-body-m">{{ mssgs.licence_type_attended_rods_note }}<a class="govuk-link" rel="noreferrer noopener" target="_blank" href="{{ data.uri.freshWaterFishingRules }}">{{ mssgs.licence_type_byelaws }}</a>{{ mssgs.full_stop }}
67
+ </p>
71
68
  {{ govukRadios({
72
69
  idPrefix: "licence-type",
73
70
  name: "licence-type",
@@ -1,4 +1,4 @@
1
- import { LICENCE_TYPE, FRESHWATER_FISING_RULES, LOCAL_BYELAWS } from '../../../uri.js'
1
+ import { LICENCE_TYPE, FRESHWATER_FISING_RULES, LOCAL_BYELAWS, CATCH_RETURN } from '../../../uri.js'
2
2
  import pageRoute from '../../../routes/page-route.js'
3
3
  import { pricingDetail } from '../../../processors/pricing-summary.js'
4
4
  import Joi from 'joi'
@@ -29,7 +29,8 @@ export const getData = async request => {
29
29
  hasJunior: concessionHelper.hasJunior(permission),
30
30
  uri: {
31
31
  freshWaterFishingRules: FRESHWATER_FISING_RULES.uri,
32
- localByelaws: LOCAL_BYELAWS.uri
32
+ localByelaws: LOCAL_BYELAWS.uri,
33
+ catchReturn: CATCH_RETURN.uri
33
34
  }
34
35
  }
35
36
  }
@@ -5,7 +5,7 @@ Object {
5
5
  "advancedPurchaseMaxDays": 30,
6
6
  "expiryTimeString": Symbol(expiryDate),
7
7
  "hasExpired": undefined,
8
- "maxStartDate": "09 02 2023",
9
- "minStartDate": "10 01 2023",
8
+ "maxStartDateMessage": "Renewal start date error max 1 30 renewal start date error max 209 02 2023",
9
+ "renewalHint": "Renewal start date error hint10 01 2023and09 02 2023",
10
10
  }
11
11
  `;
@@ -44,7 +44,7 @@ jest.mock('../../../../routes/page-route.js')
44
44
 
45
45
  const mockTransactionSet = jest.fn()
46
46
 
47
- const getMockRequest = (permission = getSamplePermission(), year, month, day) => ({
47
+ const getMockRequest = ({ permission = getSamplePermission(), year = '2025', month = '1', day = '01', error = null } = {}) => ({
48
48
  cache: () => ({
49
49
  helpers: {
50
50
  status: {
@@ -57,7 +57,8 @@ const getMockRequest = (permission = getSamplePermission(), year, month, day) =>
57
57
  'licence-start-date-year': year,
58
58
  'licence-start-date-month': month,
59
59
  'licence-start-date-day': day
60
- }
60
+ },
61
+ error
61
62
  }),
62
63
  setCurrentPermission: jest.fn()
63
64
  },
@@ -68,7 +69,7 @@ const getMockRequest = (permission = getSamplePermission(), year, month, day) =>
68
69
  }
69
70
  }),
70
71
  i18n: {
71
- getCatalog: () => [],
72
+ getCatalog: () => getMessages(),
72
73
  getLocales: () => []
73
74
  },
74
75
  url: {
@@ -76,6 +77,13 @@ const getMockRequest = (permission = getSamplePermission(), year, month, day) =>
76
77
  }
77
78
  })
78
79
 
80
+ const getMessages = () => ({
81
+ and: 'and',
82
+ renewal_start_date_error_hint: 'Renewal start date error hint',
83
+ renewal_start_date_error_max_1: 'Renewal start date error max 1 ',
84
+ renewal_start_date_error_max_2: ' renewal start date error max 2'
85
+ })
86
+
79
87
  const getSamplePermission = ({ renewedEndDate = '2023-01-10:00:00.000Z' } = {}) => ({
80
88
  licensee: {
81
89
  noLicenceRequired: {}
@@ -131,6 +139,21 @@ describe('getData', () => {
131
139
  expect(displayExpiryDate).toHaveBeenCalledWith(request, permission)
132
140
  })
133
141
 
142
+ it.each([
143
+ ['full-date', 'object.missing'],
144
+ ['day', 'any.required']
145
+ ])('should add error details ({%s: %s}) to the page data', async (errorKey, errorValue) => {
146
+ const error = { [errorKey]: errorValue }
147
+
148
+ const result = await getData(getMockRequest({ error }))
149
+ expect(result.error).toEqual({ errorKey, errorValue })
150
+ })
151
+
152
+ it('omits error if there is no error', async () => {
153
+ const result = await getData(getMockRequest())
154
+ expect(result.error).toBeUndefined()
155
+ })
156
+
134
157
  it('getData returns expected outputs', async () => {
135
158
  const expected = await getData(getMockRequest())
136
159
  expect(expected).toMatchSnapshot()
@@ -143,7 +166,7 @@ describe('setLicenceStartDateAndTime', () => {
143
166
 
144
167
  it('ageConcessionHelper is called with permission', async () => {
145
168
  const permission = { licenceStartDate: '2023-02-11T12:00:00.000Z' }
146
- await setLicenceStartDateAndTime(getMockRequest(permission))
169
+ await setLicenceStartDateAndTime(getMockRequest({ permission }))
147
170
  expect(ageConcessionHelper).toHaveBeenCalledWith(permission)
148
171
  })
149
172
 
@@ -167,7 +190,7 @@ describe('licenceStartTime and licenceToStart values', () => {
167
190
  ({ endHours, licenceToStartResult, licenceStartDate, renewedEndDate, year, month, day }) => {
168
191
  it('licenceStartTime', async () => {
169
192
  const permission = { licenceStartDate, renewedEndDate }
170
- await setLicenceStartDateAndTime(getMockRequest(permission, year, month, day))
193
+ await setLicenceStartDateAndTime(getMockRequest({ permission, year, month, day }))
171
194
  expect(mockTransactionSet).toHaveBeenCalledWith(
172
195
  expect.objectContaining({
173
196
  licenceStartTime: endHours
@@ -177,7 +200,7 @@ describe('licenceStartTime and licenceToStart values', () => {
177
200
 
178
201
  it('licenceToStart', async () => {
179
202
  const permission = { licenceStartDate: licenceStartDate, renewedEndDate: renewedEndDate }
180
- await setLicenceStartDateAndTime(getMockRequest(permission, year, month, day))
203
+ await setLicenceStartDateAndTime(getMockRequest({ permission, year, month, day }))
181
204
  expect(mockTransactionSet).toHaveBeenCalledWith(
182
205
  expect.objectContaining({
183
206
  licenceToStart: licenceToStartResult
@@ -187,38 +210,3 @@ describe('licenceStartTime and licenceToStart values', () => {
187
210
  }
188
211
  )
189
212
  })
190
-
191
- describe('validator', () => {
192
- const getMockOptions = renewedEndDate => ({
193
- context: {
194
- app: {
195
- request: {
196
- permission: {
197
- renewedEndDate
198
- }
199
- }
200
- }
201
- }
202
- })
203
-
204
- const validator = pageRoute.mock.calls[0][2]
205
- beforeEach(jest.clearAllMocks)
206
-
207
- it('validation fails', () => {
208
- return expect(() =>
209
- validator(
210
- { 'licence-start-date-year': 1990, 'licence-start-date-month': 11, 'licence-start-date-day': 11 },
211
- getMockOptions('1990-10-10')
212
- )
213
- ).toThrow()
214
- })
215
-
216
- it('validation succeeds', () => {
217
- return expect(
218
- validator(
219
- { 'licence-start-date-year': 1990, 'licence-start-date-month': 2, 'licence-start-date-day': 1 },
220
- getMockOptions('1990-02-01')
221
- )
222
- ).toBeUndefined()
223
- })
224
- })
@@ -6,11 +6,37 @@
6
6
 
7
7
  {%
8
8
  set errorMap = {
9
- 'licence-start-date': {
10
- 'date.format': { ref: '#licence-start-date-day', text: mssgs.renewal_start_date_error_format },
11
- 'date.max': { ref: '#licence-start-date-day', text: mssgs.renewal_start_date_error_max_1 + data.advancedPurchaseMaxDays + mssgs.renewal_start_date_error_max_2 + data.maxStartDate },
12
- 'date.min': { ref: '#licence-start-date-day', text: mssgs.renewal_start_date_error_min }
13
- }
9
+ 'full-date': {
10
+ 'object.missing': { ref: '#licence-start-date-day', text: mssgs.licence_start_error }
11
+ },
12
+ 'day-and-month': {
13
+ 'object.missing': { ref: '#licence-start-date-day', text: mssgs.licence_start_error_missing_day_and_month }
14
+ },
15
+ 'day-and-year': {
16
+ 'object.missing': { ref: '#licence-start-date-day', text: mssgs.licence_start_error_missing_day_and_year }
17
+ },
18
+ 'month-and-year': {
19
+ 'object.missing': { ref: '#licence-start-date-month', text: mssgs.licence_start_error_missing_month_and_year }
20
+ },
21
+ 'day': {
22
+ 'any.required': { ref: '#licence-start-date-day', text: mssgs.licence_start_error_missing_day }
23
+ },
24
+ 'month': {
25
+ 'any.required': { ref: '#licence-start-date-month', text: mssgs.licence_start_error_missing_month }
26
+ },
27
+ 'year': {
28
+ 'any.required': { ref: '#licence-start-date-year', text: mssgs.licence_start_error_missing_year }
29
+ },
30
+ 'non-numeric': {
31
+ 'number.base': { ref: '#licence-start-date-day', text: mssgs.licence_start_error_non_numeric }
32
+ },
33
+ 'invalid-date': {
34
+ 'any.custom': { ref: '#licence-start-date-day', text: mssgs.licence_start_error_date_real }
35
+ },
36
+ 'date-range': {
37
+ 'date.min': { ref: '#licence-start-date-day', text: mssgs.renewal_start_date_error_min },
38
+ 'date.max': { ref: '#licence-start-date-day', text: data.maxStartDateMessage }
39
+ }
14
40
  }
15
41
  %}
16
42
 
@@ -43,9 +69,9 @@
43
69
  id: "licence-start-date",
44
70
  namePrefix: "licence-start-date",
45
71
  items: dateInputItems,
46
- errorMessage: { text: mssgs.renewal_start_date_error_valid_date } if error,
72
+ errorMessage: { text: errorMap[data.error.errorKey][data.error.errorValue].text } if data.error,
47
73
  hint: {
48
- text: mssgs.renewal_start_date_error_hint_1 + data.minStartDate + mssgs.and + data.maxStartDate
74
+ text: data.renewalHint
49
75
  }
50
76
  }) }}
51
77
  {% endblock %}
@@ -1,33 +1,12 @@
1
1
  import { ADVANCED_PURCHASE_MAX_DAYS, SERVICE_LOCAL_TIME } from '@defra-fish/business-rules-lib'
2
- import { dateFormats } from '../../../constants.js'
3
2
  import { RENEWAL_START_DATE, LICENCE_SUMMARY } from '../../../uri.js'
4
3
  import pageRoute from '../../../routes/page-route.js'
5
- import Joi from 'joi'
6
- import JoiDate from '@hapi/joi-date'
7
4
  import moment from 'moment-timezone'
8
5
  import { displayExpiryDate, cacheDateFormat } from '../../../processors/date-and-time-display.js'
9
6
  import { addLanguageCodeToUri } from '../../../processors/uri-helper.js'
10
7
  import { licenceToStart } from '../../licence-details/licence-to-start/update-transaction.js'
11
8
  import { ageConcessionHelper } from '../../../processors/concession-helper.js'
12
-
13
- const JoiX = Joi.extend(JoiDate)
14
-
15
- const validator = (payload, options) => {
16
- const { permission } = options.context.app.request
17
- const endDateMoment = moment.utc(permission.renewedEndDate).tz(SERVICE_LOCAL_TIME)
18
- const licenceStartDate = `${payload['licence-start-date-year']}-${payload['licence-start-date-month']}-${payload['licence-start-date-day']}`
19
-
20
- return Joi.assert(
21
- { 'licence-start-date': licenceStartDate },
22
- Joi.object({
23
- 'licence-start-date': JoiX.date()
24
- .format(dateFormats)
25
- .min(endDateMoment.clone().startOf('day'))
26
- .max(endDateMoment.clone().add(ADVANCED_PURCHASE_MAX_DAYS, 'days'))
27
- .required()
28
- }).options({ abortEarly: false, allowUnknown: true })
29
- )
30
- }
9
+ import { renewalStartDateValidator } from '../../../schema/validators/validators.js'
31
10
 
32
11
  const setLicenceStartDateAndTime = async request => {
33
12
  const permission = await request.cache().helpers.transaction.getCurrentPermission()
@@ -64,20 +43,39 @@ const setLicenceStartDateAndTime = async request => {
64
43
 
65
44
  const getData = async request => {
66
45
  const permission = await request.cache().helpers.transaction.getCurrentPermission()
46
+ const page = await request.cache().helpers.page.getCurrentPermission(RENEWAL_START_DATE.page)
47
+ const mssgs = request.i18n.getCatalog()
67
48
 
68
49
  const expiryTimeString = displayExpiryDate(request, permission)
69
50
  const endDateMoment = moment.utc(permission.renewedEndDate, null, request.locale).tz(SERVICE_LOCAL_TIME)
51
+ const minStartDate = endDateMoment.format('DD MM YYYY')
52
+ const maxStartDate = endDateMoment.clone().add(ADVANCED_PURCHASE_MAX_DAYS, 'days').format('DD MM YYYY')
70
53
 
71
- return {
54
+ const pageData = {
72
55
  expiryTimeString,
73
56
  hasExpired: permission.renewedHasExpired,
74
- minStartDate: endDateMoment.format('DD MM YYYY'),
75
- maxStartDate: endDateMoment.clone().add(ADVANCED_PURCHASE_MAX_DAYS, 'days').format('DD MM YYYY'),
76
- advancedPurchaseMaxDays: ADVANCED_PURCHASE_MAX_DAYS
57
+ advancedPurchaseMaxDays: ADVANCED_PURCHASE_MAX_DAYS,
58
+ maxStartDateMessage:
59
+ mssgs.renewal_start_date_error_max_1 + ADVANCED_PURCHASE_MAX_DAYS + mssgs.renewal_start_date_error_max_2 + maxStartDate,
60
+ renewalHint: mssgs.renewal_start_date_error_hint + minStartDate + mssgs.and + maxStartDate
61
+ }
62
+
63
+ if (page?.error) {
64
+ const [errorKey] = Object.keys(page.error)
65
+ const errorValue = page.error[errorKey]
66
+ pageData.error = { errorKey, errorValue }
77
67
  }
68
+
69
+ return pageData
78
70
  }
79
71
 
80
- const route = pageRoute(RENEWAL_START_DATE.page, RENEWAL_START_DATE.uri, validator, request => setLicenceStartDateAndTime(request), getData)
72
+ const route = pageRoute(
73
+ RENEWAL_START_DATE.page,
74
+ RENEWAL_START_DATE.uri,
75
+ renewalStartDateValidator,
76
+ request => setLicenceStartDateAndTime(request),
77
+ getData
78
+ )
81
79
  route.find(r => r.method === 'POST').options.ext = {
82
80
  onPostAuth: {
83
81
  method: async (request, reply) => {
@@ -1,5 +1,5 @@
1
1
  import Joi from 'joi'
2
- import { dateOfBirthValidator, startDateValidator, getDateErrorFlags } from '../validators.js'
2
+ import { dateOfBirthValidator, startDateValidator, getDateErrorFlags, renewalStartDateValidator } from '../validators.js'
3
3
  import moment from 'moment-timezone'
4
4
  const dateSchema = require('../../date.schema.js')
5
5
 
@@ -206,3 +206,87 @@ describe('getErrorFlags', () => {
206
206
  expect(result).toEqual(expect.objectContaining(expected))
207
207
  })
208
208
  })
209
+
210
+ describe('renewalStartDateValidator', () => {
211
+ beforeEach(jest.clearAllMocks)
212
+
213
+ const getSamplePayload = ({ day = '', month = '', year = '' } = {}) => ({
214
+ 'licence-start-date-day': day,
215
+ 'licence-start-date-month': month,
216
+ 'licence-start-date-year': year
217
+ })
218
+ const renewedEndDate = moment()
219
+ const options = {
220
+ context: {
221
+ app: {
222
+ request: {
223
+ permission: {
224
+ renewedEndDate: renewedEndDate.toISOString()
225
+ }
226
+ }
227
+ }
228
+ }
229
+ }
230
+ it('throws an error for a licence starting before today', () => {
231
+ const renewedDate = moment().subtract(1, 'day')
232
+ const samplePayload = getSamplePayload({
233
+ day: renewedDate.format('DD'),
234
+ month: renewedDate.format('MM'),
235
+ year: renewedDate.format('YYYY')
236
+ })
237
+ expect(() => renewalStartDateValidator(samplePayload, options)).toThrow()
238
+ })
239
+
240
+ it('throws an error for a licence starting more than 30 days hence', () => {
241
+ const renewedDate = moment().add(31, 'days')
242
+ const samplePayload = getSamplePayload({
243
+ day: renewedDate.format('DD'),
244
+ month: renewedDate.format('MM'),
245
+ year: renewedDate.format('YYYY')
246
+ })
247
+ expect(() => renewalStartDateValidator(samplePayload, options)).toThrow()
248
+ })
249
+
250
+ it('validates for a date within the next 30 days', () => {
251
+ const renewedDate = moment().add(4, 'days')
252
+ const samplePayload = getSamplePayload({
253
+ day: renewedDate.format('DD'),
254
+ month: renewedDate.format('MM'),
255
+ year: renewedDate.format('YYYY')
256
+ })
257
+ expect(() => renewalStartDateValidator(samplePayload, options)).not.toThrow()
258
+ })
259
+
260
+ it.each([
261
+ ['01', '03', '1994'],
262
+ ['10', '12', '2004']
263
+ ])('passes start date day (%s), month (%s) and year (%s) to dateSchemaInput', (day, month, year) => {
264
+ setupMocks()
265
+ renewalStartDateValidator(getSamplePayload({ day, month, year }), options)
266
+ expect(dateSchema.dateSchemaInput).toHaveBeenCalledWith(day, month, year)
267
+ tearDownMocks()
268
+ })
269
+
270
+ it('passes dateSchemaInput output and dateSchema to Joi.assert', () => {
271
+ setupMocks()
272
+ const dsi = Symbol('dsi')
273
+ dateSchema.dateSchemaInput.mockReturnValueOnce(dsi)
274
+ renewalStartDateValidator(getSamplePayload(), options)
275
+ expect(Joi.assert).toHaveBeenCalledWith(dsi, dateSchema.dateSchema)
276
+ tearDownMocks()
277
+ })
278
+
279
+ it('passes validation if licence is set to start after payment', () => {
280
+ const samplePayload = getSamplePayload({
281
+ day: moment().format('DD'),
282
+ month: moment().format('MM'),
283
+ year: moment().format('YYYY')
284
+ })
285
+ expect(() => renewalStartDateValidator(samplePayload, options)).not.toThrow()
286
+ })
287
+
288
+ it('throws an error if licence-to-start is set to an invalid value', () => {
289
+ const samplePayload = { 'licence-to-start': '12th-of-never' }
290
+ expect(() => renewalStartDateValidator(samplePayload, options)).toThrow()
291
+ })
292
+ })
@@ -43,6 +43,19 @@ export const startDateValidator = payload => {
43
43
  }
44
44
  }
45
45
 
46
+ export const renewalStartDateValidator = (payload, options) => {
47
+ const { permission } = options.context.app.request
48
+ const endDateMoment = moment.utc(permission.renewedEndDate).tz(SERVICE_LOCAL_TIME)
49
+ const day = payload['licence-start-date-day']
50
+ const month = payload['licence-start-date-month']
51
+ const year = payload['licence-start-date-year']
52
+
53
+ const minDate = endDateMoment.clone().startOf('day').toDate()
54
+ const maxDate = endDateMoment.clone().add(ADVANCED_PURCHASE_MAX_DAYS, 'days').toDate()
55
+
56
+ validateDate(day, month, year, minDate, maxDate)
57
+ }
58
+
46
59
  export const getDateErrorFlags = error => {
47
60
  const errorFlags = { isDayError: false, isMonthError: false, isYearError: false }
48
61
  const commonErrors = ['full-date', 'invalid-date', 'date-range', 'non-numeric']
package/src/uri.js CHANGED
@@ -86,3 +86,4 @@ export const GET_PRICING_LENGTHS = { uri: '/buy/get-pricing/lengths' }
86
86
 
87
87
  export const FRESHWATER_FISING_RULES = { uri: 'https://www.gov.uk/freshwater-rod-fishing-rules' }
88
88
  export const LOCAL_BYELAWS = { uri: 'https://www.gov.uk/government/collections/local-fishing-byelaws' }
89
+ export const CATCH_RETURN = { uri: 'https://www.gov.uk/catch-return' }