From b1cb3a0aecd0a9bc5f74b23010e3d959636b9721 Mon Sep 17 00:00:00 2001 From: Yuri Koller Date: Tue, 19 Nov 2024 16:49:54 -0500 Subject: [PATCH] Add validation for mobile numbers in isMobilePhone and update tests --- src/lib/isMobilePhone.js | 24 +++- test/validators.test.js | 295 +++++++++++++++++++++++++++++++++++---- 2 files changed, 283 insertions(+), 36 deletions(-) diff --git a/src/lib/isMobilePhone.js b/src/lib/isMobilePhone.js index 393ee6fbd..f4131e510 100644 --- a/src/lib/isMobilePhone.js +++ b/src/lib/isMobilePhone.js @@ -8,6 +8,7 @@ const phones = { 'ar-DZ': /^(\+?213|0)(5|6|7)\d{8}$/, 'ar-LB': /^(\+?961)?((3|81)\d{6}|7\d{7})$/, 'ar-EG': /^((\+?20)|0)?1[0125]\d{8}$/, + 'ar-EH': /^(\+?212|0)[\s\-]?(5288|5289)[\s\-]?\d{5}$/, 'ar-IQ': /^(\+?964|0)?7[0-9]\d{8}$/, 'ar-JO': /^(\+?962|0)?7[789]\d{7}$/, 'ar-KW': /^(\+?965)([569]\d{7}|41\d{6})$/, @@ -19,6 +20,7 @@ const phones = { 'ar-SD': /^((\+?249)|0)?(9[012369]|1[012])\d{7}$/, 'ar-SY': /^(!?(\+?963)|0)?9\d{8}$/, 'ar-TN': /^(\+?216)?[2459]\d{7}$/, + 'ar-YE': /^(((\+|00)9677|0?7)[0137]\d{7}|((\+|00)967|0)[1-7]\d{6})$/, 'az-AZ': /^(\+994|0)(10|5[015]|7[07]|99)\d{7}$/, 'bs-BA': /^((((\+|00)3876)|06))((([0-3]|[5-6])\d{6})|(4\d{7}))$/, 'be-BY': /^(\+?375)?(24|25|29|33|44)\d{7}$/, @@ -30,15 +32,19 @@ const phones = { 'de-DE': /^((\+49|0)1)(5[0-25-9]\d|6([23]|0\d?)|7([0-57-9]|6\d))\d{7,9}$/, 'de-AT': /^(\+43|0)\d{1,4}\d{3,12}$/, 'de-CH': /^(\+41|0)([1-9])\d{1,9}$/, + 'de-LI': /^(?:\+423|423)[\s]?(2\d{6}|[67]\d{6}|800\d{5}|90\d{5})$/, 'de-LU': /^(\+352)?((6\d1)\d{6})$/, 'dv-MV': /^(\+?960)?(7[2-9]|9[1-9])\d{5}$/, + 'dz-BT': /^(\+?975|0)?(17|16|77|02)\d{6}$/, 'el-GR': /^(\+?30|0)?6(8[5-9]|9(?![26])[0-9])\d{7}$/, 'el-CY': /^(\+?357?)?(9(9|6)\d{6})$/, 'en-AI': /^(\+?1|0)264(?:2(35|92)|4(?:6[1-2]|76|97)|5(?:3[6-9]|8[1-4])|7(?:2(4|9)|72))\d{4}$/, 'en-AU': /^(\+?61|0)4\d{8}$/, 'en-AG': /^(?:\+1|1)268(?:464|7(?:1[3-9]|[28]\d|3[0246]|64|7[0-689]))\d{4}$/, + 'en-BB': /^(?:\+1[-\s]?|011[-\s]?(?:1[-\s]?)?|1[-\s]?)(?:246|\(246\))[-\s]?\d{3}[-\s]?\d{4}$/, 'en-BM': /^(\+?1)?441(((3|7)\d{6}$)|(5[0-3][0-9]\d{4}$)|(59\d{5}$))/, 'en-BS': /^(\+?1[-\s]?|0)?\(?242\)?[-\s]?\d{3}[-\s]?\d{4}$/, + 'en-BZ': /^(\+?501)[2-8]\d{6}$/, 'en-GB': /^(\+?44|0)7[1-9]\d{8}$/, 'en-GG': /^(\+?44|0)1481\d{6}$/, 'en-GH': /^(\+233|0)(20|50|24|54|27|57|26|56|23|53|28|55|59)\d{7}$/, @@ -66,9 +72,12 @@ const phones = { 'en-RW': /^(\+?250|0)?[7]\d{8}$/, 'en-SG': /^(\+65)?[3689]\d{7}$/, 'en-SL': /^(\+?232|0)\d{8}$/, + 'en-SR': /^(\+?597)[1-9]\d{6}$/, 'en-TZ': /^(\+?255|0)?[67]\d{8}$/, 'en-UG': /^(\+?256|0)?[7]\d{8}$/, 'en-US': /^((\+1|1)?( |-)?)?(\([2-9][0-9]{2}\)|[2-9][0-9]{2})( |-)?([2-9][0-9]{2}( |-)?[0-9]{4})$/, + 'en-VU': /^\+?678\s?5\d{5}$/, + 'en-WS': /^(?:\+?685\s?)?(?:2\d{4}|[347]\d{5,6}|8\d{6}|5\d{6,7})$/, 'en-ZA': /^(\+?27|0)\d{9}$/, 'en-ZM': /^(\+?26)?0[79][567]\d{7}$/, 'en-ZW': /^(\+263)[0-9]{9}$/, @@ -93,6 +102,7 @@ const phones = { 'es-UY': /^(\+598|0)9[1-9][\d]{6}$/, 'es-VE': /^(\+?58)?(2|4)\d{9}$/, 'et-EE': /^(\+?372)?\s?(5|8[1-4])\s?([0-9]\s?){6,7}$/, + 'fa-AF': /^(\+93|0)?(2{1}[0-8]{1}|[3-5]{1}[0-4]{1})(\d{7})$/, 'fa-IR': /^(\+?98[\-\s]?|0)9[0-39]\d[\-\s]?\d{3}[\-\s]?\d{4}$/, 'fi-FI': /^(\+?358|0)\s?(4[0-6]|50)\s?(\d\s?){4,8}$/, 'fj-FJ': /^(\+?679)?\s?\d{3}\s?\d{4}$/, @@ -100,6 +110,7 @@ const phones = { 'fr-BF': /^(\+226|0)[67]\d{7}$/, 'fr-BJ': /^(\+229)\d{8}$/, 'fr-CD': /^(\+?243|0)?(8|9)\d{8}$/, + 'fr-MC': /^(?:\+377|377)[\s]?(?:[3469]\d{6,7}|800\d{4,5})$/, 'fr-CM': /^(\+?237)6[0-9]{8}$/, 'fr-FR': /^(\+?33|0)[67]\d{8}$/, 'fr-GF': /^(\+?594|0|00594)[67]\d{8}$/, @@ -112,13 +123,15 @@ const phones = { 'hu-HU': /^(\+?36|06)(20|30|31|50|70)\d{7}$/, 'id-ID': /^(\+?62|0)8(1[123456789]|2[1238]|3[1238]|5[12356789]|7[78]|9[56789]|8[123456789])([\s?|\d]{5,11})$/, 'ir-IR': /^(\+98|0)?9\d{9}$/, + 'is-IS': /^(\+?354)?\d{7}$/, 'it-IT': /^(\+?39)?\s?3\d{2} ?\d{6,7}$/, 'it-SM': /^((\+378)|(0549)|(\+390549)|(\+3780549))?6\d{5,9}$/, 'ja-JP': /^(\+81[ \-]?(\(0\))?|0)[6789]0[ \-]?\d{4}[ \-]?\d{4}$/, 'ka-GE': /^(\+?995)?(79\d{7}|5\d{8})$/, 'kk-KZ': /^(\+?7|8)?7\d{9}$/, 'kl-GL': /^(\+?299)?\s?\d{2}\s?\d{2}\s?\d{2}$/, - 'ko-KR': /^((\+?82)[ \-]?)?0?1([0|1|6|7|8|9]{1})[ \-]?\d{3,4}[ \-]?\d{4}$/, + 'ko-KP': /^(\+850|850)\d{7,8}$/, + 'ko-KR': /^\+(?:82)?[- ]?(?:0?[1-9]{2}|[1-9]{3})[- ]?\d{4}[- ]?\d{4}$|^\d{2,3}[- ]?\d{4}[- ]?\d{4}$/, 'ky-KG': /^(\+996\s?)?(22[0-9]|50[0-9]|55[0-9]|70[0-9]|75[0-9]|77[0-9]|880|990|995|996|997|998)\s?\d{3}\s?\d{3}$/, 'lt-LT': /^(\+370|8)\d{8}$/, 'lv-LV': /^(\+?371)2\d{7}$/, @@ -151,15 +164,12 @@ const phones = { 'th-TH': /^(\+66|66|0)\d{9}$/, 'tr-TR': /^(\+?90|0)?5\d{9}$/, 'tk-TM': /^(\+993|993|8)\d{8}$/, + 'to-TO': /^(?:\+?676 ?)[1-8]\d{3,5}$/, 'uk-UA': /^(\+?38)?0(50|6[36-8]|7[357]|9[1-9])\d{7}$/, 'uz-UZ': /^(\+?998)?(6[125-79]|7[1-69]|88|9\d)\d{7}$/, 'vi-VN': /^((\+?84)|0)((3([2-9]))|(5([25689]))|(7([0|6-9]))|(8([1-9]))|(9([0-9])))([0-9]{7})$/, 'zh-CN': /^((\+|00)86)?(1[3-9]|9[28])\d{9}$/, 'zh-TW': /^(\+?886\-?|0)?9\d{8}$/, - 'dz-BT': /^(\+?975|0)?(17|16|77|02)\d{6}$/, - 'ar-YE': /^(((\+|00)9677|0?7)[0137]\d{7}|((\+|00)967|0)[1-7]\d{6})$/, - 'ar-EH': /^(\+?212|0)[\s\-]?(5288|5289)[\s\-]?\d{5}$/, - 'fa-AF': /^(\+93|0)?(2{1}[0-8]{1}|[3-5]{1}[0-4]{1})(\d{7})$/, }; /* eslint-enable max-len */ @@ -190,10 +200,10 @@ export default function isMobilePhone(str, locale, options) { } return false; }); - } else if (locale in phones) { + } if (locale in phones) { return phones[locale].test(str); // alias falsey locale as 'any' - } else if (!locale || locale === 'any') { + } if (!locale || locale === 'any') { for (const key in phones) { // istanbul ignore else if (phones.hasOwnProperty(key)) { diff --git a/test/validators.test.js b/test/validators.test.js index af170bf69..b2e5a8887 100644 --- a/test/validators.test.js +++ b/test/validators.test.js @@ -281,7 +281,6 @@ describe('Validators', () => { }); }); - it('should validate really long emails if ignore_max_length is set', () => { test({ validator: 'isEmail', @@ -486,7 +485,6 @@ describe('Validators', () => { }); }); - it('should validate URLs with any protocol', () => { test({ validator: 'isURL', @@ -2930,7 +2928,6 @@ describe('Validators', () => { ], }); - test({ validator: 'isPassportNumber', args: ['ID'], @@ -4049,7 +4046,6 @@ describe('Validators', () => { }); }); - it('should validate imei strings', () => { test({ validator: 'isIMEI', @@ -4069,7 +4065,6 @@ describe('Validators', () => { }); }); - it('should validate imei strings with hyphens', () => { test({ validator: 'isIMEI', @@ -4090,7 +4085,6 @@ describe('Validators', () => { }); }); - it('should validate uppercase strings', () => { test({ validator: 'isUppercase', @@ -6016,7 +6010,6 @@ describe('Validators', () => { }); }); - it('should validate credit cards without a proper provider', () => { test({ validator: 'isCreditCard', @@ -6032,7 +6025,6 @@ describe('Validators', () => { }); }); - it('should validate AmEx provided credit cards', () => { test({ validator: 'isCreditCard', @@ -6068,7 +6060,6 @@ describe('Validators', () => { }); }); - it('should validate Diners Club provided credit cards', () => { test({ validator: 'isCreditCard', @@ -6178,7 +6169,6 @@ describe('Validators', () => { }); }); - it('should validate Mastercard provided credit cards', () => { test({ validator: 'isCreditCard', @@ -6214,7 +6204,6 @@ describe('Validators', () => { }); }); - it('should validate Union Pay provided credit cards', () => { test({ validator: 'isCreditCard', @@ -6249,7 +6238,6 @@ describe('Validators', () => { }); }); - it('should validate Visa provided credit cards', () => { test({ validator: 'isCreditCard', @@ -6285,7 +6273,6 @@ describe('Validators', () => { }); }); - it('should validate identity cards', () => { const fixtures = [ { @@ -7117,13 +7104,13 @@ describe('Validators', () => { 'TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=', 'Vml2YW11cyBmZXJtZW50dW0gc2VtcGVyIHBvcnRhLg==', 'U3VzcGVuZGlzc2UgbGVjdHVzIGxlbw==', - 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw' + - 'UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye' + - 'rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619' + - 'FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx' + - 'QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ' + - 'Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ' + - 'HQIDAQAB', + 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMPNS1Ufof9EW/M98FNw' + + 'UAKrwflsqVxaxQjBQnHQmiI7Vac40t8x7pIb8gLGV6wL7sBTJiPovJ0V7y7oc0Ye' + + 'rhKh0Rm4skP2z/jHwwZICgGzBvA0rH8xlhUiTvcwDCJ0kc+fh35hNt8srZQM4619' + + 'FTgB66Xmp4EtVyhpQV+t02g6NzK72oZI0vnAvqhpkxLeLiMCyrI416wHm5Tkukhx' + + 'QmcL2a6hNOyu0ixX/x2kSFXApEnVrJ+/IxGyfyw8kf4N2IZpW5nEP847lpfj0SZZ' + + 'Fwrd1mnfnDbYohX2zRptLy2ZUn06Qo9pkG5ntvFEPo9bfZeULtjYzIl6K8gJ2uGZ' + + 'HQIDAQAB', ], invalid: [ '12345', @@ -7921,6 +7908,47 @@ describe('Validators', () => { '0-987123456', ], }, + { + locale: 'en-BB', + valid: [ + '+12461234567', + '12461234567', + '+1 246 123 4567', + '+1-246-123-4567', + '+1-(246)-123-4567', + '01112461234567', + '011 1 246 123 4567', + ], + invalid: [ + '12345', + '+12461234567890', + '124612345678', + '+124633334445', + '', + '123', + '12461234567A', + '+1 246-12-34567', + '+1 (246 123 4567', + '+1) 246 123 4567', + '+1-800-123-4567', + '8001234567', + ], + }, + { + locale: 'en-BZ', + valid: [ + '+5012345678', + '5012345678', + ], + invalid: [ + '12345', + '+50112345', + '50123456', + '50123456789', + '50123456A', + '', + ], + }, { local: 'en-LS', valid: [ @@ -7983,6 +8011,203 @@ describe('Validators', () => { '', ], }, + { + locale: 'en-SR', + valid: [ + '+5971234567', + '5971234567', + '5979876543', + ], + invalid: [ + '12345', + '+59712345678', + '597123456', + '5971234A567', + '', + ], + }, + { + locale: 'is-IS', + valid: [ + '+3541234567', + '3541234567', + ], + invalid: [ + '12345', + '35412345', + '+35412345678', + '354A123456', + '', + ], + }, + { + locale: 'de-LI', + valid: [ + '+423 2345678', + '423 2345678', + '+423 6000001', + '423 6000001', + '+423 80012345', + '423 80012345', + '+423 9012345', + '423 9012345', + '+4232345678', + '4232345678', + ], + invalid: [ + '12345', + '42312345', + '+42312345678', + '423A123456', + '', + '423-2345678', + '+423-2345678', + ], + }, + { + locale: 'fr-MC', + valid: [ + '+37761234567', + '37761234567', + '3776123456', + '377 61234567', + '+377 61234567', + '377 6123456', + '+377 6123456', + '3778002343', + '+377 8002343', + '377 8002343', + ], + invalid: [ + '12345', + '377612345678', + '+3776123456A', + '377123456789', + '', + '37751234567', + '+37751234567', + '37712345678', + '+37712345678', + ], + }, + { + locale: 'ko-KP', + valid: [ + '+8501234567', + '8501234567', + '+85012345678', + '85087654321', + ], + invalid: [ + '12345', + '85012345', + '850123A567', + '', + ], + }, + { + locale: 'en-WS', + valid: [ + '+68520012', + '+685300123', + '+6854001234', + '+68550012345', + '+685700123', + '+6858001234', + '6858000123', + '68520012', + '685300123', + '6854001234', + '68550012345', + '685700123', + '6858001234', + '6858000123', + '685 20012', + '685 300123', + '685 4001234', + '685 50012345', + '685 700123', + '685 8001234', + '685 8000123', + '+685 20012', + '+685 300123', + '+685 4001234', + '+685 50012345', + '+685 700123', + '+685 8001234', + '+685 8000123', + ], + invalid: [ + '', + '12345', + '+68512345', + '+685100123', + '+6852001', + '+685200123456', + '+685600123', + '+685900123', + '6852001234', + '+685ABC123', + '+685800012', + 'abc', + '123', + '+', + '++', + '685 ', + ' 68520012', + '+685 ', + '68520012 ', + '6852001', + '+6852001234567', + '+685 200123456', + ], + }, + { + locale: 'to-TO', + valid: [ + '+676212345', + '676212345', + '+67621234', + '67621234', + '+676 212345', + '676 212345', + '+676 21234', + '676 21234', + ], + invalid: [ + '12345', + '6762123456', + '676 912345', + '+676 91234', + '676012345', + ' 67621234', + '67621234 ', + '676 212345', + '676-212345', + '+676212', + '+676abcdefg', + '676\t212345', + '', + ], + }, + { + locale: 'en-VU', + valid: [ + '+678512345', + '678512345', + '+678 512345', + '678 512345', + ], + invalid: [ + '12345', + '67851234', + '+6785123456', + '6785A12345', + '+6781 234567', + '+67821234567', + '', + ], + }, { locale: 'en-ZA', valid: [ @@ -9542,20 +9767,28 @@ describe('Validators', () => { { locale: 'ko-KR', valid: [ - '+82-010-1234-5678', '+82-10-1234-5678', - '82-010-1234-5678', '82-10-1234-5678', '+82 10 1234 5678', - '010-123-5678', '10-1234-5678', '+82 10 1234 5678', '011 1234 5678', '+820112345678', - '01012345678', '+82 016 1234 5678', '82 19 1234 5678', '+82 010 12345678', + '+82-010-1234-5678', + '02-9674-5122', + '02 9674 5122', + '82 02 9674 5122', + '+82 02 9674 5122', + '+82-02-9674-5122', + '0801235678', + '01182801235678', + '080-123-5678', + '011-82-80-123-5678', + '080 123 5678', + '011 82 80 123 5678', ], invalid: [ 'abcdefghi', @@ -9566,6 +9799,15 @@ describe('Validators', () => { '+011 7766 1234', '011_7766_1234', '+820 11 7766 1234', + '080 123 56789', + '011123456789', + '82-01-2345678', + '+82-011-234-5678', + '010-1234-56789', + '82 10-1234-567', + '+82 10 1234 567', + '011-010-123-5678', + '82-080-1234-5678', ], }, { @@ -10781,7 +11023,6 @@ describe('Validators', () => { args: [], }); - it('should error on invalid locale', () => { test({ validator: 'isMobilePhone', @@ -12270,7 +12511,6 @@ describe('Validators', () => { /* eslint-enable max-len */ }); - it('should validate magnetURI', () => { /* eslint-disable max-len */ test({ @@ -12304,7 +12544,6 @@ describe('Validators', () => { /* eslint-enable max-len */ }); - it('should validate LatLong', () => { test({ validator: 'isLatLong', @@ -13019,7 +13258,6 @@ describe('Validators', () => { }); }); - it('should validate ISO6346 shipping containerID', () => { test({ validator: 'isISO6346', @@ -13701,7 +13939,6 @@ describe('Validators', () => { }); }); - it('should validate slug', () => { test({ validator: 'isSlug',