@defra-fish/gafl-webapp-service 1.59.0-rc.0 → 1.59.0-rc.2

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.0",
3
+ "version": "1.59.0-rc.2",
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.0",
40
- "@defra-fish/connectors-lib": "1.59.0-rc.0",
39
+ "@defra-fish/business-rules-lib": "1.59.0-rc.2",
40
+ "@defra-fish/connectors-lib": "1.59.0-rc.2",
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": "01bc1d91c4f25234b008dafe06b0525760f9c752"
83
+ "gitHead": "79ed1c32b80408a0c2b99b39dee1833684f38778"
84
84
  }
@@ -743,7 +743,7 @@
743
743
  "renewal_inactive_title_4": "You can ",
744
744
  "renewal_inactive_title_link": "buy a new licence.",
745
745
  "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 ",
746
+ "renewal_start_date_error_hint": "Rhowch ddyddiad rhwng ",
747
747
  "renewal_start_date_error_max_1": "Mae’n rhaid i’r trwydded newydd ddechrau o fewn ",
748
748
  "renewal_start_date_error_max_2": " diwrnod i ddyddiad terfyn eich trwydded bresennol. Rhowch ddyddiad hyd at a gan gynnwys ",
749
749
  "renewal_start_date_error_min": "Ni all y drwydded ddechrau cyn i’ch trwydded bresennol ddod i ben",
@@ -743,7 +743,7 @@
743
743
  "renewal_inactive_title_4": "You can ",
744
744
  "renewal_inactive_title_link": "buy a new licence.",
745
745
  "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 ",
746
+ "renewal_start_date_error_hint": "Enter a date between ",
747
747
  "renewal_start_date_error_max_1": "Your new licence must start within ",
748
748
  "renewal_start_date_error_max_2": " days of your current licence expiring. Enter a date up to and including ",
749
749
  "renewal_start_date_error_min": "The licence must not start before your current licence has expired",
@@ -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']