format.test.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. import metadata from '../metadata.min.json' assert { type: 'json' }
  2. import formatNumber_ from './format.js'
  3. import parsePhoneNumber from './parsePhoneNumber.js'
  4. function formatNumber(...parameters) {
  5. let v2
  6. if (parameters.length < 1) {
  7. // `input` parameter.
  8. parameters.push(undefined)
  9. } else {
  10. // Convert string `input` to a `PhoneNumber` instance.
  11. if (typeof parameters[0] === 'string') {
  12. v2 = true
  13. parameters[0] = parsePhoneNumber(parameters[0], {
  14. ...parameters[2],
  15. extract: false
  16. }, metadata)
  17. }
  18. }
  19. if (parameters.length < 2) {
  20. // `format` parameter.
  21. parameters.push(undefined)
  22. }
  23. if (parameters.length < 3) {
  24. // `options` parameter.
  25. parameters.push(undefined)
  26. }
  27. // Set `v2` flag.
  28. parameters[2] = {
  29. v2,
  30. ...parameters[2]
  31. }
  32. // Add `metadata` parameter.
  33. parameters.push(metadata)
  34. // Call the function.
  35. return formatNumber_.apply(this, parameters)
  36. }
  37. describe('format', () => {
  38. it('should work with the first argument being a E.164 number', () => {
  39. formatNumber('+12133734253', 'NATIONAL').should.equal('(213) 373-4253')
  40. formatNumber('+12133734253', 'INTERNATIONAL').should.equal('+1 213 373 4253')
  41. // Invalid number.
  42. formatNumber('+12111111111', 'NATIONAL').should.equal('(211) 111-1111')
  43. // Formatting invalid E.164 numbers.
  44. formatNumber('+11111', 'INTERNATIONAL').should.equal('+1 1111')
  45. formatNumber('+11111', 'NATIONAL').should.equal('1111')
  46. })
  47. it('should work with the first object argument expanded', () => {
  48. formatNumber('2133734253', 'NATIONAL', { defaultCountry: 'US' }).should.equal('(213) 373-4253')
  49. formatNumber('2133734253', 'INTERNATIONAL', { defaultCountry: 'US' }).should.equal('+1 213 373 4253')
  50. })
  51. it('should format using formats with no leading digits (`format.leadingDigitsPatterns().length === 0`)', () => {
  52. formatNumber({ phone: '12345678901', countryCallingCode: 888 }, 'INTERNATIONAL').should.equal('+888 123 456 78901')
  53. })
  54. it('should sort out the arguments', () => {
  55. const options = {
  56. formatExtension: (number, extension) => `${number} доб. ${extension}`
  57. }
  58. formatNumber({
  59. phone : '8005553535',
  60. country : 'RU',
  61. ext : '123'
  62. },
  63. 'NATIONAL', options).should.equal('8 (800) 555-35-35 доб. 123')
  64. // Parse number from string.
  65. formatNumber('+78005553535', 'NATIONAL', options).should.equal('8 (800) 555-35-35')
  66. formatNumber('8005553535', 'NATIONAL', { ...options, defaultCountry: 'RU' }).should.equal('8 (800) 555-35-35')
  67. })
  68. it('should format with national prefix when specifically instructed', () => {
  69. // With national prefix.
  70. formatNumber('88005553535', 'NATIONAL', { defaultCountry: 'RU' }).should.equal('8 (800) 555-35-35')
  71. // Without national prefix via an explicitly set option.
  72. formatNumber('88005553535', 'NATIONAL', { nationalPrefix: false, defaultCountry: 'RU' }).should.equal('800 555-35-35')
  73. })
  74. it('should format valid phone numbers', () => {
  75. // Switzerland
  76. formatNumber({ country: 'CH', phone: '446681800' }, 'INTERNATIONAL').should.equal('+41 44 668 18 00')
  77. formatNumber({ country: 'CH', phone: '446681800' }, 'E.164').should.equal('+41446681800')
  78. formatNumber({ country: 'CH', phone: '446681800' }, 'RFC3966').should.equal('tel:+41446681800')
  79. formatNumber({ country: 'CH', phone: '446681800' }, 'NATIONAL').should.equal('044 668 18 00')
  80. // France
  81. formatNumber({ country: 'FR', phone: '169454850' }, 'NATIONAL').should.equal('01 69 45 48 50')
  82. // Kazakhstan
  83. formatNumber('+7 702 211 1111', 'NATIONAL').should.deep.equal('8 (702) 211 1111')
  84. })
  85. it('should format national numbers with national prefix even if it\'s optional', () => {
  86. // Russia
  87. formatNumber({ country: 'RU', phone: '9991234567' }, 'NATIONAL').should.equal('8 (999) 123-45-67')
  88. })
  89. it('should work in edge cases', () => {
  90. let thrower
  91. // // No phone number
  92. // formatNumber('', 'INTERNATIONAL', { defaultCountry: 'RU' }).should.equal('')
  93. // formatNumber('', 'NATIONAL', { defaultCountry: 'RU' }).should.equal('')
  94. formatNumber({ country: 'RU', phone: '' }, 'INTERNATIONAL').should.equal('+7')
  95. formatNumber({ country: 'RU', phone: '' }, 'NATIONAL').should.equal('')
  96. // No suitable format
  97. formatNumber('+121337342530', 'NATIONAL', { defaultCountry: 'US' }).should.equal('21337342530')
  98. // No suitable format (leading digits mismatch)
  99. formatNumber('28199999', 'NATIONAL', { defaultCountry: 'AD' }).should.equal('28199999')
  100. // // Numerical `value`
  101. // thrower = () => formatNumber(89150000000, 'NATIONAL', { defaultCountry: 'RU' })
  102. // thrower.should.throw('A phone number must either be a string or an object of shape { phone, [country] }.')
  103. // // No metadata for country
  104. // expect(() => formatNumber('+121337342530', 'NATIONAL', { defaultCountry: 'USA' })).to.throw('Unknown country')
  105. // expect(() => formatNumber('21337342530', 'NATIONAL', { defaultCountry: 'USA' })).to.throw('Unknown country')
  106. // No format type
  107. thrower = () => formatNumber('+123')
  108. thrower.should.throw('Unknown "format" argument')
  109. // Unknown format type
  110. thrower = () => formatNumber('123', 'Gay', { defaultCountry: 'US' })
  111. thrower.should.throw('Unknown "format" argument')
  112. // // No metadata
  113. // thrower = () => _formatNumber('123', 'E.164', { defaultCountry: 'RU' })
  114. // thrower.should.throw('`metadata`')
  115. // No formats
  116. formatNumber('012345', 'NATIONAL', { defaultCountry: 'AC' }).should.equal('012345')
  117. // No `fromCountry` for `IDD` format.
  118. expect(formatNumber('+78005553535', 'IDD')).to.be.undefined
  119. // `fromCountry` has no default IDD prefix.
  120. expect(formatNumber('+78005553535', 'IDD', { fromCountry: 'BO' })).to.be.undefined
  121. // No such country.
  122. expect(() => formatNumber({ phone: '123', country: 'USA' }, 'NATIONAL')).to.throw('Unknown country')
  123. })
  124. it('should format phone number extensions', () => {
  125. // National
  126. formatNumber({
  127. country: 'US',
  128. phone: '2133734253',
  129. ext: '123'
  130. },
  131. 'NATIONAL').should.equal('(213) 373-4253 ext. 123')
  132. // International
  133. formatNumber({
  134. country : 'US',
  135. phone : '2133734253',
  136. ext : '123'
  137. },
  138. 'INTERNATIONAL').should.equal('+1 213 373 4253 ext. 123')
  139. // International
  140. formatNumber({
  141. country : 'US',
  142. phone : '2133734253',
  143. ext : '123'
  144. },
  145. 'INTERNATIONAL').should.equal('+1 213 373 4253 ext. 123')
  146. // E.164
  147. formatNumber({
  148. country : 'US',
  149. phone : '2133734253',
  150. ext : '123'
  151. },
  152. 'E.164').should.equal('+12133734253')
  153. // RFC3966
  154. formatNumber({
  155. country : 'US',
  156. phone : '2133734253',
  157. ext : '123'
  158. },
  159. 'RFC3966').should.equal('tel:+12133734253;ext=123')
  160. // Custom ext prefix.
  161. formatNumber({
  162. country : 'GB',
  163. phone : '7912345678',
  164. ext : '123'
  165. },
  166. 'INTERNATIONAL').should.equal('+44 7912 345678 x123')
  167. })
  168. it('should work with Argentina numbers', () => {
  169. // The same mobile number is written differently
  170. // in different formats in Argentina:
  171. // `9` gets prepended in international format.
  172. formatNumber({ country: 'AR', phone: '3435551212' }, 'INTERNATIONAL')
  173. .should.equal('+54 3435 55 1212')
  174. formatNumber({ country: 'AR', phone: '3435551212' }, 'NATIONAL')
  175. .should.equal('03435 55-1212')
  176. })
  177. it('should work with Mexico numbers', () => {
  178. // Fixed line.
  179. formatNumber({ country: 'MX', phone: '4499780001' }, 'INTERNATIONAL')
  180. .should.equal('+52 449 978 0001')
  181. formatNumber({ country: 'MX', phone: '4499780001' }, 'NATIONAL')
  182. .should.equal('449 978 0001')
  183. // or '(449)978-0001'.
  184. // Mobile.
  185. // `1` is prepended before area code to mobile numbers in international format.
  186. formatNumber({ country: 'MX', phone: '3312345678' }, 'INTERNATIONAL')
  187. .should.equal('+52 33 1234 5678')
  188. formatNumber({ country: 'MX', phone: '3312345678' }, 'NATIONAL')
  189. .should.equal('33 1234 5678')
  190. // or '045 33 1234-5678'.
  191. })
  192. it('should format possible numbers', () => {
  193. formatNumber({ countryCallingCode: '7', phone: '1111111111' }, 'E.164')
  194. .should.equal('+71111111111')
  195. formatNumber({ countryCallingCode: '7', phone: '1111111111' }, 'NATIONAL')
  196. .should.equal('1111111111')
  197. formatNumber({ countryCallingCode: '7', phone: '1111111111' }, 'INTERNATIONAL')
  198. .should.equal('+7 1111111111')
  199. })
  200. it('should format IDD-prefixed number', () => {
  201. // No `fromCountry`.
  202. expect(formatNumber('+78005553535', 'IDD')).to.be.undefined
  203. // No default IDD prefix.
  204. expect(formatNumber('+78005553535', 'IDD', { fromCountry: 'BO' })).to.be.undefined
  205. // Same country calling code.
  206. formatNumber('+12133734253', 'IDD', { fromCountry: 'CA', humanReadable: true }).should.equal('1 (213) 373-4253')
  207. formatNumber('+78005553535', 'IDD', { fromCountry: 'KZ', humanReadable: true }).should.equal('8 (800) 555-35-35')
  208. // formatNumber('+78005553535', 'IDD', { fromCountry: 'US' }).should.equal('01178005553535')
  209. formatNumber('+78005553535', 'IDD', { fromCountry: 'US', humanReadable: true }).should.equal('011 7 800 555 35 35')
  210. })
  211. it('should format non-geographic numbering plan phone numbers', () => {
  212. // https://github.com/catamphetamine/libphonenumber-js/issues/323
  213. formatNumber('+870773111632', 'INTERNATIONAL').should.equal('+870 773 111 632')
  214. formatNumber('+870773111632', 'NATIONAL').should.equal('773 111 632')
  215. })
  216. it('should use the default IDD prefix when formatting a phone number', () => {
  217. // Testing preferred international prefixes with ~ are supported.
  218. // ("~" designates waiting on a line until proceeding with the input).
  219. formatNumber('+390236618300', 'IDD', { fromCountry: 'UZ' }).should.equal('8~10 39 02 3661 8300')
  220. })
  221. })