NumberFormat.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. describe("errors", () => {
  2. test("structurally invalid tag", () => {
  3. expect(() => {
  4. new Intl.NumberFormat("root");
  5. }).toThrowWithMessage(RangeError, "root is not a structurally valid language tag");
  6. expect(() => {
  7. new Intl.NumberFormat("en-");
  8. }).toThrowWithMessage(RangeError, "en- is not a structurally valid language tag");
  9. expect(() => {
  10. new Intl.NumberFormat("Latn");
  11. }).toThrowWithMessage(RangeError, "Latn is not a structurally valid language tag");
  12. expect(() => {
  13. new Intl.NumberFormat("en-u-aa-U-aa");
  14. }).toThrowWithMessage(RangeError, "en-u-aa-U-aa is not a structurally valid language tag");
  15. });
  16. test("options is an invalid type", () => {
  17. expect(() => {
  18. new Intl.NumberFormat("en", null);
  19. }).toThrowWithMessage(TypeError, "ToObject on null or undefined");
  20. });
  21. test("localeMatcher option is invalid ", () => {
  22. expect(() => {
  23. new Intl.NumberFormat("en", { localeMatcher: "hello!" });
  24. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option localeMatcher");
  25. });
  26. test("numberingSystem option is invalid ", () => {
  27. expect(() => {
  28. new Intl.NumberFormat("en", { numberingSystem: "hello!" });
  29. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option numberingSystem");
  30. });
  31. test("style option is invalid ", () => {
  32. expect(() => {
  33. new Intl.NumberFormat("en", { style: "hello!" });
  34. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option style");
  35. });
  36. test("currency option is undefined when required ", () => {
  37. expect(() => {
  38. new Intl.NumberFormat("en", { style: "currency" });
  39. }).toThrowWithMessage(
  40. TypeError,
  41. "Option currency must be defined when option style is currency"
  42. );
  43. });
  44. test("currency option is invalid ", () => {
  45. expect(() => {
  46. new Intl.NumberFormat("en", { currency: "hello!" });
  47. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option currency");
  48. });
  49. test("currencyDisplay option is invalid ", () => {
  50. expect(() => {
  51. new Intl.NumberFormat("en", { currencyDisplay: "hello!" });
  52. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option currencyDisplay");
  53. });
  54. test("currencySign option is invalid ", () => {
  55. expect(() => {
  56. new Intl.NumberFormat("en", { currencySign: "hello!" });
  57. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option currencySign");
  58. });
  59. test("unit option is undefined when required ", () => {
  60. expect(() => {
  61. new Intl.NumberFormat("en", { style: "unit" });
  62. }).toThrowWithMessage(TypeError, "Option unit must be defined when option style is unit");
  63. });
  64. test("unit option is invalid ", () => {
  65. expect(() => {
  66. new Intl.NumberFormat("en", { unit: "hello!" });
  67. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option unit");
  68. expect(() => {
  69. new Intl.NumberFormat("en", { unit: "acre-bit" });
  70. }).toThrowWithMessage(RangeError, "acre-bit is not a valid value for option unit");
  71. expect(() => {
  72. new Intl.NumberFormat("en", { unit: "acre-per-bit-per-byte" });
  73. }).toThrowWithMessage(
  74. RangeError,
  75. "acre-per-bit-per-byte is not a valid value for option unit"
  76. );
  77. });
  78. test("unitDisplay option is invalid ", () => {
  79. expect(() => {
  80. new Intl.NumberFormat("en", { unitDisplay: "hello!" });
  81. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option unitDisplay");
  82. });
  83. test("notation option is invalid ", () => {
  84. expect(() => {
  85. new Intl.NumberFormat("en", { notation: "hello!" });
  86. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option notation");
  87. });
  88. test("minimumIntegerDigits option is invalid ", () => {
  89. expect(() => {
  90. new Intl.NumberFormat("en", { minimumIntegerDigits: 1n });
  91. }).toThrowWithMessage(TypeError, "Cannot convert BigInt to number");
  92. expect(() => {
  93. new Intl.NumberFormat("en", { minimumIntegerDigits: "hello!" });
  94. }).toThrowWithMessage(RangeError, "Value NaN is NaN or is not between 1 and 21");
  95. expect(() => {
  96. new Intl.NumberFormat("en", { minimumIntegerDigits: 0 });
  97. }).toThrowWithMessage(RangeError, "Value 0 is NaN or is not between 1 and 21");
  98. expect(() => {
  99. new Intl.NumberFormat("en", { minimumIntegerDigits: 22 });
  100. }).toThrowWithMessage(RangeError, "Value 22 is NaN or is not between 1 and 21");
  101. });
  102. test("minimumFractionDigits option is invalid ", () => {
  103. expect(() => {
  104. new Intl.NumberFormat("en", { minimumFractionDigits: 1n });
  105. }).toThrowWithMessage(TypeError, "Cannot convert BigInt to number");
  106. expect(() => {
  107. new Intl.NumberFormat("en", { minimumFractionDigits: "hello!" });
  108. }).toThrowWithMessage(RangeError, "Value NaN is NaN or is not between 0 and 20");
  109. expect(() => {
  110. new Intl.NumberFormat("en", { minimumFractionDigits: -1 });
  111. }).toThrowWithMessage(RangeError, "Value -1 is NaN or is not between 0 and 20");
  112. expect(() => {
  113. new Intl.NumberFormat("en", { minimumFractionDigits: 21 });
  114. }).toThrowWithMessage(RangeError, "Value 21 is NaN or is not between 0 and 20");
  115. });
  116. test("maximumFractionDigits option is invalid ", () => {
  117. expect(() => {
  118. new Intl.NumberFormat("en", { maximumFractionDigits: 1n });
  119. }).toThrowWithMessage(TypeError, "Cannot convert BigInt to number");
  120. expect(() => {
  121. new Intl.NumberFormat("en", { maximumFractionDigits: "hello!" });
  122. }).toThrowWithMessage(RangeError, "Value NaN is NaN or is not between 0 and 20");
  123. expect(() => {
  124. new Intl.NumberFormat("en", { maximumFractionDigits: -1 });
  125. }).toThrowWithMessage(RangeError, "Value -1 is NaN or is not between 0 and 20");
  126. expect(() => {
  127. new Intl.NumberFormat("en", { maximumFractionDigits: 21 });
  128. }).toThrowWithMessage(RangeError, "Value 21 is NaN or is not between 0 and 20");
  129. expect(() => {
  130. new Intl.NumberFormat("en", { minimumFractionDigits: 10, maximumFractionDigits: 5 });
  131. }).toThrowWithMessage(RangeError, "Minimum value 10 is larger than maximum value 5");
  132. });
  133. test("minimumSignificantDigits option is invalid ", () => {
  134. expect(() => {
  135. new Intl.NumberFormat("en", { minimumSignificantDigits: 1n });
  136. }).toThrowWithMessage(TypeError, "Cannot convert BigInt to number");
  137. expect(() => {
  138. new Intl.NumberFormat("en", { minimumSignificantDigits: "hello!" });
  139. }).toThrowWithMessage(RangeError, "Value NaN is NaN or is not between 1 and 21");
  140. expect(() => {
  141. new Intl.NumberFormat("en", { minimumSignificantDigits: 0 });
  142. }).toThrowWithMessage(RangeError, "Value 0 is NaN or is not between 1 and 21");
  143. expect(() => {
  144. new Intl.NumberFormat("en", { minimumSignificantDigits: 22 });
  145. }).toThrowWithMessage(RangeError, "Value 22 is NaN or is not between 1 and 21");
  146. });
  147. test("maximumSignificantDigits option is invalid ", () => {
  148. expect(() => {
  149. new Intl.NumberFormat("en", { maximumSignificantDigits: 1n });
  150. }).toThrowWithMessage(TypeError, "Cannot convert BigInt to number");
  151. expect(() => {
  152. new Intl.NumberFormat("en", { maximumSignificantDigits: "hello!" });
  153. }).toThrowWithMessage(RangeError, "Value NaN is NaN or is not between 1 and 21");
  154. expect(() => {
  155. new Intl.NumberFormat("en", { maximumSignificantDigits: 0 });
  156. }).toThrowWithMessage(RangeError, "Value 0 is NaN or is not between 1 and 21");
  157. expect(() => {
  158. new Intl.NumberFormat("en", { maximumSignificantDigits: 22 });
  159. }).toThrowWithMessage(RangeError, "Value 22 is NaN or is not between 1 and 21");
  160. });
  161. test("compactDisplay option is invalid ", () => {
  162. expect(() => {
  163. new Intl.NumberFormat("en", { compactDisplay: "hello!" });
  164. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option compactDisplay");
  165. });
  166. test("signDisplay option is invalid ", () => {
  167. expect(() => {
  168. new Intl.NumberFormat("en", { signDisplay: "hello!" });
  169. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option signDisplay");
  170. });
  171. });
  172. describe("normal behavior", () => {
  173. test("length is 0", () => {
  174. expect(Intl.NumberFormat).toHaveLength(0);
  175. });
  176. test("all valid localeMatcher options", () => {
  177. ["lookup", "best fit"].forEach(localeMatcher => {
  178. expect(() => {
  179. new Intl.NumberFormat("en", { localeMatcher: localeMatcher });
  180. }).not.toThrow();
  181. });
  182. });
  183. test("valid numberingSystem options", () => {
  184. ["latn", "arab", "abc-def-ghi"].forEach(numberingSystem => {
  185. expect(() => {
  186. new Intl.NumberFormat("en", { numberingSystem: numberingSystem });
  187. }).not.toThrow();
  188. });
  189. });
  190. test("all valid style options", () => {
  191. ["decimal", "percent"].forEach(style => {
  192. expect(() => {
  193. new Intl.NumberFormat("en", { style: style });
  194. }).not.toThrow();
  195. });
  196. expect(() => {
  197. new Intl.NumberFormat("en", { style: "currency", currency: "USD" });
  198. }).not.toThrow();
  199. expect(() => {
  200. new Intl.NumberFormat("en", { style: "unit", unit: "degree" });
  201. }).not.toThrow();
  202. });
  203. test("valid currency options", () => {
  204. ["USD", "EUR", "XAG"].forEach(currency => {
  205. expect(() => {
  206. new Intl.NumberFormat("en", { currency: currency });
  207. }).not.toThrow();
  208. });
  209. });
  210. test("all valid currencyDisplay options", () => {
  211. ["code", "symbol", "narrowSymbol", "name"].forEach(currencyDisplay => {
  212. expect(() => {
  213. new Intl.NumberFormat("en", { currencyDisplay: currencyDisplay });
  214. }).not.toThrow();
  215. });
  216. });
  217. test("all valid currencySign options", () => {
  218. ["standard", "accounting"].forEach(currencySign => {
  219. expect(() => {
  220. new Intl.NumberFormat("en", { currencySign: currencySign });
  221. }).not.toThrow();
  222. });
  223. });
  224. test("valid unit options", () => {
  225. ["acre", "acre-per-bit"].forEach(unit => {
  226. expect(() => {
  227. new Intl.NumberFormat("en", { unit: unit });
  228. }).not.toThrow();
  229. });
  230. });
  231. test("all valid unitDisplay options", () => {
  232. ["short", "narrow", "long"].forEach(unitDisplay => {
  233. expect(() => {
  234. new Intl.NumberFormat("en", { unitDisplay: unitDisplay });
  235. }).not.toThrow();
  236. });
  237. });
  238. test("all valid notation options", () => {
  239. ["standard", "scientific", "engineering", "compact"].forEach(notation => {
  240. expect(() => {
  241. new Intl.NumberFormat("en", { notation: notation });
  242. }).not.toThrow();
  243. });
  244. });
  245. test("all valid minimumIntegerDigits options", () => {
  246. for (let i = 1; i <= 21; ++i) {
  247. expect(() => {
  248. new Intl.NumberFormat("en", { minimumIntegerDigits: i });
  249. }).not.toThrow();
  250. }
  251. });
  252. test("all valid minimumFractionDigits options", () => {
  253. for (let i = 0; i <= 20; ++i) {
  254. expect(() => {
  255. new Intl.NumberFormat("en", { minimumFractionDigits: i });
  256. }).not.toThrow();
  257. }
  258. });
  259. test("all valid maximumFractionDigits options", () => {
  260. for (let i = 0; i <= 20; ++i) {
  261. expect(() => {
  262. new Intl.NumberFormat("en", { maximumFractionDigits: i });
  263. }).not.toThrow();
  264. }
  265. });
  266. test("all valid minimumSignificantDigits options", () => {
  267. for (let i = 1; i <= 21; ++i) {
  268. expect(() => {
  269. new Intl.NumberFormat("en", { minimumSignificantDigits: i });
  270. }).not.toThrow();
  271. }
  272. });
  273. test("all valid maximumSignificantDigits options", () => {
  274. for (let i = 1; i <= 21; ++i) {
  275. expect(() => {
  276. new Intl.NumberFormat("en", { maximumSignificantDigits: i });
  277. }).not.toThrow();
  278. }
  279. });
  280. test("all valid compactDisplay options", () => {
  281. ["short", "long"].forEach(compactDisplay => {
  282. expect(() => {
  283. new Intl.NumberFormat("en", { compactDisplay: compactDisplay });
  284. }).not.toThrow();
  285. });
  286. });
  287. test("all valid signDisplay options", () => {
  288. ["auto", "never", "always", "exceptZero"].forEach(signDisplay => {
  289. expect(() => {
  290. new Intl.NumberFormat("en", { signDisplay: signDisplay });
  291. }).not.toThrow();
  292. });
  293. });
  294. });