@yext/phonenumber-util 0.1.0
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/.husky/pre-commit +6 -0
- package/.prettierrc +6 -0
- package/CODEOWNERS +2 -0
- package/LICENSE +28 -0
- package/README.md +153 -0
- package/THIRD-PARTY-NOTICES +5 -0
- package/eslint.config.mjs +7 -0
- package/package.json +40 -0
- package/src/__tests__/index.test.js +239 -0
- package/src/areaCodeList.js +417 -0
- package/src/index.d.ts +37 -0
- package/src/index.js +380 -0
- package/src/phoneFormats.js +212 -0
- package/vitest.config.js +6 -0
package/.prettierrc
ADDED
package/CODEOWNERS
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024, Hearsay Systems
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
Utility for extracting and validating phone numbers. Extracts an array of phone numbers from an inputted string, validates that these numbers appear genuine and provide data about those phone numbers.
|
|
2
|
+
|
|
3
|
+
### Scripts
|
|
4
|
+
|
|
5
|
+
#### Install dependencies
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm i
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
#### Formatting source code
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm run format
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
#### Linting
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm run lint
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
#### Testing
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm test
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
#### Code Coverage Report
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npx vitest run --coverage
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Warning
|
|
36
|
+
|
|
37
|
+
The returned object will include a `rawNumber` value. This value is the return of the exact value passed to the function. No sanitization occurs with this value. If you reference this number, ensure you sanitize it _BEFORE_ passing to this function.
|
|
38
|
+
|
|
39
|
+
### Usage
|
|
40
|
+
|
|
41
|
+
There is additional functionality exposed as `export`, but the primary expected use case is:
|
|
42
|
+
|
|
43
|
+
#### isValidPhoneNumber
|
|
44
|
+
|
|
45
|
+
Returns a boolean based on whether the passed number is presumed to be valid or invalid.
|
|
46
|
+
|
|
47
|
+
This checks for region code, number length and validity of region code and area code (where applicable).
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
import { isValidPhoneNumber } from 'phonenumber-util';
|
|
51
|
+
const validPhoneNumber = '3103496333';
|
|
52
|
+
isValidPhoneNumber(validPhoneNumber); // Returns `true` - "310" is an area code for California
|
|
53
|
+
|
|
54
|
+
const invalidPhoneNumber = '3113496333';
|
|
55
|
+
isValidPhoneNumber(invalidPhoneNumber); // Returns `false` - "311" is not a valid area code
|
|
56
|
+
|
|
57
|
+
const intlNumber = '+380 97 123 4567';
|
|
58
|
+
isValidPhoneNumber(intlNumber); // Returns `true` - "380" is the region code for Ukraine
|
|
59
|
+
|
|
60
|
+
const invalidIntlNumber = '+666 97 123 4567';
|
|
61
|
+
isValidPhoneNumber(invalidIntlNumber); // Returns `false` - "666" is not a valid region code
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
#### getPhoneParts
|
|
65
|
+
|
|
66
|
+
Return an object of relevant phone number parts and information.
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
import { getPhoneParts } from 'phonenumber-util';
|
|
70
|
+
const validPhoneNumber = '3496333';
|
|
71
|
+
getPhoneParts(validPhoneNumber); // Returns an object, assumed to be US / Canada, region code "1" but no area code can be reliably determined.
|
|
72
|
+
|
|
73
|
+
const validPhoneNumber = '"+923331234567"';
|
|
74
|
+
getPhoneParts(validPhoneNumber); // Returns an object, assumed to be Pakistan, region code "92".
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Example output for Pakistan ("+923331234567"):
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
{
|
|
81
|
+
areaCode: null,
|
|
82
|
+
e164: "+923331234567",
|
|
83
|
+
format: "+xx xxx xxx xxxx",
|
|
84
|
+
formattedNumber: "+92 333 123 4567",
|
|
85
|
+
href: "tel:+923331234567",
|
|
86
|
+
localNumber: "3331234567",
|
|
87
|
+
rawNumber: "+923331234567",
|
|
88
|
+
regionCode: "92"
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Example for US with 7 digits provided ("3496200") where no state can be determined. Note that e164 and formattedNumber also cannot be derived:
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
{
|
|
96
|
+
areaCode: null,
|
|
97
|
+
e164: null,
|
|
98
|
+
format: "(xxx) xxx-xxxx",
|
|
99
|
+
formattedNumber: null,
|
|
100
|
+
href: "tel:3496200",
|
|
101
|
+
localNumber: "3496200",
|
|
102
|
+
rawNumber: "349.6200",
|
|
103
|
+
regionCode: "1"
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Example for US with full area code provided ("310.349.9999"):
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
{
|
|
111
|
+
areaCode: "310",
|
|
112
|
+
e164: "+13103103499999",
|
|
113
|
+
format: "(xxx) xxx-xxxx",
|
|
114
|
+
formattedNumber: "(310) 349-9999",
|
|
115
|
+
href: "tel:+13103499999",
|
|
116
|
+
localNumber: "3103499999",
|
|
117
|
+
rawNumber: "310.349.9999",
|
|
118
|
+
regionCode: "1"
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
#### findNumbersInString
|
|
123
|
+
|
|
124
|
+
Accepts a full string of text and returns an array of phone numbers extracted from within that text.
|
|
125
|
+
|
|
126
|
+
The objects within this array will be identical to the object provided in the `getPhoneParts` above with the only exception being the addition of a `index` and `lastIndex` integer noting the start and end of the instance of that specific number within the provided string.
|
|
127
|
+
|
|
128
|
+
Example for US with full area code provided ("Hey there, my number is 310.349.9999. Please give me a call!"):
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
[
|
|
132
|
+
{
|
|
133
|
+
index: 24,
|
|
134
|
+
lastIndex: 36,
|
|
135
|
+
areaCode: '310',
|
|
136
|
+
e164: '+13103103499999',
|
|
137
|
+
format: '(xxx) xxx-xxxx',
|
|
138
|
+
formattedNumber: '(310) 349-9999',
|
|
139
|
+
href: 'tel:+13103499999',
|
|
140
|
+
localNumber: '3103499999',
|
|
141
|
+
rawNumber: '310.349.9999',
|
|
142
|
+
regionCode: '1',
|
|
143
|
+
},
|
|
144
|
+
];
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Numbers that lack area codes will NOT be returned via `findNumbersInString` since they cannot be reliably validated.
|
|
148
|
+
|
|
149
|
+
Example for US with no area code provided ("Hey there, my number is 349.9999. Please give me a call!"):
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
[];
|
|
153
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yext/phonenumber-util",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"author": "bajohnson@hearsaycorp.com",
|
|
5
|
+
"license": "BSD-3-Clause",
|
|
6
|
+
"description": "Utility for extracting and validating phone numbers",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "src/index.js",
|
|
9
|
+
"types": "src/index.d.ts",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/hearsaycorp/phonenumber-util.git"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"lint": "eslint **/*.js **/__tests__/*.js",
|
|
16
|
+
"format": "prettier --write **/*.js **/__tests__/*.js",
|
|
17
|
+
"test": "vitest",
|
|
18
|
+
"build": "node -e \"console.log('No build script for vanilla JS')\"",
|
|
19
|
+
"prepare": "husky"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@eslint/js": "^9.7.0",
|
|
23
|
+
"@vitest/coverage-v8": "^2.1.1",
|
|
24
|
+
"eslint": "^9.7.0",
|
|
25
|
+
"globals": "^15.8.0",
|
|
26
|
+
"husky": "^9.1.5",
|
|
27
|
+
"lint-staged": "^15.2.10",
|
|
28
|
+
"prettier": "^3.3.3",
|
|
29
|
+
"vitest": "^2.1.1"
|
|
30
|
+
},
|
|
31
|
+
"eslintConfig": {},
|
|
32
|
+
"lint-staged": {
|
|
33
|
+
"**/*.js": [
|
|
34
|
+
"npm run lint"
|
|
35
|
+
],
|
|
36
|
+
"**/*.{js,json,md}": [
|
|
37
|
+
"npm run format"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatPhoneNumberForE164,
|
|
3
|
+
formatPhoneNumberLink,
|
|
4
|
+
isValidPhoneNumber,
|
|
5
|
+
getPhoneParts,
|
|
6
|
+
sanitizeRawNumber,
|
|
7
|
+
findNumbersInString,
|
|
8
|
+
findPhoneFormat,
|
|
9
|
+
formatPhoneNumber,
|
|
10
|
+
} from '../index.js';
|
|
11
|
+
import { describe, it, expect } from 'vitest';
|
|
12
|
+
|
|
13
|
+
const testNumbers = {
|
|
14
|
+
3103491234: '1',
|
|
15
|
+
18333671100: '1',
|
|
16
|
+
'+86 755 8357 7777': '86',
|
|
17
|
+
'+91 987 654 3210': '91',
|
|
18
|
+
'+62 812 345 6789': '62',
|
|
19
|
+
'+1 212 456 7890': '1',
|
|
20
|
+
'+55 11 98765 4321': '55',
|
|
21
|
+
'+7 912 345 6789': '7',
|
|
22
|
+
'+92 333 123 4567': '92',
|
|
23
|
+
'+234 802 345 6789': '234',
|
|
24
|
+
'+880 1712 345 678': '880',
|
|
25
|
+
'+81 90 1234 5678': '81',
|
|
26
|
+
'+49 171 234 5678': '49',
|
|
27
|
+
'+49 30 97 88 88 88': '49',
|
|
28
|
+
'+63 917 123 4567': '63',
|
|
29
|
+
'+52 55 1234 5678': '52',
|
|
30
|
+
'+98 912 345 6789': '98',
|
|
31
|
+
'+20 10 123 4567': '20',
|
|
32
|
+
'+39 333 123 4567': '39',
|
|
33
|
+
'+44 791 112 3456': '44',
|
|
34
|
+
'+84 283 822 5555': '84',
|
|
35
|
+
'+90 532 123 4567': '90',
|
|
36
|
+
'+1 (310) 349-6543': '1',
|
|
37
|
+
'+33 7 56 78 90 12': '33',
|
|
38
|
+
'+66 92 345 6789': '66',
|
|
39
|
+
'+27 82 345 6789': '27',
|
|
40
|
+
'+57 321 123 45 67': '57',
|
|
41
|
+
'+380 97 123 4567': '380',
|
|
42
|
+
'+54 911 123 4567': '54',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
describe('Region code mapping', () => {
|
|
46
|
+
it('should find the correct region based on inputted number', () => {
|
|
47
|
+
Object.keys(testNumbers).map(function (phoneNumber) {
|
|
48
|
+
const phoneParts = getPhoneParts(phoneNumber);
|
|
49
|
+
|
|
50
|
+
expect(phoneParts.regionCode).toBe(testNumbers[phoneNumber]);
|
|
51
|
+
expect(phoneParts.formattedNumber.indexOf('x')).toBe(-1);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('handles bad data', () => {
|
|
56
|
+
expect(getPhoneParts().rawNumber).toBe(undefined);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('handles a number that has an invalid area code', () => {
|
|
60
|
+
expect(getPhoneParts('+1 420 222 3333').formattedNumber).toBeNull();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('handles a number is definitely not a phone number', () => {
|
|
64
|
+
expect(getPhoneParts('7/23/2025').formattedNumber).toBeNull();
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('Sanitizing user inputted phone number values', () => {
|
|
69
|
+
it('should return safe strings', () => {
|
|
70
|
+
// These numbers are terribly malformed. We try and reasonably extract values, but safety of the inputs is the priority.
|
|
71
|
+
expect(sanitizeRawNumber("+1 <a>(3\\1%3C0) 3&49-'65`43")).toBe(
|
|
72
|
+
'+131303496543',
|
|
73
|
+
);
|
|
74
|
+
expect(sanitizeRawNumber("+1; (3<>1&0) 3`49\\-65'43")).toBe('+13103496543');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('Extracting numbers from a larger string of text', () => {
|
|
79
|
+
it('should find the correct number of phone numbers present in a large string', () => {
|
|
80
|
+
let rawString = '';
|
|
81
|
+
// First, build a string based on the names and values in testNumbers object
|
|
82
|
+
Object.keys(testNumbers).map(function (phoneNumber) {
|
|
83
|
+
rawString =
|
|
84
|
+
rawString +
|
|
85
|
+
' This: ' +
|
|
86
|
+
phoneNumber +
|
|
87
|
+
' is a phone number for ' +
|
|
88
|
+
testNumbers[phoneNumber] +
|
|
89
|
+
'\n';
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const output = findNumbersInString(rawString);
|
|
93
|
+
expect(output.length).toBe(Object.keys(testNumbers).length);
|
|
94
|
+
|
|
95
|
+
// Make sure each number given resolves to a region. The lookup table will
|
|
96
|
+
// have undefined for any number that doesn't exactly match.
|
|
97
|
+
output.map(function (number) {
|
|
98
|
+
expect(testNumbers[number.rawNumber]).toBeTruthy();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should ingore numbers of the correct local length but lack area code', () => {
|
|
103
|
+
expect(findNumbersInString('Meet me on 9/14/2024 over here').length).toBe(
|
|
104
|
+
0,
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe('Phone number formatting', () => {
|
|
110
|
+
it('should return undefined for a bad number', () => {
|
|
111
|
+
expect(getPhoneParts('4444444444').formattedNumber).toBe(null);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should return correct values for a good number', () => {
|
|
115
|
+
// Prevent malicious chars from being injected.
|
|
116
|
+
expect(getPhoneParts("+1 <a>(3\\1%3C0) 3&49-'65`43").e164).toBe(null);
|
|
117
|
+
expect(getPhoneParts("+1; (3<>1&0) 3`49\\-65'43").e164).toBe(
|
|
118
|
+
'+13103496543',
|
|
119
|
+
);
|
|
120
|
+
// US
|
|
121
|
+
expect(getPhoneParts('+1 (310) 349-6543').e164).toBe('+13103496543');
|
|
122
|
+
expect(getPhoneParts('+1 (310) 349-6543').formattedNumber).toBe(
|
|
123
|
+
'(310) 349-6543',
|
|
124
|
+
);
|
|
125
|
+
// US with a non-existent area code
|
|
126
|
+
expect(getPhoneParts('+1 (420) 349-6543').e164).toBeNull();
|
|
127
|
+
expect(getPhoneParts('+1 (420) 349-6543').formattedNumber).toBeNull();
|
|
128
|
+
// Intl number (France)
|
|
129
|
+
expect(getPhoneParts('+33 7 56 78 90 12').e164).toBe('+33756789012');
|
|
130
|
+
expect(getPhoneParts('+33 7 56 78 90 12').formattedNumber).toBe(
|
|
131
|
+
'+33 7 56 78 90 12',
|
|
132
|
+
);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
describe('Creation of e164 numbers', () => {
|
|
137
|
+
it('should create a valid e164 number for numbers that have that info. Should return null for local numbers that exclude country code.', () => {
|
|
138
|
+
const testNumbers = {
|
|
139
|
+
usLocal: { regionCode: '1', localNumber: '3496200' },
|
|
140
|
+
usAreaCode: { regionCode: '1', areaCode: '310', localNumber: '3496200' },
|
|
141
|
+
intl: { regionCode: '49', localNumber: '1712345678' },
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// US numbers without area codes don't offer enough info to provide a
|
|
145
|
+
// valid e164 number.
|
|
146
|
+
expect(formatPhoneNumberForE164(testNumbers.usLocal)).toBe(null);
|
|
147
|
+
expect(formatPhoneNumberForE164(testNumbers.usAreaCode)).toBe(
|
|
148
|
+
'+13103496200',
|
|
149
|
+
);
|
|
150
|
+
expect(formatPhoneNumberForE164(testNumbers.intl)).toBe('+491712345678');
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe('Creation of phone links for href', () => {
|
|
155
|
+
it('should create a valid href value for use in anchor tags', () => {
|
|
156
|
+
const testNumbers = {
|
|
157
|
+
nullCase: {
|
|
158
|
+
regionCode: null,
|
|
159
|
+
localNumber: null,
|
|
160
|
+
rawNumber: null,
|
|
161
|
+
},
|
|
162
|
+
usLocal: {
|
|
163
|
+
regionCode: '1',
|
|
164
|
+
localNumber: '3496200',
|
|
165
|
+
rawNumber: '3496200',
|
|
166
|
+
},
|
|
167
|
+
usAreaCode: {
|
|
168
|
+
regionCode: '1',
|
|
169
|
+
areaCode: '310',
|
|
170
|
+
localNumber: '3496200',
|
|
171
|
+
rawNumber: '(310) 349-6200',
|
|
172
|
+
},
|
|
173
|
+
intl: {
|
|
174
|
+
regionCode: '49',
|
|
175
|
+
localNumber: '1712345678',
|
|
176
|
+
rawNumber: '+49 171 234 5678',
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
expect(formatPhoneNumberLink(testNumbers.nullCase)).toBe(null);
|
|
181
|
+
expect(formatPhoneNumberLink(testNumbers.usLocal)).toBe('tel:3496200');
|
|
182
|
+
expect(formatPhoneNumberLink(testNumbers.usAreaCode)).toBe(
|
|
183
|
+
'tel:+13103496200',
|
|
184
|
+
);
|
|
185
|
+
expect(formatPhoneNumberLink(testNumbers.intl)).toBe('tel:+491712345678');
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe('Phone number validation', () => {
|
|
190
|
+
it('should determine whether a phone number is presumed valid or not', () => {
|
|
191
|
+
expect(isValidPhoneNumber('13103496200')).toBe(true);
|
|
192
|
+
expect(isValidPhoneNumber('3103496200')).toBe(true);
|
|
193
|
+
expect(isValidPhoneNumber('+234 345 6789')).toBe(true);
|
|
194
|
+
expect(isValidPhoneNumber('349-6200')).toBe(false);
|
|
195
|
+
expect(isValidPhoneNumber('7/23/2025')).toBe(false);
|
|
196
|
+
expect(isValidPhoneNumber('7.23.2025')).toBe(false);
|
|
197
|
+
expect(isValidPhoneNumber('7-23-2025')).toBe(false);
|
|
198
|
+
expect(isValidPhoneNumber('$5055')).toBe(false);
|
|
199
|
+
expect(isValidPhoneNumber('310-496-32313')).toBe(false);
|
|
200
|
+
expect(isValidPhoneNumber('5553496200')).toBe(false);
|
|
201
|
+
expect(isValidPhoneNumber('4444444444')).toBe(false);
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
describe('Phone number pretty formatting', () => {
|
|
206
|
+
it('should create a pretty phone number for different regions', () => {
|
|
207
|
+
const testNumbers = {
|
|
208
|
+
nullCase: {
|
|
209
|
+
e164: null,
|
|
210
|
+
format: findPhoneFormat({}),
|
|
211
|
+
},
|
|
212
|
+
us: {
|
|
213
|
+
e164: '13103496200',
|
|
214
|
+
regionCode: '1',
|
|
215
|
+
format: findPhoneFormat({ regionCode: '1', e164: '13103496200' }),
|
|
216
|
+
},
|
|
217
|
+
colombia: {
|
|
218
|
+
e164: '+573211234567',
|
|
219
|
+
regionCode: '57',
|
|
220
|
+
format: findPhoneFormat({ regionCode: '57', e164: '+573211234567' }),
|
|
221
|
+
},
|
|
222
|
+
germany: {
|
|
223
|
+
e164: '+49 170 87654321',
|
|
224
|
+
regionCode: '49',
|
|
225
|
+
format: findPhoneFormat({ regionCode: '49', e164: '+4917087654321' }),
|
|
226
|
+
},
|
|
227
|
+
germanyAlt: {
|
|
228
|
+
e164: '+49 170 8765432',
|
|
229
|
+
regionCode: '49',
|
|
230
|
+
format: findPhoneFormat({ regionCode: '49', e164: '+491708765432' }),
|
|
231
|
+
},
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
expect(formatPhoneNumber(testNumbers.nullCase)).toBe(null);
|
|
235
|
+
expect(formatPhoneNumber(testNumbers.us)).toBe('(310) 349-6200');
|
|
236
|
+
expect(formatPhoneNumber(testNumbers.colombia)).toBe('+57 321 123 4567');
|
|
237
|
+
expect(formatPhoneNumber(testNumbers.germanyAlt)).toBe('+49 17 08765432');
|
|
238
|
+
});
|
|
239
|
+
});
|