| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
- let suppressFormatEqualityCheck = false;
- function format() {
- let locale = "en-US", options, n;
- assert.isTrue(arguments.length > 0);
- if (typeof arguments[0] === "number") {
- [n] = arguments;
- } else if (typeof arguments[0] === "object" && !(arguments[0] instanceof Array)) {
- [options, n] = arguments;
- } else {
- [locale, options, n] = arguments;
- }
- const nf = new Intl.NumberFormat(locale, options);
- const format = nf.format(n);
- const localeString = n.toLocaleString(locale, options);
- assert.isTrue(format === localeString, `[locale = ${JSON.stringify(locale)}, options = ${JSON.stringify(options)}] format does not match toLocaleString`);
- if (WScript.Platform.INTL_LIBRARY === "icu" && !suppressFormatEqualityCheck) {
- assert.isTrue(format === nf.formatToParts(n).map((part) => part.value).join(""), `[locale = ${JSON.stringify(locale)}, options = ${JSON.stringify(options)}] format does not match formatToParts`);
- }
- return format;
- }
- const tests = [
- {
- name: "Decimal style default options",
- body: function () {
- assert.areEqual("5", format(5));
- assert.areEqual("5,000", format(5000));
- assert.areEqual("50.474", format(50.474));
- }
- },
- {
- name: "Min/max fractional digits",
- body: function () {
- // min
- assert.areEqual("5.00", format({ minimumFractionDigits: 2 }, 5));
- assert.areEqual("5.0", format({ minimumFractionDigits: 1 }, 5));
- // min and max
- assert.areEqual("5.00", format({ minimumFractionDigits: 2, maximumFractionDigits: 2 }, 5));
- assert.areEqual("5.0", format({ minimumFractionDigits: 1, maximumFractionDigits: 2 }, 5));
- // max
- assert.areEqual("5.44", format({ maximumFractionDigits: 2 }, 5.444));
- assert.areEqual("5.444", format({ maximumFractionDigits: 4 }, 5.444));
- assert.areEqual("5.45", format({ maximumFractionDigits: 2 }, 5.445));
- assert.areEqual("5.445", format({ maximumFractionDigits: 4 }, 5.445));
- assert.areEqual("5.55", format({ maximumFractionDigits: 2 }, 5.554));
- assert.areEqual("5.554", format({ maximumFractionDigits: 4 }, 5.554));
- assert.areEqual("5", format({ maximumFractionDigits: 0 }, 5.45));
- assert.areEqual("6", format({ maximumFractionDigits: 0 }, 5.5));
- }
- },
- {
- name: "Min integer digits",
- body: function () {
- assert.areEqual("5", format({ minimumIntegerDigits: 1 }, 5));
- assert.areEqual("05", format({ minimumIntegerDigits: 2 }, 5));
- assert.areEqual("0,000,000,005", format({ minimumIntegerDigits: 10 }, 5));
- assert.areEqual("500", format({ minimumIntegerDigits: 1 }, 500));
- assert.areEqual("0,000,000,500", format({ minimumIntegerDigits: 10 }, 500));
- }
- },
- {
- name: "Min/max significant digits",
- body: function () {
- // min
- assert.areEqual("5.0", format({ minimumSignificantDigits: 2 }, 5));
- assert.areEqual("500", format({ minimumSignificantDigits: 2 }, 500));
- assert.areEqual("500.0", format({ minimumSignificantDigits: 4 }, 500));
- // min and max
- assert.areEqual("5.0", format({ minimumSignificantDigits: 2, maximumSignificantDigits: 2 }, 5));
- assert.areEqual("5", format({ minimumSignificantDigits: 1, maximumSignificantDigits: 2 }, 5));
- // max
- assert.areEqual("5.44", format({ maximumSignificantDigits: 3 }, 5.444));
- assert.areEqual("5.444", format({ maximumSignificantDigits: 4 }, 5.4444));
- assert.areEqual("5.45", format({ maximumSignificantDigits: 3 }, 5.445));
- assert.areEqual("5.445", format({ maximumSignificantDigits: 4 }, 5.4445));
- assert.areEqual("5.55", format({ maximumSignificantDigits: 3 }, 5.554));
- }
- },
- {
- name: "Grouping separator",
- body: function () {
- assert.areEqual("50,000", format({ useGrouping: true }, 50000));
- assert.areEqual("50000", format({ useGrouping: false }, 50000));
- assert.areEqual("0000000005", format({ minimumIntegerDigits: 10, useGrouping: false }, 5));
- assert.areEqual("0000005000", format({ minimumIntegerDigits: 10, useGrouping: false }, 5000));
- }
- },
- {
- name: "Default style option combinations",
- body: function () {
- assert.areEqual("123", format({ minimumSignificantDigits: 3, maximumSignificantDigits: 3, minimumIntegerDigits: 5, minimumFractionDigits: 5, maximumFractionDigits: 5 }, 123.1));
- assert.areEqual("00,123.10000", format({ minimumIntegerDigits: 5, minimumFractionDigits: 5, maximumFractionDigits: 5 }, 123.1))
- }
- },
- {
- name: "Currency style",
- body: function () {
- function formatCurrency() {
- let locale = "en-US", currency = "USD", options, n;
- assert.isTrue(arguments.length > 0);
- if (typeof arguments[0] === "number") {
- [n] = arguments;
- } else if (typeof arguments[0] === "object") {
- [options, n] = arguments;
- } else if (arguments.length === 3) {
- [currency, options, n] = arguments;
- } else {
- [locale, currency, options, n] = arguments;
- }
- options = options || {};
- options.style = "currency",
- options.currency = currency;
- return format(locale, options, n)
- }
- assert.areEqual("$1.00", formatCurrency(1));
- assert.areEqual("$1.50", formatCurrency(1.50));
- assert.areEqual("$1.50", formatCurrency(1.504));
- assert.areEqual("$1.51", formatCurrency(1.505));
- assert.matches(/USD[\x20\u00a0]?1.00/, formatCurrency({ currencyDisplay: "code" }, 1), "Currency display: code");
- assert.matches(/USD[\x20\u00a0]?1.50/, formatCurrency({ currencyDisplay: "code" }, 1.504), "Currency display: code");
- assert.matches(/USD[\x20\u00a0]?1.51/, formatCurrency({ currencyDisplay: "code" }, 1.505), "Currency display: code");
- assert.areEqual("$1.00", formatCurrency({ currencyDisplay: "symbol" }, 1), "Currency display: symbol");
- assert.areEqual("$1.50", formatCurrency({ currencyDisplay: "symbol" }, 1.504), "Currency display: symbol");
- assert.areEqual("$1.51", formatCurrency({ currencyDisplay: "symbol" }, 1.505), "Currency display: symbol");
- // ICU has a proper "name" currency display, while WinGlob falls back to "code"
- if (WScript.Platform.ICU_VERSION === 62) {
- // In ICU 62, there is a mismatch between "1.00 US dollar" and "1.00 US dollars"
- suppressFormatEqualityCheck = true;
- }
- assert.matches(/(?:USD[\x20\u00a0]?1.00|1.00 US dollars)/, formatCurrency({ currencyDisplay: "name" }, 1), "Currency display: name");
- suppressFormatEqualityCheck = false;
- assert.matches(/(?:USD[\x20\u00a0]?1.50|1.50 US dollars)/, formatCurrency({ currencyDisplay: "name" }, 1.504), "Currency display: name");
- assert.matches(/(?:USD[\x20\u00a0]?1.51|1.51 US dollars)/, formatCurrency({ currencyDisplay: "name" }, 1.505), "Currency display: name");
- }
- },
- {
- name: "Percent style",
- body: function () {
- assert.matches(/100[\x20\u00a0]?%/, format({ style: "percent" }, 1));
- assert.matches(/1[\x20\u00a0]?%/, format({ style: "percent" }, 0.01));
- assert.matches(/10,000[\x20\u00a0]?%/,format({ style: "percent" }, 100));
- }
- },
- {
- name: "Negative 0 (https://github.com/tc39/ecma402/issues/219)",
- body() {
- assert.areEqual(
- 0,
- new Intl.NumberFormat(undefined, { minimumFractionDigits: -0 }).resolvedOptions().minimumFractionDigits,
- "Passing -0 for minimumFractionDigits should get normalized to 0 by DefaultNumberOption"
- );
- assert.areEqual("-0", (-0).toLocaleString(), "-0 should be treated as a negative number (toLocaleString)");
- assert.areEqual("-0", new Intl.NumberFormat().format(-0), "-0 should be treated as a negative number (NumberFormat.prototype.format)");
- if (WScript.Platform.INTL_LIBRARY === "icu") {
- assert.areEqual("-0", new Intl.NumberFormat().formatToParts(-0).map(v => v.value).join(""), "-0 should be treated as a negative number (NumberFormat.prototype.formatToParts)");
- }
- }
- },
- {
- name: "formatToParts",
- body() {
- if (WScript.Platform.INTL_LIBRARY === "winglob") {
- return;
- }
- function assertParts(locale, options, n, expectedParts) {
- const nf = new Intl.NumberFormat(locale, options);
- const resolved = nf.resolvedOptions();
- assert.areEqual(locale, resolved.locale, `This test requires ${locale} support`);
- if (options) {
- for (const opt of Object.getOwnPropertyNames(options)) {
- assert.areEqual(options[opt], resolved[opt], `Bad option resolution for option ${opt}`)
- }
- }
- const actualParts = nf.formatToParts(n);
- assert.isTrue(Array.isArray(actualParts), `formatToParts(${n}) did not return an array`);
- if (WScript.Platform.ICU_VERSION < 61) {
- // real formatToParts support was only added with ICU 61
- assert.areEqual(1, actualParts.length, `formatToParts(${n}) stub implementation should return only one part`);
- const literal = actualParts[0];
- assert.areEqual("unknown", literal.type, `formatToParts(${n}) stub implementation should return an unknown part`);
- assert.areEqual(nf.format(n), literal.value, `formatToParts(${n}) stub implementation should return one part whose value matches the fully formatted number`);
- return;
- }
- assert.areEqual(expectedParts.length, actualParts.length, `formatToParts(${n}) returned wrong number of parts (actual: ${JSON.stringify(actualParts, null, 2)})`);
- expectedParts.forEach((part, i) => {
- assert.areEqual(expectedParts[i].type, actualParts[i].type, `formatToParts(${n}) returned bad type for part ${i}`);
- assert.areEqual(expectedParts[i].value, actualParts[i].value, `formatToParts(${n}) returned bad value for part ${i} (code points: ${actualParts[i].value.split("").map(char => char.charCodeAt(0)).toString()})`);
- })
- }
- assertParts("en-US", undefined, 1000, [
- { type: "integer" , value: "1" },
- { type: "group", value: "," },
- { type: "integer", value: "000" }
- ]);
- assertParts("en-US", undefined, -1000, [
- { type: "minusSign", value: "-" },
- { type: "integer" , value: "1" },
- { type: "group", value: "," },
- { type: "integer", value: "000" }
- ]);
- if (WScript.Platform.ICU_VERSION !== 62) {
- assertParts("en-US", undefined, NaN, [{ type: "nan", value: "NaN" }]);
- }
- assertParts("en-US", undefined, Infinity, [{ type: "infinity", value: "∞" }]);
- assertParts("en-US", undefined, 1000.3423, [
- { type: "integer", value: "1" },
- { type: "group", value: "," },
- { type: "integer", value: "000" },
- { type: "decimal", value: "." },
- { type: "fraction", value: "342" }
- ]);
- assertParts("en-US", { minimumFractionDigits: 5 }, 1000.3423, [
- { type: "integer", value: "1" },
- { type: "group", value: "," },
- { type: "integer", value: "000" },
- { type: "decimal", value: "." },
- { type: "fraction", value: "34230" }
- ]);
- assertParts("en-US", { style: "currency", currency: "CAD", currencyDisplay: "name" }, 1000.3423, [
- { type: "integer", value: "1" },
- { type: "group", value: "," },
- { type: "integer", value: "000" },
- { type: "decimal", value: "." },
- { type: "fraction", value: "34" },
- { type: "literal", value: " " },
- { type: "currency", value: "Canadian dollars" }
- ]);
- assertParts("en-US", { style: "percent", minimumSignificantDigits: 4 }, 0.3423, [
- { type: "integer", value: "34" },
- { type: "decimal", value: "." },
- { type: "fraction", value: "23" },
- { type: "percent", value: "%" }
- ]);
- assertParts("de-DE", { minimumFractionDigits: 5 }, 1000.3423, [
- { type: "integer", value: "1" },
- { type: "group", value: "." },
- { type: "integer", value: "000" },
- { type: "decimal", value: "," },
- { type: "fraction", value: "34230" }
- ]);
- assertParts("de-DE", { style: "currency", currency: "CAD", currencyDisplay: "name" }, 1000.3423, [
- { type: "integer", value: "1" },
- { type: "group", value: "." },
- { type: "integer", value: "000" },
- { type: "decimal", value: "," },
- { type: "fraction", value: "34" },
- { type: "literal", value: " " },
- { type: "currency", value: "Kanadische Dollar" }
- ]);
- assertParts("de-DE", { style: "percent", minimumSignificantDigits: 4 }, 0.3423, [
- { type: "integer", value: "34" },
- { type: "decimal", value: "," },
- { type: "fraction", value: "23" },
- { type: "literal", value: "\u00A0" }, // non-breaking space
- { type: "percent", value: "%" }
- ]);
- }
- }
- ];
- testRunner.runTests(tests, { verbose: false });
|