blob: fc103cbb2353e53a448b018bb411f0095174ff82 [file] [log] [blame]
//-------------------------------------------------------------------------------------------------------
// 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");
testRunner.runTests([
{
name: "Basic compare behavior",
body() {
function test(locale, options, left, right, expected) {
const msg = `Comparing ${left} and ${right} with options ${JSON.stringify(options)} and locale ${locale}`;
assert.areEqual(expected, new Intl.Collator(locale, options).compare(left, right), `${msg} using Intl.Collator`);
assert.areEqual(expected, left.localeCompare(right, locale, options), `${msg} using String.prototype.localeCompare`);
}
test("en-US", { sensitivity: "base" }, "A", "a", 0);
test("en-US", { sensitivity: "base" }, "A", "B", -1);
test("en-US", { sensitivity: "base" }, "a", "\u00E2", 0);
test("en-US", { sensitivity: "accent" }, "A", "a", 0);
test("en-US", { sensitivity: "accent" }, "A", "B", -1);
test("en-US", { sensitivity: "accent" }, "a", "\u00E2", -1);
test("en-US", { sensitivity: "case" }, "A", "a", 1);
test("en-US", { sensitivity: "case" }, "A", "B", -1);
test("en-US", { sensitivity: "case" }, "a", "\u00E2", 0);
test("en-US", { sensitivity: "variant" }, "A", "a", 1);
test("en-US", { sensitivity: "variant" }, "A", "B", -1);
test("en-US", { sensitivity: "variant" }, "a", "\u00E2", -1);
test("en-US", { ignorePunctuation: true }, ".a", "a", 0);
test("en-US", { ignorePunctuation: false }, ".a", "a", -1);
test("en-US", { numeric: true }, "10", "9", 1);
test("en-US", { numeric: false }, "10", "9", -1);
assert.areEqual("de-DE", Intl.Collator.supportedLocalesOf("de-DE")[0], "This test requires de-DE");
test("de-DE-u-co-phonebk", {}, "\u00e4b", "ada", 1);
test("de-DE-u-co-phonebk", {}, "äb", "ada", 1);
test("de-DE", {}, "\u00e4b", "ada", -1);
test("de-DE", {}, "äb", "ada", -1);
test("de-DE", { numeric: true }, "21", "100", -1);
test("de-DE-u-kn-true", {}, "21", "100", -1);
test("de-DE", { numeric: false }, "21", "100", 1);
test("de-DE-u-kn-false", {}, "21", "100", 1);
test("de-DE-u-kn-true-co-phonebk", {}, "21", "100", -1);
test("de-DE-u-kn-true-co-phonebk", {}, "\u00e4b", "ada", 1);
test("de-DE-u-kn-false-co-phonebk", {}, "21", "100", 1);
test("de-DE-u-kn-false-co-phonebk", {}, "\u00e4b", "ada", 1);
test("en-US", { ignorePunctuation: true }, "aa", "a!a", 0);
test("en-US", { ignorePunctuation: false }, "aa", "a!a", 1);
}
},
{
name: "Options resolution",
body() {
assert.areEqual("es", Intl.Collator.supportedLocalesOf("es")[0], "Collator must support es for this test");
assert.areEqual("default", new Intl.Collator("es", { collation: "trad" }).resolvedOptions().collation, "Collation must not be taken through options object");
assert.areEqual("trad", new Intl.Collator("es-u-co-trad").resolvedOptions().collation, "Collation must be taken through unicode extension");
function test(locale, options, expectedResolved) {
const coll = new Intl.Collator(locale, options);
const resolved = coll.resolvedOptions();
const expected = expectedResolved || options;
for (const prop of Object.getOwnPropertyNames(expected)) {
assert.areEqual(expected[prop], resolved[prop], `Testing option property ${prop} with locale ${locale} and options ${JSON.stringify(options)}`);
}
}
test("en-US", { sensitivity: "variant" });
test("en-US", { sensitivity: "case" });
test("en-US", { sensitivity: "accent" });
test("en-US", { sensitivity: "base" });
if (WScript.Platform.INTL_LIBRARY === "winglob") {
// Windows Globalization has different, usually incorrect, option resolution strategies
return;
}
assert.areEqual("de-DE", Intl.Collator.supportedLocalesOf("de-DE")[0], "This test requires de-DE");
// collation can not be passed via options object
test("de-DE", { collation: "phonebk" }, { collation: "default" });
test("de-DE-u-co-phonebk", { collation: "phonebk" });
// Defaults
test("de-DE", undefined, { numeric: false, caseFirst: "false", collation: "default", sensitivity: "variant", ignorePunctuation: false });
// numeric option
test("de-DE", { numeric: false });
test("de-DE", { numeric: true });
test("de-DE-u-kn-true", undefined, { numeric: true });
test("de-DE-u-kn-false", undefined, { numeric: false });
// options object takes precedence
test("de-DE-u-kn-true", { numeric: false });
test("de-DE-u-kn-false", { numeric: true });
// caseFirst option
test("de-DE", { caseFirst: "upper" });
test("de-DE", { caseFirst: "lower" });
test("de-DE", { caseFirst: "false" });
test("de-DE-u-kf-upper", undefined, { caseFirst: "upper" });
test("de-DE-u-kf-lower", undefined, { caseFirst: "lower" });
test("de-DE-u-kf-false", undefined, { caseFirst: "false" });
// options object takes precedence
test("de-DE-u-kf-upper", { caseFirst: "lower" });
test("de-DE-u-kf-false", { caseFirst: "upper" });
// mixing unicode extensions and options object
test("de-DE-u-co-phonebk", { numeric: false }, { numeric: false, collation: "phonebk" });
test("de-DE-u-co-phonebk-kn-true", { numeric: false, caseFirst: "upper", ignorePunctuation: true }, { numeric: false, caseFirst: "upper", ignorePunctuation: true, collation: "phonebk" });
}
},
{
name: "Invalid options should throw",
body() {
function test(locale, options) {
assert.throws(() => new Intl.Collator(locale, options), RangeError, `Creating a collator`);
assert.throws(() => "a".localeCompare("b", locale, options), RangeError, `localeCompare with locale ${locale} and options ${JSON.stringify(options)}`);
}
test("en-US", { usage: "invalid" });
test("en-US", { localeMatcher: "invalid" });
test("en-US", { caseFirst: "invalid" });
test("en-US", { sensitivity: "invalid" });
}
},
{
name: "Collator should normalize strings",
body() {
// this test is adapted from test262's `canonically-equivalent-strings` test
const collator = new Intl.Collator();
const pairs = [
// example from Unicode 5.0, section 3.7, definition D70
["o\u0308", "ö"],
// examples from Unicode 5.0, chapter 3.11
["ä\u0323", "a\u0323\u0308"],
["a\u0308\u0323", "a\u0323\u0308"],
["ạ\u0308", "a\u0323\u0308"],
["ä\u0306", "a\u0308\u0306"],
["ă\u0308", "a\u0306\u0308"],
// example from Unicode 5.0, chapter 3.12
["\u1111\u1171\u11B6", "퓛"],
// examples from UTS 10, Unicode Collation Algorithm
["Å", "Å"],
["Å", "A\u030A"],
["x\u031B\u0323", "x\u0323\u031B"],
["ự", "ụ\u031B"],
["ự", "u\u031B\u0323"],
["ự", "ư\u0323"],
["ự", "u\u0323\u031B"],
// examples from UAX 15, Unicode Normalization Forms
["Ç", "C\u0327"],
["q\u0307\u0323", "q\u0323\u0307"],
["가", "\u1100\u1161"],
["Å", "A\u030A"],
["Ω", "Ω"],
["Å", "A\u030A"],
["ô", "o\u0302"],
["ṩ", "s\u0323\u0307"],
["ḋ\u0323", "d\u0323\u0307"],
["ḋ\u0323", "ḍ\u0307"],
["q\u0307\u0323", "q\u0323\u0307"],
// examples involving supplementary characters from UCD NormalizationTest.txt
["\uD834\uDD5E", "\uD834\uDD57\uD834\uDD65"],
["\uD87E\uDC2B", "北"]
];
function test(left, right) {
assert.areEqual(0, collator.compare(left, right), `${left} and ${right} were not equal using Intl.Collator`);
assert.areEqual(0, left.localeCompare(right), `${left} and ${right} were not equal using String.prototype.localeCompare`);
}
pairs.forEach((pair) => test(pair[0], pair[1]));
}
},
{
name: "https://github.com/Microsoft/ChakraCore/issues/5097",
body() {
const cases = [0, 1, true, false, null, undefined, { toString() { return "hello!" }}, [1, 2, 3, 4], {}, new (class ToStringTag { get [Symbol.toStringTag]() { return "MyClass" } })];
const coll = new Intl.Collator();
cases.forEach((test) => {
assert.areEqual(0, ("" + test).localeCompare(test), `${test} did not compare equal to itself using String.prototype.localeCompare`);
assert.areEqual(0, coll.compare("" + test, test), `${test} did not compare equal to itself using Collator.prototype.compare`);
});
}
}
], { verbose: !WScript.Arguments.includes("summary") });