@defra-fish/business-rules-lib
Version:
Shared business rules for the rod licensing digital services
553 lines (488 loc) • 23.7 kB
JavaScript
import Joi from 'joi'
import * as contactValidation from '../contact.validators.js'
import moment from 'moment'
const INVALID_DATE_ERROR_MESSAGE = '"value" must be in [YYYY-MM-DD] format'
describe('contact validators', () => {
beforeEach(() => {
jest.resetAllMocks()
})
describe('birthDateValidator', () => {
const validDate = moment().subtract(1, 'day')
it('allows a date in the past', async () => {
const testValue = validDate.format('YYYY-MM-DD')
await expect(contactValidation.createBirthDateValidator(Joi).validateAsync(testValue)).resolves.toEqual(testValue)
})
it('allows a date in alternative format', async () => {
const testValueIn = validDate.format('YYYY-M-D')
const testValueOut = validDate.format('YYYY-MM-DD')
await expect(contactValidation.createBirthDateValidator(Joi).validateAsync(testValueIn)).resolves.toEqual(testValueOut)
})
it('throws if given an invalid format', async () => {
await expect(contactValidation.createBirthDateValidator(Joi).validateAsync(validDate.format('YYYY-MM-DDThh:mm:ss'))).rejects.toThrow(
INVALID_DATE_ERROR_MESSAGE
)
})
it('throws if given an invalid date', async () => {
await expect(contactValidation.createBirthDateValidator(Joi).validateAsync('1-111-19')).rejects.toThrow(INVALID_DATE_ERROR_MESSAGE)
})
it('throws if the year is specified as 2 digits', async () => {
const testValueIn = validDate.format('YY-MM-DD')
await expect(contactValidation.createBirthDateValidator(Joi).validateAsync(testValueIn)).rejects.toThrow(INVALID_DATE_ERROR_MESSAGE)
})
it("throws if given tommorow's date", async () => {
await expect(
contactValidation.createBirthDateValidator(Joi).validateAsync(moment().add(1, 'days').format('YYYY-MM-DD'))
).rejects.toThrow('"value" must be less than or equal to "now"')
})
it('throws if given a date of a person aged over 120', async () => {
await expect(
contactValidation
.createBirthDateValidator(Joi)
.validateAsync(moment().subtract(120, 'years').subtract(1, 'days').format('YYYY-MM-DD'))
).rejects.toThrow('"value" date before minimum allowed')
})
})
describe('firstNameValidator', () => {
describe('converts to title case', () => {
it.each([
[' mIchael-hArrY ', 'Michael-Harry'],
[' érmintrùdé ', 'Érmintrùdé']
])('converts %s to %s', async (name, expected) => {
await expect(contactValidation.createFirstNameValidator(Joi).validateAsync(name)).resolves.toEqual(expected)
})
})
describe('standardises formatting of allowed punctuation and standardises spacing', () => {
it.each([
// Standard dash
[' Peter - Paul ', 'Peter-Paul'],
// Endash
['Peter – Paul', 'Peter-Paul'],
// Emdash
['Peter — Paul', 'Peter-Paul'],
// Comma
['Peter, Paul,', 'Peter Paul'],
// Period
['Peter . Paul .', 'Peter Paul'],
['J.Sue.', 'J Sue']
])('converts %s to %s', async (name, expected) => {
await expect(contactValidation.createFirstNameValidator(Joi).validateAsync(name)).resolves.toEqual(expected)
})
})
describe('allows specific punctuation characters', () => {
it.each("'-".split(''))('allows the %s character', async c => {
await expect(contactValidation.createFirstNameValidator(Joi).validateAsync(`Test${c}Separator`)).resolves.toEqual(
`Test${c}Separator`
)
})
})
describe('does not allow names containing banned characters', () => {
it.each('!@£$%^&()+*/{}[];":;|\\?<>§±`~0123456789'.split(''))('does not allow a string containing the %s character', async c => {
await expect(contactValidation.createFirstNameValidator(Joi).validateAsync(`Mich${c}`)).rejects.toThrow(
'contains forbidden characters'
)
})
})
it('allows and trims forenames', async () => {
await expect(contactValidation.createFirstNameValidator(Joi).validateAsync(' Peter Paul ')).resolves.toEqual('Peter Paul')
})
it.each([
['', '"value" is not allowed to be empty'],
['..', '"value" must contain at least 2 alpha characters'],
['()', '"value" must contain at least 2 alpha characters'],
["''", '"value" must contain at least 2 alpha characters'],
['--', '"value" must contain at least 2 alpha characters'],
['A', '"value" must contain at least 2 alpha characters'],
['A..', '"value" must contain at least 2 alpha characters']
])('throws on cases where the forename does not contain sufficient alpha characters - "%s"', async (testValue, expectedError) => {
await expect(contactValidation.createFirstNameValidator(Joi).validateAsync(testValue)).rejects.toThrow(expectedError)
})
it('throws where the name exceeds the maximum allowed length', async () => {
await expect(contactValidation.createFirstNameValidator(Joi).validateAsync('A'.repeat(101))).rejects.toThrow(
'"value" length must be less than or equal to 100 characters long'
)
})
it('allows a range of unicode characters from plane 1', async () => {
const internationStr = 'ÆÇÉÑØĶŤ'
await expect(contactValidation.createFirstNameValidator(Joi).validateAsync(internationStr)).resolves.toEqual('Æçéñøķť')
})
it('allows the minimum number of required alpha characters to be configured', async () => {
// Default to 2
await expect(contactValidation.createFirstNameValidator(Joi).validateAsync('AB')).resolves.toEqual('Ab')
// Allows customisation of rules using minimumLength property
await expect(contactValidation.createFirstNameValidator(Joi, { minimumLength: 3 }).validateAsync('AB')).rejects.toThrow(
'"value" must contain at least 3 alpha characters'
)
})
it.each([
'M̵i̵c̵h̵a̵e̵l̵',
'M̷i̷c̷h̷a̷e̷l̷',
'M͟i͟c͟h͟a͟e͟l͟',
'𝔐𝔦𝔠𝔥𝔞𝔢𝔩',
'𝕄𝕚𝕔𝕙𝕒𝕖𝕝',
'ןǝɐɥɔıW',
'Ⓜⓘⓒⓗⓐⓔⓛ',
'🄼🄸🄲🄷🄰🄴🄻',
'Mɪᴄʜᴀᴇʟ',
'ᴹᶦᶜʰᵃᵉˡ',
'𖢑𖥣𖥐𖦙𖧥𖠢ꛚ',
'ℳ𝒾𝒸𝒽𝒶ℯ𝓁',
'𝙼𝚒𝚌𝚑𝚊𝚎𝚕 '
])('prohibits a string with non-standard characters: %s', async c => {
await expect(contactValidation.createFirstNameValidator(Joi).validateAsync(c)).rejects.toThrow()
})
})
describe('lastNameValidator', () => {
describe('converts to title case', () => {
it.each([
[' SMITH-JONES ', 'Smith-Jones'],
['smith-jones', 'Smith-Jones'],
['denver', 'Denver'],
['ian st. john', 'Ian St John'],
['smythé', 'Smythé'],
["O'DELL", "O'Dell"],
['mcdonald', 'McDonald'],
['macdonald', 'Macdonald'],
['macy', 'Macy'],
['van doorn', 'van Doorn'],
['de vries', 'de Vries'],
['van der waals', 'van der Waals'],
['van den heuvel', 'van den Heuvel']
])('converts %s to %s', async (name, expected) => {
await expect(contactValidation.createLastNameValidator(Joi).validateAsync(name)).resolves.toEqual(expected)
})
})
describe('standardises formatting of allowed punctuation and standardises spacing', () => {
it.each([
// Standard dash
[' Bedford - Cuffe ', 'Bedford-Cuffe'],
// Endash
['Bedford – Cuffe', 'Bedford-Cuffe'],
// Emdash
['Bedford — Cuffe', 'Bedford-Cuffe'],
// Apostrophe
["O' Connor", "O'Connor"],
// Right single quotation mark
['O’ Connor', "O'Connor"],
// Left single quotation mark
['O‘ Connor', "O'Connor"],
// Backtick/Grave Accent
['O` Connor', "O'Connor"],
// Acute Accent
['O´ Connor', "O'Connor"],
// Prime
['O′ Connor', "O'Connor"],
// Reversed prime
['O‵ Connor', "O'Connor"],
// Fullwidth apostrophe
['O'Connor', "O'Connor"],
// Brackets
['Dean ( Senior ) ', 'Dean (Senior)']
])('converts %s to %s', async (name, expected) => {
await expect(contactValidation.createLastNameValidator(Joi).validateAsync(name)).resolves.toEqual(expected)
})
})
describe('allows specific punctuation characters', () => {
it.each("'-".split(''))('allows the %s character', async c => {
await expect(contactValidation.createLastNameValidator(Joi).validateAsync(`Test${c}Separator`)).resolves.toEqual(
`Test${c}Separator`
)
})
})
describe('does not allow names containing banned characters', () => {
it.each('!@£$%^&()+*/{}[];":;|\\?<>§±~0123456789'.split(''))('does not allow the %s character', async c => {
await expect(contactValidation.createLastNameValidator(Joi).validateAsync(`Gra${c}am`)).rejects.toThrow(
'contains forbidden characters'
)
})
})
it.each([
['', '"value" is not allowed to be empty'],
['..', '"value" must contain at least 2 alpha characters'],
['()', '"value" must contain at least 2 alpha characters'],
["''", '"value" must contain at least 2 alpha characters'],
['--', '"value" must contain at least 2 alpha characters'],
['A', '"value" must contain at least 2 alpha characters'],
['A..', '"value" must contain at least 2 alpha characters']
])('throws on cases where the last name does not contain sufficient alpha characters - "%s"', async (testValue, expectedError) => {
await expect(contactValidation.createLastNameValidator(Joi).validateAsync(testValue)).rejects.toThrow(expectedError)
})
it('throws where the name exceeds the maximum allowed length', async () => {
await expect(contactValidation.createLastNameValidator(Joi).validateAsync('A'.repeat(101))).rejects.toThrow(
'"value" length must be less than or equal to 100 characters long'
)
})
it('allows a range of unicode characters from plane 1', async () => {
const internationStr = 'ÆÇÉÑØĶŤ'
await expect(contactValidation.createLastNameValidator(Joi).validateAsync(internationStr)).resolves.toEqual('Æçéñøķť')
})
it('allows the minimum number of required alpha characters to be configured', async () => {
// Default to 2
await expect(contactValidation.createLastNameValidator(Joi).validateAsync('AB')).resolves.toEqual('Ab')
// Allows customisation of rules using minimumLength property
await expect(contactValidation.createLastNameValidator(Joi, { minimumLength: 3 }).validateAsync('AB')).rejects.toThrow(
'"value" must contain at least 3 alpha characters'
)
})
it.each([
'M̵i̵c̵h̵a̵e̵l̵',
'M̷i̷c̷h̷a̷e̷l̷',
'M͟i͟c͟h͟a͟e͟l͟',
'𝔐𝔦𝔠𝔥𝔞𝔢𝔩',
'𝕄𝕚𝕔𝕙𝕒𝕖𝕝',
'ןǝɐɥɔıW',
'Ⓜⓘⓒⓗⓐⓔⓛ',
'🄼🄸🄲🄷🄰🄴🄻',
'Mɪᴄʜᴀᴇʟ',
'ᴹᶦᶜʰᵃᵉˡ',
'𖢑𖥣𖥐𖦙𖧥𖠢ꛚ',
'ℳ𝒾𝒸𝒽𝒶ℯ𝓁',
'𝙼𝚒𝚌𝚑𝚊𝚎𝚕'
])('prohibits a string with non-standard characters: %s', async c => {
await expect(contactValidation.createLastNameValidator(Joi).validateAsync(c)).rejects.toThrow()
})
})
describe('emailValidator', () => {
it('expects an email with 2 domain segments', async () => {
await expect(contactValidation.createEmailValidator(Joi).validateAsync('person@example.com')).resolves.toEqual('person@example.com')
})
it('throws on a single segment', async () => {
await expect(contactValidation.createEmailValidator(Joi).validateAsync('person@example')).rejects.toThrow(
'"value" must be a valid email'
)
})
it('allows a range of unicode characters from plane 1', async () => {
const internationStr = 'æçéñøķť@email.com'
await expect(contactValidation.createEmailValidator(Joi).validateAsync(internationStr)).resolves.toEqual('æçéñøķť@email.com')
})
it.each([
'ᵐᵢᶜₕᵃₑˡ@ᵉₘᵃᵢˡ.ᶜₒᵐ',
'𝓂𝒾𝒸𝒽𝒶ℯ𝓁@ℯ𝓂𝒶𝒾𝓁.𝒸ℴ𝓂',
'm̶i̶c̶h̶a̶e̶l̶@̶e̶m̶a̶i̶l̶.̶c̶o̶m̶',
'm̷i̷c̷h̷a̷e̷l̷@̷e̷m̷a̷i̷l̷.̷c̷o̷m̷',
'𝖒𝖎𝖈𝖍𝖆𝖊𝖑@𝖊𝖒𝖆𝖎𝖑.𝖈𝖔𝖒',
'm̲i̲c̲h̲a̲e̲l̲@̲e̲m̲a̲i̲l̲.̲c̲o̲m̲',
'ꕮꕯꖀꖾꗇꗍꝆ@ꗍꕮꗇꕯꝆ.ꖀꗞꕮ',
'🅼🅘🅲🅗🅰🅔🅻@🅴🅜🅰🅘🅻.🅲🅞🅼',
'ɯoɔ˙ןıɐɯǝ@ןǝɐɥɔıɯ',
'ꮇꮖꮯꮋꭺꭼꮮ@ꭼꮇꭺꮖꮮ.ꮯꮎꮇ',
'michael@email.com',
'ₘᵢcₕaₑₗ@ₑₘaᵢₗ.cₒₘ'
])('prohibits a string with non-standard characters: %s', async c => {
await expect(contactValidation.createEmailValidator(Joi).validateAsync(c)).rejects.toThrow()
})
})
describe('mobilePhoneValidator', () => {
it.each(['+44 7700 900088', '07700 900088'])('validates %s successfully', async number => {
await expect(contactValidation.createMobilePhoneValidator(Joi).validateAsync(number)).resolves.toEqual(number)
})
it.each(['test', '07700 test'])('rejects the invalid number %s', async number => {
await expect(contactValidation.createMobilePhoneValidator(Joi).validateAsync(number)).rejects.toThrow()
})
it.each([
'𝟘𝟟𝟟𝟘𝟘 𝟡𝟘𝟘𝟘𝟠𝟠',
'0𝟟7𝟘0 9𝟘0𝟘8𝟠',
'0𝟽𝟽00 𝟿000𝟾𝟾',
'0̵7̵7̵0̵0̵ ̵9̵0̵0̵0̵8̵8̵',
'0͟7͟7͟0͟0͟ ͟9͟0͟0͟0͟8͟8͟',
'0̸7̸7̸0̸0̸ ̸9̸0̸0̸0̸8̸8̸',
'07700 900088',
'⁰⁷⁷⁰⁰ ⁹⁰⁰⁰⁸⁸',
'⓿➐➐⓿⓿ ➒⓿⓿⓿➑➑',
'+ㄐㄐワワㄖㄖ ㄢㄖㄖㄖ曰曰',
'07700👏 900088',
'0̐̈7̐̈7̐̈0̐̈0̐̈ ̐̈9̐̈0̐̈0̐̈0̐̈8̐̈8̐̈',
'+4④7⑦0⓪ ⑨0⓪0⑧8'
])('prohibits a string with non-standard characters: %s', async c => {
await expect(contactValidation.createMobilePhoneValidator(Joi).validateAsync(c)).rejects.toThrow()
})
})
describe('ukPostcodeValidator', () => {
it.each([
['ba21nw', 'BA2 1NW'],
[' AB12 3CD ', 'AB12 3CD'],
['AB123CD ', 'AB12 3CD']
])('formats the UK postcode %s successfully as %s', async (postcode, replacedValue) => {
await expect(contactValidation.createUKPostcodeValidator(Joi).validateAsync(postcode)).resolves.toEqual(replacedValue)
})
it('expects a minimum of 1 character', async () => {
await expect(contactValidation.createUKPostcodeValidator(Joi).validateAsync('')).rejects.toThrow('"value" is not allowed to be empty')
})
it('expects a maximum of 12 characters', async () => {
await expect(contactValidation.createUKPostcodeValidator(Joi).validateAsync('0123456789ABC')).rejects.toThrow(
'"value" length must be less than or equal to 12 characters long'
)
})
it('expects postcodes to conform to the pattern used in the UK', async () => {
await expect(contactValidation.createUKPostcodeValidator(Joi).validateAsync('0123456789')).rejects.toThrow(
/fails to match the required pattern/
)
})
it.each([
'A⃣B⃣1⃣2⃣ 1⃣A⃣B⃣',
'🄐🄑⑴⑵ ⑴🄐🄑',
'丹乃丨己 丨丹乃',
'A͢B͢1͢2͢ ͢1͢A͢B͢',
'A⃟B⃟1⃟2⃟ 1⃟A⃟B⃟',
'AB12👏 1AB',
'🅐Ⓑ➊② ①🅐Ⓑ',
'𝘼𝐵𝟭𝟮 1𝘼𝘽',
'🅰𝙱12 1𝕬𝓑',
'1ᴬAᴮB¹²',
'ᴬᴮ¹² ¹ᴬᴮ',
'q∀1 21q∀',
'A̶B̶1̶2̶ ̶1̶A̶B̶'
])('prohibits a string with non-standard characters: %s', async c => {
await expect(contactValidation.createUKPostcodeValidator(Joi).validateAsync(c)).rejects.toThrow()
})
})
describe('overseasPostcodeValidator', () => {
it('converts to uppercase and trims', async () => {
await expect(contactValidation.createOverseasPostcodeValidator(Joi).validateAsync('a ')).resolves.toEqual('A')
})
it('expects a minimum of 1 character', async () => {
await expect(contactValidation.createOverseasPostcodeValidator(Joi).validateAsync('')).rejects.toThrow(
'"value" is not allowed to be empty'
)
})
it('expects a maximum of 12 characters', async () => {
await expect(contactValidation.createOverseasPostcodeValidator(Joi).validateAsync('123456789AAAA')).rejects.toThrow()
})
it('will not accept special characters', async () => {
await expect(contactValidation.createOverseasPostcodeValidator(Joi).validateAsync('12£4')).rejects.toThrow()
})
it.each([
'A⃣B⃣1⃣2⃣ 1⃣A⃣B⃣',
'🄐🄑⑴⑵ ⑴🄐🄑',
'丹乃丨己 丨丹乃',
'A͢B͢1͢2͢ ͢1͢A͢B͢',
'A⃟B⃟1⃟2⃟ 1⃟A⃟B⃟',
'AB12👏 1AB',
'🅐Ⓑ➊② ①🅐Ⓑ',
'𝘼𝐵𝟭𝟮 1𝘼𝘽',
'🅰𝙱12 1𝕬𝓑',
'1ᴬAᴮB¹²',
'ᴬᴮ¹² ¹ᴬᴮ',
'q∀1 21q∀',
'A̶B̶1̶2̶ ̶1̶A̶B̶'
])('prohibits a string with non-standard characters: %s', async c => {
await expect(contactValidation.createOverseasPostcodeValidator(Joi).validateAsync(c)).rejects.toThrow()
})
})
describe('premisesValidator', () => {
it('allows and trims premises', async () => {
await expect(contactValidation.createPremisesValidator(Joi).validateAsync(' 15 ROSE COTTAGE ')).resolves.toEqual('15 Rose Cottage')
})
it('throws on empty premises', async () => {
await expect(contactValidation.createPremisesValidator(Joi).validateAsync('')).rejects.toThrow('"value" is not allowed to be empty')
})
it('throws where the premises exceeds the maximum allowed length', async () => {
await expect(contactValidation.createPremisesValidator(Joi).validateAsync('A'.repeat(51))).rejects.toThrow(
'"value" length must be less than or equal to 50 characters long'
)
})
it.each([
'15 𐝥ꗞꕷꗍ ꖀꗞꖡꖡꗇꗱꗍ',
'15 Rose Cottage',
'¹⁵ ᴿᵒˢᵉ ᶜᵒᵗᵗᵃᵍᵉ',
'15 ᖇᐤᔆᕪ ᐸᐤᐩᐩᐞᕐᕪ',
'15👏 Rose👏 Cottage',
'1̶5̶ ̶R̶o̶s̶e̶ ̶C̶o̶t̶t̶a̶g̶e̶',
'1̲5̲ ̲R̲o̲s̲e̲ ̲C̲o̲t̲t̲a̲g̲e̲',
'1̸5̸ ̸R̸o̸s̸e̸ ̸C̸o̸t̸t̸a̸g̸e̸',
'➊➎ 🅡🅞🅢🅔 🅒🅞🅣🅣🅐🅖🅔',
'①➎ 🅡ⓞ🅢ⓔ Ⓒ🅞ⓣ🅣ⓐ🅖ⓔ',
'1⑤ 𝑅𝐨𝑠ⓔ 𝒞𝓸𝘁𝕥𝒶ℊ🄴',
'𝟏𝟓 𝐑𝐨𝐬𝐞 𝐂𝐨𝐭𝐭𝐚𝐠𝐞'
])('prohibits a string with non-standard characters: %s', async c => {
await expect(contactValidation.createPremisesValidator(Joi).validateAsync(c)).rejects.toThrow()
})
})
describe('streetValidator', () => {
it('allows and trims street', async () => {
await expect(contactValidation.createStreetValidator(Joi).validateAsync(' BOND STREET ')).resolves.toEqual('Bond Street')
})
it('allows empty street', async () => {
await expect(contactValidation.createStreetValidator(Joi).validateAsync('')).resolves.toBeFalsy()
})
it('throws where the street exceeds the maximum allowed length', async () => {
await expect(contactValidation.createStreetValidator(Joi).validateAsync('A'.repeat(101))).rejects.toThrow(
'"value" length must be less than or equal to 100 characters long'
)
})
})
describe('localityValidator', () => {
it('allows and trims locality', async () => {
await expect(contactValidation.createLocalityValidator(Joi).validateAsync(' MAYFAIR ')).resolves.toEqual('Mayfair')
})
it('allows empty locality', async () => {
await expect(contactValidation.createLocalityValidator(Joi).validateAsync('')).resolves.toBeFalsy()
})
it('throws where the locality exceeds the maximum allowed length', async () => {
await expect(contactValidation.createLocalityValidator(Joi).validateAsync('A'.repeat(101))).rejects.toThrow(
'"value" length must be less than or equal to 100 characters long'
)
})
})
describe('townValidator', () => {
describe('converts to title case', () => {
it.each([
['lOndon', 'London'],
['newcastle upon tyne', 'Newcastle upon Tyne'],
['wotton-under-edge', 'Wotton-under-Edge'],
['barrow-in-ferness', 'Barrow-in-Ferness'],
['stoke-on-trent', 'Stoke-on-Trent'],
['sutton cum lound', 'Sutton cum Lound'],
['wells-next-the-sea', 'Wells-next-the-Sea'],
['chapel-en-le-frith', 'Chapel-en-le-Frith'],
['puddleby-on-the-marsh', 'Puddleby-on-the-Marsh'],
['weston-super-mare', 'Weston-super-Mare']
])('converts %s to %s', async (name, expected) => {
await expect(contactValidation.createTownValidator(Joi).validateAsync(name)).resolves.toEqual(expected)
})
})
it('allows and trims town', async () => {
await expect(contactValidation.createTownValidator(Joi).validateAsync(' LONDON ')).resolves.toEqual('London')
})
it('throws on empty town', async () => {
await expect(contactValidation.createTownValidator(Joi).validateAsync('')).rejects.toThrow('"value" is not allowed to be empty')
})
it('throws where the town exceeds the maximum allowed length', async () => {
await expect(contactValidation.createTownValidator(Joi).validateAsync('A'.repeat(101))).rejects.toThrow(
'"value" length must be less than or equal to 100 characters long'
)
})
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̲'])(
'prohibits a string with non-standard characters: %s',
async c => {
await expect(contactValidation.createTownValidator(Joi).validateAsync(c)).rejects.toThrow()
}
)
})
describe('nationalInsuranceNumberValidator', () => {
it('Allows valid NI number AB123456A', async () => {
await expect(contactValidation.createNationalInsuranceNumberValidator(Joi).validateAsync('AB123456A')).resolves.toEqual(
'AB 12 34 56 A'
)
})
it('Disallows invalid NI number QQ123456A', async () => {
await expect(contactValidation.createNationalInsuranceNumberValidator(Joi).validateAsync('QQ123456A')).rejects.toThrow()
})
it('Disallows invalid NI number BG123456A', async () => {
await expect(contactValidation.createNationalInsuranceNumberValidator(Joi).validateAsync('QQ123456A')).rejects.toThrow()
})
it.each([
'A̲B̲1̲2̲3̲4̲5̲6̲A̲',
'A̸B̸1̸2̸3̸4̸5̸6̸A̸',
'AB123456A',
'ᴬᴮ¹²³⁴⁵⁶ᴬ',
'🅐🅑①②③④⑤⑥🅐',
'🅐ⓑ①②③④⑤⑥ⓐ',
'A⃠B⃠1⃠2⃠3⃠4⃠5⃠6⃠A⃠',
'升A马B丨1己2ヨ3ㄐ4丂5石6刄A',
'✌️AB123456A✌️',
'𝐀𝐁𝟏𝟐𝟑𝟒𝟓𝟔𝐀'
])('prohibits a string with non-standard characters: %s', async c => {
await expect(contactValidation.createNationalInsuranceNumberValidator(Joi).validateAsync(c)).rejects.toThrow()
})
})
})