NumberFormat.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
  6. function format() {
  7. let locale = "en-US", options, n;
  8. assert.isTrue(arguments.length > 0);
  9. if (typeof arguments[0] === "number") {
  10. [n] = arguments;
  11. } else if (typeof arguments[0] === "object" && !(arguments[0] instanceof Array)) {
  12. [options, n] = arguments;
  13. } else {
  14. [locale, options, n] = arguments;
  15. }
  16. const format = new Intl.NumberFormat(locale, options).format(n);
  17. const localeString = n.toLocaleString(locale, options);
  18. assert.isTrue(format === localeString, `[locale = ${JSON.stringify(locale)}, options = ${JSON.stringify(options)}] new Intl.NumberFormat().format(${n}) -> ${format} !== ${n}.toLocaleString() -> ${localeString}`);
  19. return format;
  20. }
  21. const tests = [
  22. {
  23. name: "Decimal style default options",
  24. body: function () {
  25. assert.areEqual("5", format(5));
  26. assert.areEqual("5,000", format(5000));
  27. assert.areEqual("50.474", format(50.474));
  28. }
  29. },
  30. {
  31. name: "Min/max fractional digits",
  32. body: function () {
  33. // min
  34. assert.areEqual("5.00", format({ minimumFractionDigits: 2 }, 5));
  35. assert.areEqual("5.0", format({ minimumFractionDigits: 1 }, 5));
  36. // min and max
  37. assert.areEqual("5.00", format({ minimumFractionDigits: 2, maximumFractionDigits: 2 }, 5));
  38. assert.areEqual("5.0", format({ minimumFractionDigits: 1, maximumFractionDigits: 2 }, 5));
  39. // max
  40. assert.areEqual("5.44", format({ maximumFractionDigits: 2 }, 5.444));
  41. assert.areEqual("5.444", format({ maximumFractionDigits: 4 }, 5.444));
  42. assert.areEqual("5.45", format({ maximumFractionDigits: 2 }, 5.445));
  43. assert.areEqual("5.445", format({ maximumFractionDigits: 4 }, 5.445));
  44. assert.areEqual("5.55", format({ maximumFractionDigits: 2 }, 5.554));
  45. assert.areEqual("5.554", format({ maximumFractionDigits: 4 }, 5.554));
  46. assert.areEqual("5", format({ maximumFractionDigits: 0 }, 5.45));
  47. assert.areEqual("6", format({ maximumFractionDigits: 0 }, 5.5));
  48. }
  49. },
  50. {
  51. name: "Min integer digits",
  52. body: function () {
  53. assert.areEqual("5", format({ minimumIntegerDigits: 1 }, 5));
  54. assert.areEqual("05", format({ minimumIntegerDigits: 2 }, 5));
  55. assert.areEqual("0,000,000,005", format({ minimumIntegerDigits: 10 }, 5));
  56. assert.areEqual("500", format({ minimumIntegerDigits: 1 }, 500));
  57. assert.areEqual("0,000,000,500", format({ minimumIntegerDigits: 10 }, 500));
  58. }
  59. },
  60. {
  61. name: "Min/max significant digits",
  62. body: function () {
  63. // min
  64. assert.areEqual("5.0", format({ minimumSignificantDigits: 2 }, 5));
  65. assert.areEqual("500", format({ minimumSignificantDigits: 2 }, 500));
  66. assert.areEqual("500.0", format({ minimumSignificantDigits: 4 }, 500));
  67. // min and max
  68. assert.areEqual("5.0", format({ minimumSignificantDigits: 2, maximumSignificantDigits: 2 }, 5));
  69. assert.areEqual("5", format({ minimumSignificantDigits: 1, maximumSignificantDigits: 2 }, 5));
  70. // max
  71. assert.areEqual("5.44", format({ maximumSignificantDigits: 3 }, 5.444));
  72. assert.areEqual("5.444", format({ maximumSignificantDigits: 4 }, 5.4444));
  73. assert.areEqual("5.45", format({ maximumSignificantDigits: 3 }, 5.445));
  74. assert.areEqual("5.445", format({ maximumSignificantDigits: 4 }, 5.4445));
  75. assert.areEqual("5.55", format({ maximumSignificantDigits: 3 }, 5.554));
  76. }
  77. },
  78. {
  79. name: "Grouping separator",
  80. body: function () {
  81. assert.areEqual("50,000", format({ useGrouping: true }, 50000));
  82. assert.areEqual("50000", format({ useGrouping: false }, 50000));
  83. assert.areEqual("0000000005", format({ minimumIntegerDigits: 10, useGrouping: false }, 5));
  84. assert.areEqual("0000005000", format({ minimumIntegerDigits: 10, useGrouping: false }, 5000));
  85. }
  86. },
  87. {
  88. name: "Default style option combinations",
  89. body: function () {
  90. assert.areEqual("123", format({ minimumSignificantDigits: 3, maximumSignificantDigits: 3, minimumIntegerDigits: 5, minimumFractionDigits: 5, maximumFractionDigits: 5 }, 123.1));
  91. assert.areEqual("00,123.10000", format({ minimumIntegerDigits: 5, minimumFractionDigits: 5, maximumFractionDigits: 5 }, 123.1))
  92. }
  93. },
  94. {
  95. name: "Currency style",
  96. body: function () {
  97. function formatCurrency() {
  98. let locale = "en-US", currency = "USD", options, n;
  99. assert.isTrue(arguments.length > 0);
  100. if (typeof arguments[0] === "number") {
  101. [n] = arguments;
  102. } else if (typeof arguments[0] === "object") {
  103. [options, n] = arguments;
  104. } else if (arguments.length === 3) {
  105. [currency, options, n] = arguments;
  106. } else {
  107. [locale, currency, options, n] = arguments;
  108. }
  109. options = options || {};
  110. options.style = "currency",
  111. options.currency = currency;
  112. return format(locale, options, n)
  113. }
  114. assert.areEqual("$1.00", formatCurrency(1));
  115. assert.areEqual("$1.50", formatCurrency(1.50));
  116. assert.areEqual("$1.50", formatCurrency(1.504));
  117. assert.areEqual("$1.51", formatCurrency(1.505));
  118. assert.matches(/USD[\x20\u00a0]?1.00/, formatCurrency({ currencyDisplay: "code" }, 1), "Currency display: code");
  119. assert.matches(/USD[\x20\u00a0]?1.50/, formatCurrency({ currencyDisplay: "code" }, 1.504), "Currency display: code");
  120. assert.matches(/USD[\x20\u00a0]?1.51/, formatCurrency({ currencyDisplay: "code" }, 1.505), "Currency display: code");
  121. assert.areEqual("$1.00", formatCurrency({ currencyDisplay: "symbol" }, 1), "Currency display: symbol");
  122. assert.areEqual("$1.50", formatCurrency({ currencyDisplay: "symbol" }, 1.504), "Currency display: symbol");
  123. assert.areEqual("$1.51", formatCurrency({ currencyDisplay: "symbol" }, 1.505), "Currency display: symbol");
  124. // ICU has a proper "name" currency display, while WinGlob falls back to "code"
  125. assert.matches(/(?:USD[\x20\u00a0]?1.00|1.00 US dollars)/, formatCurrency({ currencyDisplay: "name" }, 1), "Currency display: name");
  126. assert.matches(/(?:USD[\x20\u00a0]?1.50|1.50 US dollars)/, formatCurrency({ currencyDisplay: "name" }, 1.504), "Currency display: name");
  127. assert.matches(/(?:USD[\x20\u00a0]?1.51|1.51 US dollars)/, formatCurrency({ currencyDisplay: "name" }, 1.505), "Currency display: name");
  128. }
  129. },
  130. {
  131. name: "Percent style",
  132. body: function () {
  133. assert.matches(/100[\x20\u00a0]?%/, format({ style: "percent" }, 1));
  134. assert.matches(/1[\x20\u00a0]?%/, format({ style: "percent" }, 0.01));
  135. assert.matches(/10,000[\x20\u00a0]?%/,format({ style: "percent" }, 100));
  136. }
  137. }
  138. ];
  139. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });