@defra-fish/business-rules-lib 1.49.0-rc.3 → 1.49.0-rc.4
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/business-rules-lib",
|
|
3
|
-
"version": "1.49.0-rc.
|
|
3
|
+
"version": "1.49.0-rc.4",
|
|
4
4
|
"description": "Shared business rules for the rod licensing digital services",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"moment": "^2.29.1",
|
|
38
38
|
"uuid": "^8.3.2"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "5c9d0205887751b34c54c9e28d86c09ae16183ca"
|
|
41
41
|
}
|
|
@@ -5,6 +5,9 @@ import moment from 'moment'
|
|
|
5
5
|
const INVALID_DATE_ERROR_MESSAGE = '"value" must be in [YYYY-MM-DD] format'
|
|
6
6
|
|
|
7
7
|
describe('contact validators', () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
jest.resetAllMocks()
|
|
10
|
+
})
|
|
8
11
|
describe('birthDateValidator', () => {
|
|
9
12
|
const validDate = moment().subtract(1, 'day')
|
|
10
13
|
|
|
@@ -128,6 +131,24 @@ describe('contact validators', () => {
|
|
|
128
131
|
'"value" must contain at least 3 alpha characters'
|
|
129
132
|
)
|
|
130
133
|
})
|
|
134
|
+
|
|
135
|
+
it.each([
|
|
136
|
+
'M̵i̵c̵h̵a̵e̵l̵',
|
|
137
|
+
'M̷i̷c̷h̷a̷e̷l̷',
|
|
138
|
+
'M͟i͟c͟h͟a͟e͟l͟',
|
|
139
|
+
'𝔐𝔦𝔠𝔥𝔞𝔢𝔩',
|
|
140
|
+
'𝕄𝕚𝕔𝕙𝕒𝕖𝕝',
|
|
141
|
+
'ןǝɐɥɔıW',
|
|
142
|
+
'Ⓜⓘⓒⓗⓐⓔⓛ',
|
|
143
|
+
'🄼🄸🄲🄷🄰🄴🄻',
|
|
144
|
+
'Mɪᴄʜᴀᴇʟ',
|
|
145
|
+
'ᴹᶦᶜʰᵃᵉˡ',
|
|
146
|
+
'𖢑𖥣𖥐𖦙𖧥𖠢ꛚ',
|
|
147
|
+
'ℳ𝒾𝒸𝒽𝒶ℯ𝓁',
|
|
148
|
+
'𝙼𝚒𝚌𝚑𝚊𝚎𝚕'
|
|
149
|
+
])('prohibits a string with non-standard characters: %s', async c => {
|
|
150
|
+
await expect(contactValidation.createFirstNameValidator(Joi).validateAsync(c)).rejects.toThrow()
|
|
151
|
+
})
|
|
131
152
|
})
|
|
132
153
|
|
|
133
154
|
describe('lastNameValidator', () => {
|
|
@@ -229,6 +250,24 @@ describe('contact validators', () => {
|
|
|
229
250
|
'"value" must contain at least 3 alpha characters'
|
|
230
251
|
)
|
|
231
252
|
})
|
|
253
|
+
|
|
254
|
+
it.each([
|
|
255
|
+
'M̵i̵c̵h̵a̵e̵l̵',
|
|
256
|
+
'M̷i̷c̷h̷a̷e̷l̷',
|
|
257
|
+
'M͟i͟c͟h͟a͟e͟l͟',
|
|
258
|
+
'𝔐𝔦𝔠𝔥𝔞𝔢𝔩',
|
|
259
|
+
'𝕄𝕚𝕔𝕙𝕒𝕖𝕝',
|
|
260
|
+
'ןǝɐɥɔıW',
|
|
261
|
+
'Ⓜⓘⓒⓗⓐⓔⓛ',
|
|
262
|
+
'🄼🄸🄲🄷🄰🄴🄻',
|
|
263
|
+
'Mɪᴄʜᴀᴇʟ',
|
|
264
|
+
'ᴹᶦᶜʰᵃᵉˡ',
|
|
265
|
+
'𖢑𖥣𖥐𖦙𖧥𖠢ꛚ',
|
|
266
|
+
'ℳ𝒾𝒸𝒽𝒶ℯ𝓁',
|
|
267
|
+
'𝙼𝚒𝚌𝚑𝚊𝚎𝚕'
|
|
268
|
+
])('prohibits a string with non-standard characters: %s', async c => {
|
|
269
|
+
await expect(contactValidation.createLastNameValidator(Joi).validateAsync(c)).rejects.toThrow()
|
|
270
|
+
})
|
|
232
271
|
})
|
|
233
272
|
|
|
234
273
|
describe('emailValidator', () => {
|
|
@@ -241,6 +280,28 @@ describe('contact validators', () => {
|
|
|
241
280
|
'"value" must be a valid email'
|
|
242
281
|
)
|
|
243
282
|
})
|
|
283
|
+
|
|
284
|
+
it('allows a range of unicode characters from plane 1', async () => {
|
|
285
|
+
const internationStr = 'æçéñøķť@email.com'
|
|
286
|
+
await expect(contactValidation.createEmailValidator(Joi).validateAsync(internationStr)).resolves.toEqual('æçéñøķť@email.com')
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
it.each([
|
|
290
|
+
'ᵐᵢᶜₕᵃₑˡ@ᵉₘᵃᵢˡ.ᶜₒᵐ',
|
|
291
|
+
'𝓂𝒾𝒸𝒽𝒶ℯ𝓁@ℯ𝓂𝒶𝒾𝓁.𝒸ℴ𝓂',
|
|
292
|
+
'm̶i̶c̶h̶a̶e̶l̶@̶e̶m̶a̶i̶l̶.̶c̶o̶m̶',
|
|
293
|
+
'm̷i̷c̷h̷a̷e̷l̷@̷e̷m̷a̷i̷l̷.̷c̷o̷m̷',
|
|
294
|
+
'𝖒𝖎𝖈𝖍𝖆𝖊𝖑@𝖊𝖒𝖆𝖎𝖑.𝖈𝖔𝖒',
|
|
295
|
+
'm̲i̲c̲h̲a̲e̲l̲@̲e̲m̲a̲i̲l̲.̲c̲o̲m̲',
|
|
296
|
+
'ꕮꕯꖀꖾꗇꗍꝆ@ꗍꕮꗇꕯꝆ.ꖀꗞꕮ',
|
|
297
|
+
'🅼🅘🅲🅗🅰🅔🅻@🅴🅜🅰🅘🅻.🅲🅞🅼',
|
|
298
|
+
'ɯoɔ˙ןıɐɯǝ@ןǝɐɥɔıɯ',
|
|
299
|
+
'ꮇꮖꮯꮋꭺꭼꮮ@ꭼꮇꭺꮖꮮ.ꮯꮎꮇ',
|
|
300
|
+
'michael@email.com',
|
|
301
|
+
'ₘᵢcₕaₑₗ@ₑₘaᵢₗ.cₒₘ'
|
|
302
|
+
])('prohibits a string with non-standard characters: %s', async c => {
|
|
303
|
+
await expect(contactValidation.createEmailValidator(Joi).validateAsync(c)).rejects.toThrow()
|
|
304
|
+
})
|
|
244
305
|
})
|
|
245
306
|
|
|
246
307
|
describe('mobilePhoneValidator', () => {
|
|
@@ -251,6 +312,24 @@ describe('contact validators', () => {
|
|
|
251
312
|
it.each(['test', '07700 test'])('rejects the invalid number %s', async number => {
|
|
252
313
|
await expect(contactValidation.createMobilePhoneValidator(Joi).validateAsync(number)).rejects.toThrow()
|
|
253
314
|
})
|
|
315
|
+
|
|
316
|
+
it.each([
|
|
317
|
+
'𝟘𝟟𝟟𝟘𝟘 𝟡𝟘𝟘𝟘𝟠𝟠',
|
|
318
|
+
'0𝟟7𝟘0 9𝟘0𝟘8𝟠',
|
|
319
|
+
'0𝟽𝟽00 𝟿000𝟾𝟾',
|
|
320
|
+
'0̵7̵7̵0̵0̵ ̵9̵0̵0̵0̵8̵8̵',
|
|
321
|
+
'0͟7͟7͟0͟0͟ ͟9͟0͟0͟0͟8͟8͟',
|
|
322
|
+
'0̸7̸7̸0̸0̸ ̸9̸0̸0̸0̸8̸8̸',
|
|
323
|
+
'07700 900088',
|
|
324
|
+
'⁰⁷⁷⁰⁰ ⁹⁰⁰⁰⁸⁸',
|
|
325
|
+
'⓿➐➐⓿⓿ ➒⓿⓿⓿➑➑',
|
|
326
|
+
'+ㄐㄐワワㄖㄖ ㄢㄖㄖㄖ曰曰',
|
|
327
|
+
'07700👏 900088',
|
|
328
|
+
'0̐̈7̐̈7̐̈0̐̈0̐̈ ̐̈9̐̈0̐̈0̐̈0̐̈8̐̈8̐̈',
|
|
329
|
+
'+4④7⑦0⓪ ⑨0⓪0⑧8'
|
|
330
|
+
])('prohibits a string with non-standard characters: %s', async c => {
|
|
331
|
+
await expect(contactValidation.createMobilePhoneValidator(Joi).validateAsync(c)).rejects.toThrow()
|
|
332
|
+
})
|
|
254
333
|
})
|
|
255
334
|
|
|
256
335
|
describe('ukPostcodeValidator', () => {
|
|
@@ -265,33 +344,74 @@ describe('contact validators', () => {
|
|
|
265
344
|
it('expects a minimum of 1 character', async () => {
|
|
266
345
|
await expect(contactValidation.createUKPostcodeValidator(Joi).validateAsync('')).rejects.toThrow('"value" is not allowed to be empty')
|
|
267
346
|
})
|
|
347
|
+
|
|
268
348
|
it('expects a maximum of 12 characters', async () => {
|
|
269
349
|
await expect(contactValidation.createUKPostcodeValidator(Joi).validateAsync('0123456789ABC')).rejects.toThrow(
|
|
270
350
|
'"value" length must be less than or equal to 12 characters long'
|
|
271
351
|
)
|
|
272
352
|
})
|
|
353
|
+
|
|
273
354
|
it('expects postcodes to conform to the pattern used in the UK', async () => {
|
|
274
355
|
await expect(contactValidation.createUKPostcodeValidator(Joi).validateAsync('0123456789')).rejects.toThrow(
|
|
275
356
|
/fails to match the required pattern/
|
|
276
357
|
)
|
|
277
358
|
})
|
|
359
|
+
|
|
360
|
+
it.each([
|
|
361
|
+
'A⃣B⃣1⃣2⃣ 1⃣A⃣B⃣',
|
|
362
|
+
'🄐🄑⑴⑵ ⑴🄐🄑',
|
|
363
|
+
'丹乃丨己 丨丹乃',
|
|
364
|
+
'A͢B͢1͢2͢ ͢1͢A͢B͢',
|
|
365
|
+
'A⃟B⃟1⃟2⃟ 1⃟A⃟B⃟',
|
|
366
|
+
'AB12👏 1AB',
|
|
367
|
+
'🅐Ⓑ➊② ①🅐Ⓑ',
|
|
368
|
+
'𝘼𝐵𝟭𝟮 1𝘼𝘽',
|
|
369
|
+
'🅰𝙱12 1𝕬𝓑',
|
|
370
|
+
'1ᴬAᴮB¹²',
|
|
371
|
+
'ᴬᴮ¹² ¹ᴬᴮ',
|
|
372
|
+
'q∀1 21q∀',
|
|
373
|
+
'A̶B̶1̶2̶ ̶1̶A̶B̶'
|
|
374
|
+
])('prohibits a string with non-standard characters: %s', async c => {
|
|
375
|
+
await expect(contactValidation.createUKPostcodeValidator(Joi).validateAsync(c)).rejects.toThrow()
|
|
376
|
+
})
|
|
278
377
|
})
|
|
279
378
|
|
|
280
379
|
describe('overseasPostcodeValidator', () => {
|
|
281
380
|
it('converts to uppercase and trims', async () => {
|
|
282
381
|
await expect(contactValidation.createOverseasPostcodeValidator(Joi).validateAsync('a ')).resolves.toEqual('A')
|
|
283
382
|
})
|
|
383
|
+
|
|
284
384
|
it('expects a minimum of 1 character', async () => {
|
|
285
385
|
await expect(contactValidation.createOverseasPostcodeValidator(Joi).validateAsync('')).rejects.toThrow(
|
|
286
386
|
'"value" is not allowed to be empty'
|
|
287
387
|
)
|
|
288
388
|
})
|
|
389
|
+
|
|
289
390
|
it('expects a maximum of 12 characters', async () => {
|
|
290
391
|
await expect(contactValidation.createOverseasPostcodeValidator(Joi).validateAsync('123456789AAAA')).rejects.toThrow()
|
|
291
392
|
})
|
|
393
|
+
|
|
292
394
|
it('will not accept special characters', async () => {
|
|
293
395
|
await expect(contactValidation.createOverseasPostcodeValidator(Joi).validateAsync('12£4')).rejects.toThrow()
|
|
294
396
|
})
|
|
397
|
+
|
|
398
|
+
it.each([
|
|
399
|
+
'A⃣B⃣1⃣2⃣ 1⃣A⃣B⃣',
|
|
400
|
+
'🄐🄑⑴⑵ ⑴🄐🄑',
|
|
401
|
+
'丹乃丨己 丨丹乃',
|
|
402
|
+
'A͢B͢1͢2͢ ͢1͢A͢B͢',
|
|
403
|
+
'A⃟B⃟1⃟2⃟ 1⃟A⃟B⃟',
|
|
404
|
+
'AB12👏 1AB',
|
|
405
|
+
'🅐Ⓑ➊② ①🅐Ⓑ',
|
|
406
|
+
'𝘼𝐵𝟭𝟮 1𝘼𝘽',
|
|
407
|
+
'🅰𝙱12 1𝕬𝓑',
|
|
408
|
+
'1ᴬAᴮB¹²',
|
|
409
|
+
'ᴬᴮ¹² ¹ᴬᴮ',
|
|
410
|
+
'q∀1 21q∀',
|
|
411
|
+
'A̶B̶1̶2̶ ̶1̶A̶B̶'
|
|
412
|
+
])('prohibits a string with non-standard characters: %s', async c => {
|
|
413
|
+
await expect(contactValidation.createOverseasPostcodeValidator(Joi).validateAsync(c)).rejects.toThrow()
|
|
414
|
+
})
|
|
295
415
|
})
|
|
296
416
|
|
|
297
417
|
describe('premisesValidator', () => {
|
|
@@ -308,6 +428,23 @@ describe('contact validators', () => {
|
|
|
308
428
|
'"value" length must be less than or equal to 50 characters long'
|
|
309
429
|
)
|
|
310
430
|
})
|
|
431
|
+
|
|
432
|
+
it.each([
|
|
433
|
+
'15 𐝥ꗞꕷꗍ ꖀꗞꖡꖡꗇꗱꗍ',
|
|
434
|
+
'15 Rose Cottage',
|
|
435
|
+
'¹⁵ ᴿᵒˢᵉ ᶜᵒᵗᵗᵃᵍᵉ',
|
|
436
|
+
'15 ᖇᐤᔆᕪ ᐸᐤᐩᐩᐞᕐᕪ',
|
|
437
|
+
'15👏 Rose👏 Cottage',
|
|
438
|
+
'1̶5̶ ̶R̶o̶s̶e̶ ̶C̶o̶t̶t̶a̶g̶e̶',
|
|
439
|
+
'1̲5̲ ̲R̲o̲s̲e̲ ̲C̲o̲t̲t̲a̲g̲e̲',
|
|
440
|
+
'1̸5̸ ̸R̸o̸s̸e̸ ̸C̸o̸t̸t̸a̸g̸e̸',
|
|
441
|
+
'➊➎ 🅡🅞🅢🅔 🅒🅞🅣🅣🅐🅖🅔',
|
|
442
|
+
'①➎ 🅡ⓞ🅢ⓔ Ⓒ🅞ⓣ🅣ⓐ🅖ⓔ',
|
|
443
|
+
'1⑤ 𝑅𝐨𝑠ⓔ 𝒞𝓸𝘁𝕥𝒶ℊ🄴',
|
|
444
|
+
'𝟏𝟓 𝐑𝐨𝐬𝐞 𝐂𝐨𝐭𝐭𝐚𝐠𝐞'
|
|
445
|
+
])('prohibits a string with non-standard characters: %s', async c => {
|
|
446
|
+
await expect(contactValidation.createPremisesValidator(Joi).validateAsync(c)).rejects.toThrow()
|
|
447
|
+
})
|
|
311
448
|
})
|
|
312
449
|
|
|
313
450
|
describe('streetValidator', () => {
|
|
@@ -324,6 +461,22 @@ describe('contact validators', () => {
|
|
|
324
461
|
'"value" length must be less than or equal to 100 characters long'
|
|
325
462
|
)
|
|
326
463
|
})
|
|
464
|
+
|
|
465
|
+
it.each([
|
|
466
|
+
'Bond👏 Street',
|
|
467
|
+
'🅑ⓞ🅝ⓓ ⓢⓣⓡⓔⓔⓣ',
|
|
468
|
+
'Bond Street',
|
|
469
|
+
'ᴮᵒⁿᵈ ˢᵗʳᵉᵉᵗ',
|
|
470
|
+
'B̲o̲n̲d̲ ̲S̲t̲r̲e̲e̲t̲',
|
|
471
|
+
'B̸o̸n̸d̸ ̸S̸t̸r̸e̸e̸t̸',
|
|
472
|
+
'🅑🅞🅝🅓 🅢🅣🅡🅔🅔🅣',
|
|
473
|
+
'B𝑜𝓷d S𝓉𝓇𝑒𝑒𝓉',
|
|
474
|
+
'もB囗o几n问d 丂S匕t尺r乇eモe匕t',
|
|
475
|
+
'B⃠o⃠n⃠d⃠ S⃠t⃠r⃠e⃠e⃠t⃠',
|
|
476
|
+
'𝐁𝐨𝐧𝐝 𝐒𝐭𝐫𝐞𝐞𝐭'
|
|
477
|
+
])('prohibits a string with non-standard characters: %s', async c => {
|
|
478
|
+
await expect(contactValidation.createStreetValidator(Joi).validateAsync(c)).rejects.toThrow()
|
|
479
|
+
})
|
|
327
480
|
})
|
|
328
481
|
|
|
329
482
|
describe('localityValidator', () => {
|
|
@@ -340,6 +493,20 @@ describe('contact validators', () => {
|
|
|
340
493
|
'"value" length must be less than or equal to 100 characters long'
|
|
341
494
|
)
|
|
342
495
|
})
|
|
496
|
+
|
|
497
|
+
it.each([
|
|
498
|
+
'M̲a̲y̲f̲a̲i̲r̲',
|
|
499
|
+
'M̸a̸y̸f̸a̸i̸r̸',
|
|
500
|
+
'Mayfair',
|
|
501
|
+
'ᴹᵃʸᶠᵃⁱʳ',
|
|
502
|
+
'🅜🅐🅨🅕🅐🅘🅡',
|
|
503
|
+
'🅜ⓐ🅨ⓕⓐⓘⓡ',
|
|
504
|
+
'爪M丹aリy乍f丹a工i尺r',
|
|
505
|
+
'M⃠a⃠y⃠f⃠a⃠i⃠r⃠',
|
|
506
|
+
'𝐌𝐚𝐲𝐟𝐚𝐢𝐫'
|
|
507
|
+
])('prohibits a string with non-standard characters: %s', async c => {
|
|
508
|
+
await expect(contactValidation.createLocalityValidator(Joi).validateAsync(c)).rejects.toThrow()
|
|
509
|
+
})
|
|
343
510
|
})
|
|
344
511
|
|
|
345
512
|
describe('townValidator', () => {
|
|
@@ -373,6 +540,13 @@ describe('contact validators', () => {
|
|
|
373
540
|
'"value" length must be less than or equal to 100 characters long'
|
|
374
541
|
)
|
|
375
542
|
})
|
|
543
|
+
|
|
544
|
+
it.each(['London', 'ᴸᵒⁿᵈᵒⁿ', '𝐋𝐨𝐧𝐝𝐨𝐧', 'ㄥL口o几n冂d口o几n', 'L⃠o⃠n⃠d⃠o⃠n⃠', '🅛🅞🅝🅓🅞🅝', 'L̸o̸n̸d̸o̸n̸', 'L̲o̲n̲d̲o̲n̲'])(
|
|
545
|
+
'prohibits a string with non-standard characters: %s',
|
|
546
|
+
async c => {
|
|
547
|
+
await expect(contactValidation.createTownValidator(Joi).validateAsync(c)).rejects.toThrow()
|
|
548
|
+
}
|
|
549
|
+
)
|
|
376
550
|
})
|
|
377
551
|
|
|
378
552
|
describe('nationalInsuranceNumberValidator', () => {
|
|
@@ -381,11 +555,28 @@ describe('contact validators', () => {
|
|
|
381
555
|
'AB 12 34 56 A'
|
|
382
556
|
)
|
|
383
557
|
})
|
|
558
|
+
|
|
384
559
|
it('Disallows invalid NI number QQ123456A', async () => {
|
|
385
560
|
await expect(contactValidation.createNationalInsuranceNumberValidator(Joi).validateAsync('QQ123456A')).rejects.toThrow()
|
|
386
561
|
})
|
|
562
|
+
|
|
387
563
|
it('Disallows invalid NI number BG123456A', async () => {
|
|
388
564
|
await expect(contactValidation.createNationalInsuranceNumberValidator(Joi).validateAsync('QQ123456A')).rejects.toThrow()
|
|
389
565
|
})
|
|
566
|
+
|
|
567
|
+
it.each([
|
|
568
|
+
'A̲B̲1̲2̲3̲4̲5̲6̲A̲',
|
|
569
|
+
'A̸B̸1̸2̸3̸4̸5̸6̸A̸',
|
|
570
|
+
'AB123456A',
|
|
571
|
+
'ᴬᴮ¹²³⁴⁵⁶ᴬ',
|
|
572
|
+
'🅐🅑①②③④⑤⑥🅐',
|
|
573
|
+
'🅐ⓑ①②③④⑤⑥ⓐ',
|
|
574
|
+
'A⃠B⃠1⃠2⃠3⃠4⃠5⃠6⃠A⃠',
|
|
575
|
+
'升A马B丨1己2ヨ3ㄐ4丂5石6刄A',
|
|
576
|
+
'✌️AB123456A✌️',
|
|
577
|
+
'𝐀𝐁𝟏𝟐𝟑𝟒𝟓𝟔𝐀'
|
|
578
|
+
])('prohibits a string with non-standard characters: %s', async c => {
|
|
579
|
+
await expect(contactValidation.createNationalInsuranceNumberValidator(Joi).validateAsync(c)).rejects.toThrow()
|
|
580
|
+
})
|
|
390
581
|
})
|
|
391
582
|
})
|
|
@@ -78,6 +78,12 @@ const createDateStringValidator = joi =>
|
|
|
78
78
|
}
|
|
79
79
|
})
|
|
80
80
|
|
|
81
|
+
const allowedUnicodeBlocks = '\\u0000-\\u024F'
|
|
82
|
+
const forbiddenCharsRegex = new RegExp(`[^${allowedUnicodeBlocks}\\s'’()-]`, 'gu')
|
|
83
|
+
const forbiddenEmailRegex = new RegExp(`[^A-Za-z0-9\\s'’@._${allowedUnicodeBlocks}]`, 'gu')
|
|
84
|
+
const forbiddenCharsNumbersRegex = new RegExp(`[^A-Za-z0-9\\s${allowedUnicodeBlocks}]`, 'gu')
|
|
85
|
+
const forbiddenMobileRegex = /[^+()0-9\-.\s]+/g
|
|
86
|
+
|
|
81
87
|
/**
|
|
82
88
|
* Create a validator to check a contact's birth date
|
|
83
89
|
*
|
|
@@ -92,7 +98,8 @@ export const createBirthDateValidator = joi => createDateStringValidator(joi).tr
|
|
|
92
98
|
* @param {Joi.Root} joi the joi validator used by the consuming project
|
|
93
99
|
* @returns {Joi.StringSchema}
|
|
94
100
|
*/
|
|
95
|
-
export const createEmailValidator = joi =>
|
|
101
|
+
export const createEmailValidator = joi =>
|
|
102
|
+
checkCopyPasteValidator(joi, forbiddenEmailRegex).string().allowable().trim().email().max(100).lowercase().example('person@example.com')
|
|
96
103
|
|
|
97
104
|
export const mobilePhoneRegex = /^[+]*[(]?[0-9]{1,4}[)]?[-\s./0-9]*$/
|
|
98
105
|
/**
|
|
@@ -101,7 +108,10 @@ export const mobilePhoneRegex = /^[+]*[(]?[0-9]{1,4}[)]?[-\s./0-9]*$/
|
|
|
101
108
|
* @param {Joi.Root} joi the joi validator used by the consuming project
|
|
102
109
|
* @returns {Joi.StringSchema}
|
|
103
110
|
*/
|
|
104
|
-
export const createMobilePhoneValidator = joi =>
|
|
111
|
+
export const createMobilePhoneValidator = joi =>
|
|
112
|
+
checkCopyPasteValidator(joi, forbiddenMobileRegex).string().allowable().trim().pattern(mobilePhoneRegex).example('person@example.com')
|
|
113
|
+
|
|
114
|
+
const maxPremises = 50
|
|
105
115
|
|
|
106
116
|
/**
|
|
107
117
|
* Create a validator to check a contact's address premises
|
|
@@ -109,7 +119,16 @@ export const createMobilePhoneValidator = joi => joi.string().trim().pattern(mob
|
|
|
109
119
|
* @param {Joi.Root} joi the joi validator used by the consuming project
|
|
110
120
|
* @returns {Joi.StringSchema}
|
|
111
121
|
*/
|
|
112
|
-
export const createPremisesValidator = joi =>
|
|
122
|
+
export const createPremisesValidator = joi =>
|
|
123
|
+
checkCopyPasteValidator(joi, forbiddenCharsNumbersRegex)
|
|
124
|
+
.string()
|
|
125
|
+
.allowable()
|
|
126
|
+
.trim()
|
|
127
|
+
.min(1)
|
|
128
|
+
.max(maxPremises)
|
|
129
|
+
.external(toTitleCase())
|
|
130
|
+
.required()
|
|
131
|
+
.example('Example House')
|
|
113
132
|
|
|
114
133
|
/**
|
|
115
134
|
* Create a validator to check a contact's address street
|
|
@@ -117,7 +136,15 @@ export const createPremisesValidator = joi => joi.string().trim().min(1).max(50)
|
|
|
117
136
|
* @param {Joi.Root} joi the joi validator used by the consuming project
|
|
118
137
|
* @returns {Joi.StringSchema}
|
|
119
138
|
*/
|
|
120
|
-
export const createStreetValidator = joi =>
|
|
139
|
+
export const createStreetValidator = joi =>
|
|
140
|
+
checkCopyPasteValidator(joi, forbiddenCharsRegex)
|
|
141
|
+
.string()
|
|
142
|
+
.allowable()
|
|
143
|
+
.trim()
|
|
144
|
+
.max(100)
|
|
145
|
+
.external(toTitleCase())
|
|
146
|
+
.empty('')
|
|
147
|
+
.example('Example Street')
|
|
121
148
|
|
|
122
149
|
/**
|
|
123
150
|
* Create a validator to check a contact's address locality
|
|
@@ -125,7 +152,15 @@ export const createStreetValidator = joi => joi.string().trim().max(100).externa
|
|
|
125
152
|
* @param {Joi.Root} joi the joi validator used by the consuming project
|
|
126
153
|
* @returns {Joi.StringSchema}
|
|
127
154
|
*/
|
|
128
|
-
export const createLocalityValidator = joi =>
|
|
155
|
+
export const createLocalityValidator = joi =>
|
|
156
|
+
checkCopyPasteValidator(joi, forbiddenCharsRegex)
|
|
157
|
+
.string()
|
|
158
|
+
.allowable()
|
|
159
|
+
.trim()
|
|
160
|
+
.max(100)
|
|
161
|
+
.external(toTitleCase())
|
|
162
|
+
.empty('')
|
|
163
|
+
.example('Near Sample')
|
|
129
164
|
|
|
130
165
|
/**
|
|
131
166
|
* Create a validator to check a contact's address town
|
|
@@ -134,8 +169,9 @@ export const createLocalityValidator = joi => joi.string().trim().max(100).exter
|
|
|
134
169
|
* @returns {Joi.StringSchema}
|
|
135
170
|
*/
|
|
136
171
|
export const createTownValidator = joi =>
|
|
137
|
-
joi
|
|
172
|
+
checkCopyPasteValidator(joi, forbiddenCharsRegex)
|
|
138
173
|
.string()
|
|
174
|
+
.allowable()
|
|
139
175
|
.trim()
|
|
140
176
|
.max(100)
|
|
141
177
|
.external(toTitleCase(['under', 'upon', 'in', 'on', 'cum', 'next', 'the', 'en', 'le', 'super']))
|
|
@@ -144,6 +180,7 @@ export const createTownValidator = joi =>
|
|
|
144
180
|
|
|
145
181
|
export const ukPostcodeRegex = /^([A-PR-UWYZ][0-9]{1,2}[A-HJKPSTUW]?|[A-PR-UWYZ][A-HK-Y][0-9]{1,2}[ABEHMNPRVWXY]?)\s{0,6}([0-9][A-Z]{2})$/i
|
|
146
182
|
export const overseasPostcodeRegex = /^([a-zA-Z0-9 ]{1,12})$/i
|
|
183
|
+
const maxPostcode = 12
|
|
147
184
|
|
|
148
185
|
/**
|
|
149
186
|
* Create a validator to check a contact's postcode
|
|
@@ -154,7 +191,17 @@ export const overseasPostcodeRegex = /^([a-zA-Z0-9 ]{1,12})$/i
|
|
|
154
191
|
* @returns {Joi.StringSchema}
|
|
155
192
|
*/
|
|
156
193
|
export const createUKPostcodeValidator = joi =>
|
|
157
|
-
joi
|
|
194
|
+
checkCopyPasteValidator(joi, forbiddenCharsNumbersRegex)
|
|
195
|
+
.string()
|
|
196
|
+
.allowable()
|
|
197
|
+
.trim()
|
|
198
|
+
.min(1)
|
|
199
|
+
.max(maxPostcode)
|
|
200
|
+
.required()
|
|
201
|
+
.pattern(ukPostcodeRegex)
|
|
202
|
+
.replace(ukPostcodeRegex, '$1 $2')
|
|
203
|
+
.uppercase()
|
|
204
|
+
.example('AB12 3CD')
|
|
158
205
|
|
|
159
206
|
/**
|
|
160
207
|
* Create a validator to check/format overseas postcodes
|
|
@@ -162,7 +209,15 @@ export const createUKPostcodeValidator = joi =>
|
|
|
162
209
|
* @returns {Joi.StringSchema}
|
|
163
210
|
*/
|
|
164
211
|
export const createOverseasPostcodeValidator = joi =>
|
|
165
|
-
joi
|
|
212
|
+
checkCopyPasteValidator(joi, forbiddenCharsNumbersRegex)
|
|
213
|
+
.string()
|
|
214
|
+
.allowable()
|
|
215
|
+
.trim()
|
|
216
|
+
.min(1)
|
|
217
|
+
.max(maxPostcode)
|
|
218
|
+
.uppercase()
|
|
219
|
+
.required()
|
|
220
|
+
.pattern(overseasPostcodeRegex)
|
|
166
221
|
|
|
167
222
|
const nameStringSubstitutions = [
|
|
168
223
|
/*
|
|
@@ -251,7 +306,7 @@ const createNameStringValidator = (joi, { minimumLength }) =>
|
|
|
251
306
|
return helpers.error('string.min')
|
|
252
307
|
}
|
|
253
308
|
value = standardiseName(value)
|
|
254
|
-
if (!nameStringRegex.test(value)) {
|
|
309
|
+
if (!nameStringRegex.test(value) || forbiddenCharsRegex.test(value)) {
|
|
255
310
|
return helpers.error('string.forbidden')
|
|
256
311
|
}
|
|
257
312
|
return value
|
|
@@ -302,8 +357,9 @@ const ukNINORegEx =
|
|
|
302
357
|
/^([ABCEGHJ-PRSTW-Z][ABCEGHJ-NPRSTW-Z])(?<!(?:BG|GB|KN|NK|NT|TN|ZZ))\s?([0-9]{2})\s{0,3}([0-9]{2})\s{0,3}([0-9]{2})\s{0,3}([ABCD])$/
|
|
303
358
|
|
|
304
359
|
export const createNationalInsuranceNumberValidator = joi =>
|
|
305
|
-
joi
|
|
360
|
+
checkCopyPasteValidator(joi, forbiddenCharsNumbersRegex)
|
|
306
361
|
.string()
|
|
362
|
+
.allowable()
|
|
307
363
|
.trim()
|
|
308
364
|
.uppercase()
|
|
309
365
|
.pattern(ukNINORegEx)
|
|
@@ -311,3 +367,22 @@ export const createNationalInsuranceNumberValidator = joi =>
|
|
|
311
367
|
.required()
|
|
312
368
|
.description('A UK national insurance number')
|
|
313
369
|
.example('NH 12 34 56 A')
|
|
370
|
+
|
|
371
|
+
const checkCopyPasteValidator = (joi, forbiddenRegex) =>
|
|
372
|
+
joi.extend({
|
|
373
|
+
type: 'string',
|
|
374
|
+
base: joi.string(),
|
|
375
|
+
rules: {
|
|
376
|
+
allowable: {
|
|
377
|
+
validate (value, helpers) {
|
|
378
|
+
if (forbiddenRegex.test(value)) {
|
|
379
|
+
return helpers.error('string.forbidden')
|
|
380
|
+
}
|
|
381
|
+
return value
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
messages: {
|
|
386
|
+
'string.forbidden': '{{#label}} contains forbidden characters'
|
|
387
|
+
}
|
|
388
|
+
})
|