// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Adapted from Gecko's js/src/tests/Intl/NumberFormat/formatToParts.js, // which was dedicated to the public domain. // NOTE: Some of these tests exercise standard behavior (e.g. that format and // formatToParts expose the same formatted string). But much of this, // like the exact-formatted-string expectations, is technically // implementation-dependent. This is necessary as a practical matter to // properly test the conversion from ICU's nested-field exposure to // ECMA-402's sequential-parts exposure. if (this.Intl) { function GenericPartCreator(type) { return function(str) { return { type, value: str }; }; } var Nan = GenericPartCreator("nan"); var Inf = GenericPartCreator("infinity"); var Integer = GenericPartCreator("integer"); var Group = GenericPartCreator("group"); var Decimal = GenericPartCreator("decimal"); var Fraction = GenericPartCreator("fraction"); var MinusSign = GenericPartCreator("minusSign"); var PlusSign = GenericPartCreator("plusSign"); var PercentSign = GenericPartCreator("percentSign"); var Currency = GenericPartCreator("currency"); var Literal = GenericPartCreator("literal"); function assertParts(nf, x, expected) { var parts = nf.formatToParts(x); assertEquals(nf.format(x), parts.map(part => part.value).join("")); var len = parts.length; assertEquals(expected.length, len); for (var i = 0; i < len; i++) { assertEquals(expected[i].type, parts[i].type); assertEquals(expected[i].value, parts[i].value); } } //----------------------------------------------------------------------------- // Test behavior of a currency with code formatting. var usdCodeOptions = { style: "currency", currency: "USD", currencyDisplay: "code", minimumFractionDigits: 0, maximumFractionDigits: 0, }; var usDollarsCode = new Intl.NumberFormat("en-US", usdCodeOptions); assertParts(usDollarsCode, 25, [Currency("USD"), Literal("\u00a0"), Integer("25")]); // ISO 4217 currency codes are formed from an ISO 3166-1 alpha-2 country code // followed by a third letter. ISO 3166 guarantees that no country code // starting with "X" will ever be assigned. Stepping carefully around a few // 4217-designated special "currencies", XQQ will never have a representation. // Thus, yes: this really is specified to work, as unrecognized or unsupported // codes pass into the string unmodified. var xqqCodeOptions = { style: "currency", currency: "XQQ", currencyDisplay: "code", minimumFractionDigits: 0, maximumFractionDigits: 0, }; var xqqMoneyCode = new Intl.NumberFormat("en-US", xqqCodeOptions); assertParts(xqqMoneyCode, 25, [Currency("XQQ"), Literal("\u00a0"), Integer("25")]); // Test currencyDisplay: "name". var usdNameOptions = { style: "currency", currency: "USD", currencyDisplay: "name", minimumFractionDigits: 0, maximumFractionDigits: 0, }; var usDollarsName = new Intl.NumberFormat("en-US", usdNameOptions); assertParts(usDollarsName, 25, [Integer("25"), Literal(" "), Currency("US dollars")]); var usdNameGroupingOptions = { style: "currency", currency: "USD", currencyDisplay: "name", minimumFractionDigits: 0, maximumFractionDigits: 0, }; var usDollarsNameGrouping = new Intl.NumberFormat("en-US", usdNameGroupingOptions); assertParts(usDollarsNameGrouping, 12345678, [Integer("12"), Group(","), Integer("345"), Group(","), Integer("678"), Literal(" "), Currency("US dollars")]); // But if the implementation doesn't recognize the currency, the provided code // is used in place of a proper name, unmolested. var xqqNameOptions = { style: "currency", currency: "XQQ", currencyDisplay: "name", minimumFractionDigits: 0, maximumFractionDigits: 0, }; var xqqMoneyName = new Intl.NumberFormat("en-US", xqqNameOptions); assertParts(xqqMoneyName, 25, [Integer("25"), Literal(" "), Currency("XQQ")]); // Test some currencies with fractional components. var usdNameFractionOptions = { style: "currency", currency: "USD", currencyDisplay: "name", minimumFractionDigits: 2, maximumFractionDigits: 2, }; var usdNameFractionFormatter = new Intl.NumberFormat("en-US", usdNameFractionOptions); // The US national surplus (i.e. debt) as of October 18, 2016. // (Replicating data from a comment in Intl.cpp.) var usNationalSurplus = -19766580028249.41; assertParts(usdNameFractionFormatter, usNationalSurplus, [MinusSign("-"), Integer("19"), Group(","), Integer("766"), Group(","), Integer("580"), Group(","), Integer("028"), Group(","), Integer("249"), Decimal("."), Fraction("41"), Literal(" "), Currency("US dollars")]); // Percents in various forms. var usPercentOptions = { style: "percent", minimumFractionDigits: 1, maximumFractionDigits: 1, }; var usPercentFormatter = new Intl.NumberFormat("en-US", usPercentOptions); assertParts(usPercentFormatter, 0.375, [Integer("37"), Decimal("."), Fraction("5"), PercentSign("%")]); assertParts(usPercentFormatter, -1284.375, [MinusSign("-"), Integer("128"), Group(","), Integer("437"), Decimal("."), Fraction("5"), PercentSign("%")]); assertParts(usPercentFormatter, NaN, [Nan("NaN"), PercentSign("%")]); assertParts(usPercentFormatter, Infinity, [Inf("∞"), PercentSign("%")]); assertParts(usPercentFormatter, -Infinity, [MinusSign("-"), Inf("∞"), PercentSign("%")]); var arPercentOptions = { style: "percent", minimumFractionDigits: 2, }; var arPercentFormatter = new Intl.NumberFormat("ar-IQ", arPercentOptions); assertParts(arPercentFormatter, -135.32, [Literal("\u{061C}"), MinusSign("-"), Integer("١٣"), Group("٬"), Integer("٥٣٢"), Decimal("٫"), Fraction("٠٠"), PercentSign("٪"), Literal("\u{061C}")]); // Decimals. var usDecimalOptions = { style: "decimal", maximumFractionDigits: 7 // minimum defaults to 0 }; var usDecimalFormatter = new Intl.NumberFormat("en-US", usDecimalOptions); assertParts(usDecimalFormatter, 42, [Integer("42")]); assertParts(usDecimalFormatter, 1337, [Integer("1"), Group(","), Integer("337")]); assertParts(usDecimalFormatter, -6.25, [MinusSign("-"), Integer("6"), Decimal("."), Fraction("25")]); assertParts(usDecimalFormatter, -1376.25, [MinusSign("-"), Integer("1"), Group(","), Integer("376"), Decimal("."), Fraction("25")]); assertParts(usDecimalFormatter, 124816.8359375, [Integer("124"), Group(","), Integer("816"), Decimal("."), Fraction("8359375")]); var usNoGroupingDecimalOptions = { style: "decimal", useGrouping: false, maximumFractionDigits: 7 // minimum defaults to 0 }; var usNoGroupingDecimalFormatter = new Intl.NumberFormat("en-US", usNoGroupingDecimalOptions); assertParts(usNoGroupingDecimalFormatter, 1337, [Integer("1337")]); assertParts(usNoGroupingDecimalFormatter, -6.25, [MinusSign("-"), Integer("6"), Decimal("."), Fraction("25")]); assertParts(usNoGroupingDecimalFormatter, -1376.25, [MinusSign("-"), Integer("1376"), Decimal("."), Fraction("25")]); assertParts(usNoGroupingDecimalFormatter, 124816.8359375, [Integer("124816"), Decimal("."), Fraction("8359375")]); var deDecimalOptions = { style: "decimal", maximumFractionDigits: 7 // minimum defaults to 0 }; var deDecimalFormatter = new Intl.NumberFormat("de-DE", deDecimalOptions); assertParts(deDecimalFormatter, 42, [Integer("42")]); assertParts(deDecimalFormatter, 1337, [Integer("1"), Group("."), Integer("337")]); assertParts(deDecimalFormatter, -6.25, [MinusSign("-"), Integer("6"), Decimal(","), Fraction("25")]); assertParts(deDecimalFormatter, -1376.25, [MinusSign("-"), Integer("1"), Group("."), Integer("376"), Decimal(","), Fraction("25")]); assertParts(deDecimalFormatter, 124816.8359375, [Integer("124"), Group("."), Integer("816"), Decimal(","), Fraction("8359375")]); var deNoGroupingDecimalOptions = { style: "decimal", useGrouping: false, maximumFractionDigits: 7 // minimum defaults to 0 }; var deNoGroupingDecimalFormatter = new Intl.NumberFormat("de-DE", deNoGroupingDecimalOptions); assertParts(deNoGroupingDecimalFormatter, 1337, [Integer("1337")]); assertParts(deNoGroupingDecimalFormatter, -6.25, [MinusSign("-"), Integer("6"), Decimal(","), Fraction("25")]); assertParts(deNoGroupingDecimalFormatter, -1376.25, [MinusSign("-"), Integer("1376"), Decimal(","), Fraction("25")]); assertParts(deNoGroupingDecimalFormatter, 124816.8359375, [Integer("124816"), Decimal(","), Fraction("8359375")]); }