@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 +4 -4
- package/src/locales/cy.json +13 -11
- package/src/locales/en.json +13 -11
- package/src/pages/licence-details/licence-type/licence-type.njk +14 -17
- package/src/pages/licence-details/licence-type/route.js +3 -2
- package/src/pages/renewals/renewal-start-date/__tests__/__snapshots__/route.spec.js.snap +2 -2
- package/src/pages/renewals/renewal-start-date/__tests__/route.spec.js +29 -41
- package/src/pages/renewals/renewal-start-date/renewal-start-date.njk +33 -7
- package/src/pages/renewals/renewal-start-date/route.js +25 -27
- package/src/schema/validators/__tests__/validators.spec.js +85 -1
- package/src/schema/validators/validators.js +13 -0
- package/src/uri.js +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defra-fish/gafl-webapp-service",
|
|
3
|
-
"version": "1.59.0-rc.
|
|
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.
|
|
40
|
-
"@defra-fish/connectors-lib": "1.59.0-rc.
|
|
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": "
|
|
83
|
+
"gitHead": "ba5b2afbe6d3c096d813ce3445c39db2c088523d"
|
|
84
84
|
}
|
package/src/locales/cy.json
CHANGED
|
@@ -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
|
|
482
|
-
"licence_type_byelaws": "is-ddeddfau pysgota
|
|
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": "
|
|
495
|
-
"licence_type_salmon_acr_note_2": "
|
|
496
|
-
"licence_type_salmon_acr_note_3": "
|
|
497
|
-
"
|
|
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
|
|
500
|
-
"licence_type_title_you": "Pa drwydded
|
|
501
|
-
"
|
|
502
|
-
"
|
|
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": "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 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
|
-
"
|
|
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",
|
package/src/locales/en.json
CHANGED
|
@@ -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
|
|
482
|
-
"licence_type_byelaws": "
|
|
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": "
|
|
495
|
-
"licence_type_salmon_acr_note_2": "
|
|
496
|
-
"licence_type_salmon_acr_note_3": "
|
|
497
|
-
"
|
|
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
|
|
500
|
-
"licence_type_title_you": "Which type of licence do you
|
|
501
|
-
"
|
|
502
|
-
"
|
|
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
|
-
"
|
|
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 }}
|
|
40
|
-
|
|
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 }}</
|
|
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
|
-
"
|
|
9
|
-
"
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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:
|
|
72
|
+
errorMessage: { text: errorMap[data.error.errorKey][data.error.errorValue].text } if data.error,
|
|
47
73
|
hint: {
|
|
48
|
-
text:
|
|
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
|
-
|
|
54
|
+
const pageData = {
|
|
72
55
|
expiryTimeString,
|
|
73
56
|
hasExpired: permission.renewedHasExpired,
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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(
|
|
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' }
|