v8/test/intl/number-format/format-range-v3.js
Frank Tang a4bdc77fe8 [intl] Part 3 of NumberFormat v3
Add NumberFormat.prototype.formatRange(ToParts)?

https://github.com/tc39/proposal-intl-numberformat-v3

https://chromestatus.com/guide/edit/5707621009981440

Design Doc: https://docs.google.com/document/d/19jAogPBb6W4Samt8NWGZKu47iv0_KoQhBvLgQH3xvr8/edit


Bug: v8:10776
Change-Id: I9bb163c0c15ccac9d3a2d5e55ad38aa5c06bbaa6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3429464
Reviewed-by: Shu-yu Guo <syg@chromium.org>
Commit-Queue: Frank Tang <ftang@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79373}
2022-03-04 22:53:20 +00:00

159 lines
5.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2022 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.
// Flags: --harmony-intl-number-format-v3
const validRanges = [[-12345, -5678], [-12345, 56789], [12345, 56789]];
const nf = new Intl.NumberFormat("en", {signDisplay: "exceptZero"});
['formatRange', 'formatRangeToParts'].forEach(function(method) {
assertEquals("function", typeof nf[method]);
// 2. Perform ? RequireInternalSlot(nf, [[InitializedNumberFormat]]).
// Assert if called without nf
let f = nf[method];
assertThrows(() => { f(1, 23) }, TypeError);
// Assert normal call success
assertDoesNotThrow(() => nf[method](1, 23));
// 3. If start is undefined ..., throw a TypeError exception.
assertThrows(() => { nf[method](undefined, 23) }, TypeError);
// 3. If ... end is undefined, throw a TypeError exception.
assertThrows(() => { nf[method](1, undefined) }, TypeError);
// 4. Let x be ? ToNumeric(start).
// Verify it won't throw error
assertDoesNotThrow(() => nf[method](null, 23));
assertDoesNotThrow(() => nf[method](false, 23));
assertDoesNotThrow(() => nf[method](true, 23));
assertDoesNotThrow(() => nf[method](12, 23));
assertDoesNotThrow(() => nf[method](12n, 23));
// Verify it will throw error
assertThrows(() => { nf[method](Symbol(12), 23) }, TypeError);
// 5. Let y be ? ToNumeric(end).
// Verify it won't throw error
assertDoesNotThrow(() => nf[method](-12, null));
assertDoesNotThrow(() => nf[method](-12, false));
assertDoesNotThrow(() => nf[method](-12, true));
assertDoesNotThrow(() => nf[method](12, 23));
assertDoesNotThrow(() => nf[method](12, 23n));
// Verify it will throw error
assertThrows(() => { nf[method](12, Symbol(23)) }, TypeError);
// 6. If x is NaN ..., throw a RangeError exception.
assertThrows(() => { nf[method](NaN, 23) }, RangeError);
// 6. If ... y is NaN, throw a RangeError exception.
assertThrows(() => { nf[method](12, NaN) }, RangeError);
// 8. If x is greater than y, throw a RangeError exception.
// neither x nor y are bigint.
assertThrows(() => { nf[method](23, 12) }, RangeError);
assertDoesNotThrow(() => nf[method](12, 23));
// x is not bigint but y is.
assertThrows(() => { nf[method](23, 12n) }, RangeError);
assertDoesNotThrow(() => nf[method](12, 23n));
// x is bigint but y is not.
assertThrows(() => { nf[method](23n, 12) }, RangeError);
assertDoesNotThrow(() => nf[method](12n, 23));
// both x and y are bigint.
assertThrows(() => { nf[method](23n, 12n) }, RangeError);
assertDoesNotThrow(() => nf[method](12n, 23n));
validRanges.forEach(
function([x, y]) {
const X = BigInt(x);
const Y = BigInt(y);
const formatted_x_y = nf[method](x, y);
const formatted_X_y = nf[method](X, y);
const formatted_x_Y = nf[method](x, Y);
const formatted_X_Y = nf[method](X, Y);
assertEquals(formatted_x_y, formatted_X_y);
assertEquals(formatted_x_y, formatted_x_Y);
assertEquals(formatted_x_y, formatted_X_Y);
});
});
// Check the number of part with type: "plusSign" and "minusSign" are corre
validRanges.forEach(
function([x, y]) {
const expectedPlus = (x > 0) ? ((y > 0) ? 2 : 1) : ((y > 0) ? 1 : 0);
const expectedMinus = (x < 0) ? ((y < 0) ? 2 : 1) : ((y < 0) ? 1 : 0);
let actualPlus = 0;
let actualMinus = 0;
const parts = nf.formatRangeToParts(x, y);
parts.forEach(function(part) {
if (part.type == "plusSign") actualPlus++;
if (part.type == "minusSign") actualMinus++;
});
const method = "formatRangeToParts(" + x + ", " + y + "): ";
assertEquals(expectedPlus, actualPlus,
method + "Number of type: 'plusSign' in parts is incorrect");
assertEquals(expectedMinus, actualMinus,
method + "Number of type: 'minusSign' in parts is incorrect");
});
// From https://github.com/tc39/proposal-intl-numberformat-v3#formatrange-ecma-402-393
const nf2 = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "EUR",
maximumFractionDigits: 0,
});
// README.md said it expect "€35"
assertEquals("€3 €5", nf2.formatRange(3, 5));
const nf3 = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "EUR",
maximumFractionDigits: 0,
});
const actual3 = nf3.formatRangeToParts(3, 5);
/*
[
{type: "currency", value: "€", source: "startRange"}
{type: "integer", value: "3", source: "startRange"}
{type: "literal", value: "", source: "shared"}
{type: "integer", value: "5", source: "endRange"}
]
*/
assertEquals(5, actual3.length);
assertEquals("currency", actual3[0].type);
assertEquals("€", actual3[0].value);
assertEquals("startRange", actual3[0].source);
assertEquals("integer", actual3[1].type);
assertEquals("3", actual3[1].value);
assertEquals("startRange", actual3[1].source);
assertEquals("literal", actual3[2].type);
assertEquals(" ", actual3[2].value);
assertEquals("shared", actual3[2].source);
assertEquals("currency", actual3[3].type);
assertEquals("€", actual3[3].value);
assertEquals("endRange", actual3[3].source);
assertEquals("integer", actual3[4].type);
assertEquals("5", actual3[4].value);
assertEquals("endRange", actual3[4].source);
const nf4 = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "EUR",
maximumFractionDigits: 0,
});
assertEquals("~€3", nf4.formatRange(2.9, 3.1));
const nf5 = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "EUR",
signDisplay: "always",
});
assertEquals("~+€3.00", nf5.formatRange(2.999, 3.001));
const nf6 = new Intl.NumberFormat("en");
assertEquals("3∞", nf6.formatRange(3, 1/0));
assertThrows(() => { nf6.formatRange(3, 0/0); }, RangeError);