diff --git a/README.md b/README.md index 0b2e9b7ff..153b1e0ed 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,7 @@ null' are accepted as valid JSON values. **isURL(str [, options])** | check if the string is an URL.

`options` is an object which defaults to `{ protocols: ['http','https','ftp'], require_tld: true, require_protocol: false, require_host: true, require_port: false, require_valid_protocol: true, allow_underscores: false, host_whitelist: false, host_blacklist: false, allow_trailing_dot: false, allow_protocol_relative_urls: false, allow_fragments: true, allow_query_components: true, disallow_auth: false, validate_length: true }`.

require_protocol - if set as true isURL will return false if protocol is not present in the URL.
require_valid_protocol - isURL will check if the URL's protocol is present in the protocols option.
protocols - valid protocols can be modified with this option.
require_host - if set as false isURL will not check if host is present in the URL.
require_port - if set as true isURL will check if port is present in the URL.
allow_protocol_relative_urls - if set as true protocol relative URLs will be allowed.
allow_fragments - if set as false isURL will return false if fragments are present.
allow_query_components - if set as false isURL will return false if query components are present.
validate_length - if set as false isURL will skip string length validation (2083 characters is IE max URL length). **isUUID(str [, version])** | check if the string is a UUID (version 1, 2, 3, 4 or 5). **isVariableWidth(str)** | check if the string contains a mixture of full and half-width chars. -**isVAT(str, countryCode)** | checks that the string is a [valid VAT number](https://en.wikipedia.org/wiki/VAT_identification_number) if validation is available for the given country code matching [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2).

Available country codes: `[ 'GB', 'IT','NL' ]`. +**isVAT(str, countryCode)** | checks that the string is a [valid VAT number](https://en.wikipedia.org/wiki/VAT_identification_number) if validation is available for the given country code matching [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2).

Available country codes: `[ 'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'EL', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'AL', 'MK', 'AU', 'BY', 'CA', 'IS', 'IN', 'ID', 'IL', 'KZ', 'NZ', 'NG', 'NO', 'PH', 'RU', 'SM', 'SA', 'RS', 'CH', 'TR', 'UA', 'GB', 'UZ', 'AR', 'BO', 'BR', 'CL', 'CO', 'CR', 'EC', 'SV', 'GT', 'HN', 'MX', 'NI', 'PA', 'PY', 'PE', 'DO', 'UY', 'VE' ]`. **isWhitelisted(str, chars)** | checks characters if they appear in the whitelist. **matches(str, pattern [, modifiers])** | check if string matches the pattern.

Either `matches('foo', /foo/i)` or `matches('foo', 'foo', 'i')`. diff --git a/src/lib/isVAT.js b/src/lib/isVAT.js index 884b066ff..95593569d 100644 --- a/src/lib/isVAT.js +++ b/src/lib/isVAT.js @@ -1,9 +1,101 @@ import assertString from './util/assertString'; +import * as algorithms from './util/algorithms'; + +const PT = (str) => { + const match = str.match(/^(PT)?(\d{9})$/); + if (!match) { + return false; + } + + const tin = match[2]; + + const checksum = 11 - (algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 8).map(a => parseInt(a, 10)), 9) % 11); + if (checksum > 9) { + return parseInt(tin[8], 10) === 0; + } + return checksum === parseInt(tin[8], 10); +}; export const vatMatchers = { - GB: /^GB((\d{3} \d{4} ([0-8][0-9]|9[0-6]))|(\d{9} \d{3})|(((GD[0-4])|(HA[5-9]))[0-9]{2}))$/, - IT: /^(IT)?[0-9]{11}$/, - NL: /^(NL)?[0-9]{9}B[0-9]{2}$/, + /** + * European Union VAT identification numbers + */ + AT: str => /^(AT)?U\d{8}$/.test(str), + BE: str => /^(BE)?\d{10}$/.test(str), + BG: str => /^(BG)?\d{9,10}$/.test(str), + HR: str => /^(HR)?\d{11}$/.test(str), + CY: str => /^(CY)?\w{9}$/.test(str), + CZ: str => /^(CZ)?\d{8,10}$/.test(str), + DK: str => /^(DK)?\d{8}$/.test(str), + EE: str => /^(EE)?\d{9}$/.test(str), + FI: str => /^(FI)?\d{8}$/.test(str), + FR: str => /^(FR)?\w{2}\d{9}$/.test(str), + DE: str => /^(DE)?\d{9}$/.test(str), + EL: str => /^(EL)?\d{9}$/.test(str), + HU: str => /^(HU)?\d{8}$/.test(str), + IE: str => /^(IE)?\d{7}\w{1}(W)?$/.test(str), + IT: str => /^(IT)?\d{11}$/.test(str), + LV: str => /^(LV)?\d{11}$/.test(str), + LT: str => /^(LT)?\d{9,12}$/.test(str), + LU: str => /^(LU)?\d{8}$/.test(str), + MT: str => /^(MT)?\d{8}$/.test(str), + NL: str => /^(NL)?\d{9}B\d{2}$/.test(str), + PL: str => /^(PL)?(\d{10}|(\d{3}-\d{3}-\d{2}-\d{2})|(\d{3}-\d{2}-\d{2}-\d{3}))$/.test(str), + PT, + RO: str => /^(RO)?\d{2,10}$/.test(str), + SK: str => /^(SK)?\d{10}$/.test(str), + SI: str => /^(SI)?\d{8}$/.test(str), + ES: str => /^(ES)?\w\d{7}[A-Z]$/.test(str), + SE: str => /^(SE)?\d{12}$/.test(str), + + /** + * VAT numbers of non-EU countries + */ + AL: str => /^(AL)?\w{9}[A-Z]$/.test(str), + MK: str => /^(MK)?\d{13}$/.test(str), + AU: str => /^(AU)?\d{11}$/.test(str), + BY: str => /^(УНП )?\d{9}$/.test(str), + CA: str => /^(CA)?\d{9}$/.test(str), + IS: str => /^(IS)?\d{5,6}$/.test(str), + IN: str => /^(IN)?\d{15}$/.test(str), + ID: str => /^(ID)?(\d{15}|(\d{2}.\d{3}.\d{3}.\d{1}-\d{3}.\d{3}))$/.test(str), + IL: str => /^(IL)?\d{9}$/.test(str), + KZ: str => /^(KZ)?\d{9}$/.test(str), + NZ: str => /^(NZ)?\d{9}$/.test(str), + NG: str => /^(NG)?(\d{12}|(\d{8}-\d{4}))$/.test(str), + NO: str => /^(NO)?\d{9}MVA$/.test(str), + PH: str => /^(PH)?(\d{12}|\d{3} \d{3} \d{3} \d{3})$/.test(str), + RU: str => /^(RU)?(\d{10}|\d{12})$/.test(str), + SM: str => /^(SM)?\d{5}$/.test(str), + SA: str => /^(SA)?\d{15}$/.test(str), + RS: str => /^(RS)?\d{9}$/.test(str), + CH: str => /^(CH)?(\d{6}|\d{9}|(\d{3}.\d{3})|(\d{3}.\d{3}.\d{3}))(TVA|MWST|IVA)$/.test(str), + TR: str => /^(TR)?\d{10}$/.test(str), + UA: str => /^(UA)?\d{12}$/.test(str), + GB: str => /^GB((\d{3} \d{4} ([0-8][0-9]|9[0-6]))|(\d{9} \d{3})|(((GD[0-4])|(HA[5-9]))[0-9]{2}))$/.test(str), + UZ: str => /^(UZ)?\d{9}$/.test(str), + + /** + * VAT numbers of Latin American countries + */ + AR: str => /^(AR)?\d{11}$/.test(str), + BO: str => /^(BO)?\d{7}$/.test(str), + BR: str => /^(BR)?((\d{2}.\d{3}.\d{3}\/\d{4}-\d{2})|(\d{3}.\d{3}.\d{3}-\d{2}))$/.test(str), + CL: str => /^(CL)?\d{8}-\d{1}$/.test(str), + CO: str => /^(CO)?\d{10}$/.test(str), + CR: str => /^(CR)?\d{9,12}$/.test(str), + EC: str => /^(EC)?\d{13}$/.test(str), + SV: str => /^(SV)?\d{4}-\d{6}-\d{3}-\d{1}$/.test(str), + GT: str => /^(GT)?\d{7}-\d{1}$/.test(str), + HN: str => /^(HN)?$/.test(str), + MX: str => /^(MX)?\w{3,4}\d{6}\w{3}$/.test(str), + NI: str => /^(NI)?\d{3}-\d{6}-\d{4}\w{1}$/.test(str), + PA: str => /^(PA)?$/.test(str), + PY: str => /^(PY)?\d{6,8}-\d{1}$/.test(str), + PE: str => /^(PE)?\d{11}$/.test(str), + DO: str => /^(DO)?(\d{11}|(\d{3}-\d{7}-\d{1})|[1,4,5]{1}\d{8}|([1,4,5]{1})-\d{2}-\d{5}-\d{1})$/.test(str), + UY: str => /^(UY)?\d{12}$/.test(str), + VE: str => /^(VE)?[J,G,V,E]{1}-(\d{9}|(\d{8}-\d{1}))$/.test(str), }; export default function isVAT(str, countryCode) { @@ -11,7 +103,7 @@ export default function isVAT(str, countryCode) { assertString(countryCode); if (countryCode in vatMatchers) { - return vatMatchers[countryCode].test(str); + return vatMatchers[countryCode](str); } throw new Error(`Invalid country code: '${countryCode}'`); } diff --git a/test/validators.js b/test/validators.js index 0f96f0398..ea1e4010f 100644 --- a/test/validators.js +++ b/test/validators.js @@ -12440,6 +12440,620 @@ describe('Validators', () => { }); }); it('should validate VAT numbers', () => { + test({ + validator: 'isVAT', + args: ['AT'], + valid: [ + 'ATU12345678', + 'U12345678', + ], + invalid: [ + 'AT 12345678', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['BE'], + valid: [ + 'BE1234567890', + '1234567890', + ], + invalid: [ + 'BE 1234567890', + '123456789', + ], + }); + test({ + validator: 'isVAT', + args: ['BG'], + valid: [ + 'BG1234567890', + '1234567890', + 'BG123456789', + '123456789', + ], + invalid: [ + 'BG 1234567890', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['HR'], + valid: [ + 'HR12345678901', + '12345678901', + ], + invalid: [ + 'HR 12345678901', + '1234567890', + ], + }); + test({ + validator: 'isVAT', + args: ['CY'], + valid: [ + 'CY123456789', + '123456789', + ], + invalid: [ + 'CY 123456789', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['CZ'], + valid: [ + 'CZ1234567890', + 'CZ123456789', + 'CZ12345678', + '1234567890', + '123456789', + '12345678', + ], + invalid: [ + 'CZ 123456789', + '1234567', + ], + }); + test({ + validator: 'isVAT', + args: ['DK'], + valid: [ + 'DK12345678', + '12345678', + ], + invalid: [ + 'DK 12345678', + '1234567', + ], + }); + test({ + validator: 'isVAT', + args: ['EE'], + valid: [ + 'EE123456789', + '123456789', + ], + invalid: [ + 'EE 123456789', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['FI'], + valid: [ + 'FI12345678', + '12345678', + ], + invalid: [ + 'FI 12345678', + '1234567', + ], + }); + test({ + validator: 'isVAT', + args: ['FR'], + valid: [ + 'FRAA123456789', + 'AA123456789', + ], + invalid: [ + 'FR AA123456789', + '123456789', + ], + }); + test({ + validator: 'isVAT', + args: ['DE'], + valid: [ + 'DE123456789', + '123456789', + ], + invalid: [ + 'DE 123456789', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['EL'], + valid: [ + 'EL123456789', + '123456789', + ], + invalid: [ + 'EL 123456789', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['HU'], + valid: [ + 'HU12345678', + '12345678', + ], + invalid: [ + 'HU 12345678', + '1234567', + ], + }); + test({ + validator: 'isVAT', + args: ['IE'], + valid: [ + 'IE1234567AW', + '1234567AW', + ], + invalid: [ + 'IE 1234567', + '1234567', + ], + }); + test({ + validator: 'isVAT', + args: ['IT'], + valid: [ + 'IT12345678910', + '12345678910', + ], + invalid: [ + 'IT12345678 910', + 'IT 123456789101', + 'IT123456789101', + 'GB12345678910', + 'IT123456789', + ], + }); + test({ + validator: 'isVAT', + args: ['LV'], + valid: [ + 'LV12345678901', + '12345678901', + ], + invalid: [ + 'LV 12345678901', + '1234567890', + ], + }); + test({ + validator: 'isVAT', + args: ['LT'], + valid: [ + 'LT123456789012', + '123456789012', + 'LT12345678901', + '12345678901', + 'LT1234567890', + '1234567890', + 'LT123456789', + '123456789', + ], + invalid: [ + 'LT 123456789012', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['LU'], + valid: [ + 'LU12345678', + '12345678', + ], + invalid: [ + 'LU 12345678', + '1234567', + ], + }); + test({ + validator: 'isVAT', + args: ['MT'], + valid: [ + 'MT12345678', + '12345678', + ], + invalid: [ + 'MT 12345678', + '1234567', + ], + }); + test({ + validator: 'isVAT', + args: ['NL'], + valid: [ + 'NL123456789B10', + '123456789B10', + ], + invalid: [ + 'NL12345678 910', + 'NL 123456789101', + 'NL123456789B1', + 'GB12345678910', + 'NL123456789', + ], + }); + test({ + validator: 'isVAT', + args: ['PL'], + valid: [ + 'PL1234567890', + '1234567890', + 'PL123-456-78-90', + '123-456-78-90', + 'PL123-45-67-890', + '123-45-67-890', + ], + invalid: [ + 'PL 1234567890', + '123456789', + ], + }); + test({ + validator: 'isVAT', + args: ['PT'], + valid: [ + 'PT123456789', + '123456789', + ], + invalid: [ + 'PT 123456789', + '000000001', + ], + }); + test({ + validator: 'isVAT', + args: ['RO'], + valid: [ + 'RO1234567890', + '1234567890', + 'RO12', + '12', + ], + invalid: [ + 'RO 12', + '1', + ], + }); + test({ + validator: 'isVAT', + args: ['SK'], + valid: [ + 'SK1234567890', + '1234567890', + ], + invalid: [ + 'SK 1234567890', + '123456789', + ], + }); + test({ + validator: 'isVAT', + args: ['SI'], + valid: [ + 'SI12345678', + '12345678', + ], + invalid: [ + 'SI 12345678', + '1234567', + ], + }); + test({ + validator: 'isVAT', + args: ['ES'], + valid: [ + 'ESA1234567A', + 'A1234567A', + ], + invalid: [ + 'ES 1234567A', + '123456789', + ], + }); + test({ + validator: 'isVAT', + args: ['SE'], + valid: [ + 'SE123456789012', + '123456789012', + ], + invalid: [ + 'SE 123456789012', + '12345678901', + ], + }); + test({ + validator: 'isVAT', + args: ['AL'], + valid: [ + 'AL123456789A', + '123456789A', + ], + invalid: [ + 'AL 123456789A', + '123456789', + ], + }); + test({ + validator: 'isVAT', + args: ['MK'], + valid: [ + 'MK1234567890123', + '1234567890123', + ], + invalid: [ + 'MK 1234567890123', + '123456789012', + ], + }); + test({ + validator: 'isVAT', + args: ['AU'], + valid: [ + 'AU12345678901', + '12345678901', + ], + invalid: [ + 'AU 12345678901', + '1234567890', + ], + }); + test({ + validator: 'isVAT', + args: ['BY'], + valid: [ + 'УНП 123456789', + '123456789', + ], + invalid: [ + 'BY 123456789', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['CA'], + valid: [ + 'CA123456789', + '123456789', + ], + invalid: [ + 'CA 123456789', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['IS'], + valid: [ + 'IS123456', + '12345', + ], + invalid: [ + 'IS 12345', + '1234', + ], + }); + test({ + validator: 'isVAT', + args: ['IN'], + valid: [ + 'IN123456789012345', + '123456789012345', + ], + invalid: [ + 'IN 123456789012345', + '12345678901234', + ], + }); + test({ + validator: 'isVAT', + args: ['ID'], + valid: [ + 'ID123456789012345', + '123456789012345', + 'ID12.345.678.9-012.345', + '12.345.678.9-012.345', + ], + invalid: [ + 'ID 123456789012345', + '12345678901234', + ], + }); + test({ + validator: 'isVAT', + args: ['IL'], + valid: [ + 'IL123456789', + '123456789', + ], + invalid: [ + 'IL 123456789', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['KZ'], + valid: [ + 'KZ123456789', + '123456789', + ], + invalid: [ + 'KZ 123456789', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['NZ'], + valid: [ + 'NZ123456789', + '123456789', + ], + invalid: [ + 'NZ 123456789', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['NG'], + valid: [ + 'NG123456789012', + '123456789012', + 'NG12345678-9012', + '12345678-9012', + ], + invalid: [ + 'NG 123456789012', + '12345678901', + ], + }); + test({ + validator: 'isVAT', + args: ['NO'], + valid: [ + 'NO123456789MVA', + '123456789MVA', + ], + invalid: [ + 'NO 123456789MVA', + '123456789', + ], + }); + test({ + validator: 'isVAT', + args: ['PH'], + valid: [ + 'PH123456789012', + '123456789012', + 'PH123 456 789 012', + '123 456 789 012', + ], + invalid: [ + 'PH 123456789012', + '12345678901', + ], + }); + test({ + validator: 'isVAT', + args: ['RU'], + valid: [ + 'RU1234567890', + '1234567890', + 'RU123456789012', + '123456789012', + ], + invalid: [ + 'RU 123456789012', + '12345678901', + ], + }); + test({ + validator: 'isVAT', + args: ['SM'], + valid: [ + 'SM12345', + '12345', + ], + invalid: [ + 'SM 12345', + '1234', + ], + }); + test({ + validator: 'isVAT', + args: ['SA'], + valid: [ + 'SA123456789012345', + '123456789012345', + ], + invalid: [ + 'SA 123456789012345', + '12345678901234', + ], + }); + test({ + validator: 'isVAT', + args: ['RS'], + valid: [ + 'RS123456789', + '123456789', + ], + invalid: [ + 'RS 123456789', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['CH'], + valid: [ + 'CH123456TVA', + '123456TVA', + 'CH123456789MWST', + '123456789MWST', + 'CH123.456IVA', + '123.456IVA', + 'CH123.456.789TVA', + '123.456.789TVA', + ], + invalid: [ + 'CH 123456', + '12345', + ], + }); + test({ + validator: 'isVAT', + args: ['TR'], + valid: [ + 'TR1234567890', + '1234567890', + ], + invalid: [ + 'TR 1234567890', + '123456789', + ], + }); + test({ + validator: 'isVAT', + args: ['UA'], + valid: [ + 'UA123456789012', + '123456789012', + ], + invalid: [ + 'UA 123456789012', + '12345678901', + ], + }); test({ validator: 'isVAT', args: ['GB'], @@ -12471,32 +13085,242 @@ describe('Validators', () => { }); test({ validator: 'isVAT', - args: ['IT'], + args: ['UZ'], valid: [ - 'IT12345678910', - '12345678910', + 'UZ123456789', + '123456789', ], invalid: [ - 'IT12345678 910', - 'IT 123456789101', - 'IT123456789101', - 'GB12345678910', - 'IT123456789', + 'UZ 123456789', + '12345678', ], }); test({ validator: 'isVAT', - args: ['NL'], + args: ['AR'], valid: [ - 'NL123456789B10', - '123456789B10', + 'AR12345678901', + '12345678901', ], invalid: [ - 'NL12345678 910', - 'NL 123456789101', - 'NL123456789B1', - 'GB12345678910', - 'NL123456789', + 'AR 12345678901', + '1234567890', + ], + }); + test({ + validator: 'isVAT', + args: ['BO'], + valid: [ + 'BO1234567', + '1234567', + ], + invalid: [ + 'BO 1234567', + '123456', + ], + }); + test({ + validator: 'isVAT', + args: ['BR'], + valid: [ + 'BR12.345.678/9012-34', + '12.345.678/9012-34', + 'BR123.456.789-01', + '123.456.789-01', + ], + invalid: [ + 'BR 12.345.678/9012-34', + '12345678901234', + ], + }); + test({ + validator: 'isVAT', + args: ['CL'], + valid: [ + 'CL12345678-9', + '12345678-9', + ], + invalid: [ + 'CL 12345678-9', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['CO'], + valid: [ + 'CO1234567890', + '1234567890', + ], + invalid: [ + 'CO 1234567890', + '123456789', + ], + }); + test({ + validator: 'isVAT', + args: ['CR'], + valid: [ + 'CR123456789012', + '123456789012', + 'CR123456789', + '123456789', + ], + invalid: [ + 'CR 123456789', + '12345678', + ], + }); + test({ + validator: 'isVAT', + args: ['EC'], + valid: [ + 'EC1234567890123', + '1234567890123', + ], + invalid: [ + 'EC 1234567890123', + '123456789012', + ], + }); + test({ + validator: 'isVAT', + args: ['SV'], + valid: [ + 'SV1234-567890-123-1', + '1234-567890-123-1', + ], + invalid: [ + 'SV 1234-567890-123-1', + '1234567890123', + ], + }); + test({ + validator: 'isVAT', + args: ['GT'], + valid: [ + 'GT1234567-8', + '1234567-8', + ], + invalid: [ + 'GT 1234567-8', + '1234567', + ], + }); + test({ + validator: 'isVAT', + args: ['HN'], + valid: [ + 'HN', + ], + invalid: [ + 'HN ', + ], + }); + test({ + validator: 'isVAT', + args: ['MX'], + valid: [ + 'MXABCD123456EFG', + 'ABCD123456EFG', + 'MXABC123456DEF', + 'ABC123456DEF', + ], + invalid: [ + 'MX ABC123456EFG', + '123456', + ], + }); + test({ + validator: 'isVAT', + args: ['NI'], + valid: [ + 'NI123-456789-0123A', + '123-456789-0123A', + ], + invalid: [ + 'NI 123-456789-0123A', + '1234567890123', + ], + }); + test({ + validator: 'isVAT', + args: ['PA'], + valid: [ + 'PA', + ], + invalid: [ + 'PA ', + ], + }); + test({ + validator: 'isVAT', + args: ['PY'], + valid: [ + 'PY12345678-9', + '12345678-9', + 'PY123456-7', + '123456-7', + ], + invalid: [ + 'PY 123456-7', + '123456', + ], + }); + test({ + validator: 'isVAT', + args: ['PE'], + valid: [ + 'PE12345678901', + '12345678901', + ], + invalid: [ + 'PE 12345678901', + '1234567890', + ], + }); + test({ + validator: 'isVAT', + args: ['DO'], + valid: [ + 'DO12345678901', + '12345678901', + 'DO123-4567890-1', + '123-4567890-1', + 'DO123456789', + '123456789', + 'DO1-23-45678-9', + '1-23-45678-9', + ], + invalid: [ + 'DO 12345678901', + '1234567890', + ], + }); + test({ + validator: 'isVAT', + args: ['UY'], + valid: [ + 'UY123456789012', + '123456789012', + ], + invalid: [ + 'UY 123456789012', + '12345678901', + ], + }); + test({ + validator: 'isVAT', + args: ['VE'], + valid: [ + 'VEJ-123456789', + 'J-123456789', + 'VEJ-12345678-9', + 'J-12345678-9', + ], + invalid: [ + 'VE J-123456789', + '12345678', ], }); test({