mirror of
https://github.com/tc39/test262.git
synced 2025-04-08 19:35:28 +02:00
Added new tests for chapters 10 to 13 of the ECMAScript Internationalization API Specification.
This commit is contained in:
parent
1af2425075
commit
d71ffa59d5
@ -656,3 +656,474 @@ function isCanonicalizedStructurallyValidLanguageTag(locale) {
|
||||
canonicalizeLanguageTag(locale) === locale;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the named options property is correctly handled by the given constructor.
|
||||
* @param {object} Constructor the constructor to test.
|
||||
* @param {string} property the name of the options property to test.
|
||||
* @param {string} type the type that values of the property are expected to have
|
||||
* @param {Array} [values] an array of allowed values for the property. Not needed for boolean.
|
||||
* @param {any} fallback the fallback value that the property assumes if not provided.
|
||||
* @param {object} testOptions additional options:
|
||||
* @param {boolean} isOptional whether support for this property is optional for implementations.
|
||||
* @param {boolean} noReturn whether the resulting value of the property is not returned.
|
||||
* @param {boolean} isILD whether the resulting value of the property is implementation and locale dependent.
|
||||
* @param {object} extra additional option to pass along, properties are value -> {option: value}.
|
||||
* @return {boolean} whether the test succeeded.
|
||||
*/
|
||||
function testOption(Constructor, property, type, values, fallback, testOptions) {
|
||||
var isOptional = testOptions !== undefined && testOptions.isOptional === true;
|
||||
var noReturn = testOptions !== undefined && testOptions.noReturn === true;
|
||||
var isILD = testOptions !== undefined && testOptions.isILD === true;
|
||||
|
||||
function addExtraOptions(options, value, testOptions) {
|
||||
if (testOptions !== undefined && testOptions.extra !== undefined) {
|
||||
var extra;
|
||||
if (value !== undefined && testOptions.extra[value] !== undefined) {
|
||||
extra = testOptions.extra[value];
|
||||
} else if (testOptions.extra.any !== undefined) {
|
||||
extra = testOptions.extra.any;
|
||||
}
|
||||
if (extra !== undefined) {
|
||||
Object.getOwnPropertyNames(extra).forEach(function (prop) {
|
||||
options[prop] = extra[prop];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testValues, options, obj, expected, actual, error;
|
||||
|
||||
// test that the specified values are accepted. Also add values that convert to specified values.
|
||||
if (type === "boolean") {
|
||||
if (values === undefined) {
|
||||
values = [true, false];
|
||||
}
|
||||
testValues = values.slice(0);
|
||||
testValues.push(888);
|
||||
testValues.push(0);
|
||||
} else if (type === "string") {
|
||||
testValues = values.slice(0);
|
||||
testValues.push({toString: function () { return values[0]; }});
|
||||
}
|
||||
testValues.forEach(function (value) {
|
||||
options = {};
|
||||
options[property] = value;
|
||||
addExtraOptions(options, value, testOptions);
|
||||
obj = new Constructor(undefined, options);
|
||||
if (noReturn) {
|
||||
if (obj.resolvedOptions().hasOwnProperty(property)) {
|
||||
$ERROR("Option property " + property + " is returned, but shouldn't be.");
|
||||
}
|
||||
} else {
|
||||
actual = obj.resolvedOptions()[property];
|
||||
if (isILD) {
|
||||
if (actual !== undefined && values.indexOf(actual) === -1) {
|
||||
$ERROR("Invalid value " + actual + " returned for property " + property + ".");
|
||||
}
|
||||
} else {
|
||||
if (type === "boolean") {
|
||||
expected = Boolean(value);
|
||||
} else if (type === "string") {
|
||||
expected = String(value);
|
||||
}
|
||||
if (actual !== expected && !(isOptional && actual === undefined)) {
|
||||
$ERROR("Option value " + value + " for property " + property +
|
||||
" was not accepted; got " + actual + " instead.");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// test that invalid values are rejected
|
||||
if (type === "string") {
|
||||
var invalidValues = ["invalidValue", -1, null];
|
||||
// assume that we won't have values in caseless scripts
|
||||
if (values[0].toUpperCase() !== values[0]) {
|
||||
invalidValues.push(values[0].toUpperCase());
|
||||
} else {
|
||||
invalidValues.push(values[0].toLowerCase());
|
||||
}
|
||||
invalidValues.forEach(function (value) {
|
||||
options = {};
|
||||
options[property] = value;
|
||||
addExtraOptions(options, value, testOptions);
|
||||
error = undefined;
|
||||
try {
|
||||
obj = new Constructor(undefined, options);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Invalid option value " + value + " for property " + property + " was not rejected.");
|
||||
} else if (error.name !== "RangeError") {
|
||||
$ERROR("Invalid option value " + value + " for property " + property + " was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// test that fallback value or another valid value is used if no options value is provided
|
||||
if (!noReturn) {
|
||||
options = {};
|
||||
addExtraOptions(options, undefined, testOptions);
|
||||
obj = new Constructor(undefined, options);
|
||||
actual = obj.resolvedOptions()[property];
|
||||
if (!(isOptional && actual === undefined)) {
|
||||
if (fallback !== undefined) {
|
||||
if (actual !== fallback) {
|
||||
$ERROR("Option fallback value " + fallback + " for property " + property +
|
||||
" was not used; got " + actual + " instead.");
|
||||
}
|
||||
} else {
|
||||
if (values.indexOf(actual) === -1 && !(isILD && actual === undefined)) {
|
||||
$ERROR("Invalid value " + actual + " returned for property " + property + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the named property of the given object has a valid value
|
||||
* and the default attributes of the properties of an object literal.
|
||||
* @param {Object} obj the object to be tested.
|
||||
* @param {string} property the name of the property
|
||||
* @param {Function|Array} valid either a function that tests value for validity and returns a boolean,
|
||||
* an array of valid values.
|
||||
* @exception if the property has an invalid value.
|
||||
*/
|
||||
function testProperty(obj, property, valid) {
|
||||
var desc = Object.getOwnPropertyDescriptor(obj, property);
|
||||
if (!desc.writable) {
|
||||
$ERROR("Property " + property + " must be writable.");
|
||||
}
|
||||
if (!desc.enumerable) {
|
||||
$ERROR("Property " + property + " must be enumerable.");
|
||||
}
|
||||
if (!desc.configurable) {
|
||||
$ERROR("Property " + property + " must be configurable.");
|
||||
}
|
||||
var value = desc.value;
|
||||
var isValid = (typeof valid === "function") ? valid(value) : (valid.indexOf(value) !== -1);
|
||||
if (!isValid) {
|
||||
$ERROR("Property value " + value + " is not allowed for property " + property + ".");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the named property of the given object, if present at all, has a valid value
|
||||
* and the default attributes of the properties of an object literal.
|
||||
* @param {Object} obj the object to be tested.
|
||||
* @param {string} property the name of the property
|
||||
* @param {Function|Array} valid either a function that tests value for validity and returns a boolean,
|
||||
* an array of valid values.
|
||||
* @exception if the property is present and has an invalid value.
|
||||
*/
|
||||
function mayHaveProperty(obj, property, valid) {
|
||||
if (obj.hasOwnProperty(property)) {
|
||||
testProperty(obj, property, valid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the given object has the named property with a valid value
|
||||
* and the default attributes of the properties of an object literal.
|
||||
* @param {Object} obj the object to be tested.
|
||||
* @param {string} property the name of the property
|
||||
* @param {Function|Array} valid either a function that tests value for validity and returns a boolean,
|
||||
* an array of valid values.
|
||||
* @exception if the property is missing or has an invalid value.
|
||||
*/
|
||||
function mustHaveProperty(obj, property, valid) {
|
||||
if (!obj.hasOwnProperty(property)) {
|
||||
$ERROR("Object is missing property " + property + ".");
|
||||
}
|
||||
testProperty(obj, property, valid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the given object does not have the named property.
|
||||
* @param {Object} obj the object to be tested.
|
||||
* @param {string} property the name of the property
|
||||
* @exception if the property is present.
|
||||
*/
|
||||
function mustNotHaveProperty(obj, property) {
|
||||
if (obj.hasOwnProperty(property)) {
|
||||
$ERROR("Object has property it mustn't have: " + property + ".");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether name is a valid BCP 47 numbering system name
|
||||
* and not excluded from use in the ECMAScript Internationalization API.
|
||||
* @param {string} name the name to be tested.
|
||||
* @return {boolean} whether name is a valid BCP 47 numbering system name and
|
||||
* allowed for use in the ECMAScript Internationalization API.
|
||||
*/
|
||||
|
||||
function isValidNumberingSystem(name) {
|
||||
|
||||
// source: CLDR file common/bcp47/number.xml; version CLDR 21.
|
||||
var numberingSystems = [
|
||||
"arab",
|
||||
"arabext",
|
||||
"armn",
|
||||
"armnlow",
|
||||
"bali",
|
||||
"beng",
|
||||
"brah",
|
||||
"cakm",
|
||||
"cham",
|
||||
"deva",
|
||||
"ethi",
|
||||
"finance",
|
||||
"fullwide",
|
||||
"geor",
|
||||
"grek",
|
||||
"greklow",
|
||||
"gujr",
|
||||
"guru",
|
||||
"hanidec",
|
||||
"hans",
|
||||
"hansfin",
|
||||
"hant",
|
||||
"hantfin",
|
||||
"hebr",
|
||||
"java",
|
||||
"jpan",
|
||||
"jpanfin",
|
||||
"kali",
|
||||
"khmr",
|
||||
"knda",
|
||||
"osma",
|
||||
"lana",
|
||||
"lanatham",
|
||||
"laoo",
|
||||
"latn",
|
||||
"lepc",
|
||||
"limb",
|
||||
"mlym",
|
||||
"mong",
|
||||
"mtei",
|
||||
"mymr",
|
||||
"mymrshan",
|
||||
"native",
|
||||
"nkoo",
|
||||
"olck",
|
||||
"orya",
|
||||
"roman",
|
||||
"romanlow",
|
||||
"saur",
|
||||
"shrd",
|
||||
"sora",
|
||||
"sund",
|
||||
"talu",
|
||||
"takr",
|
||||
"taml",
|
||||
"tamldec",
|
||||
"telu",
|
||||
"thai",
|
||||
"tibt",
|
||||
"traditio",
|
||||
"vaii"
|
||||
];
|
||||
|
||||
var excluded = [
|
||||
"finance",
|
||||
"native",
|
||||
"traditio"
|
||||
];
|
||||
|
||||
|
||||
return numberingSystems.indexOf(name) !== -1 && excluded.indexOf(name) === -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides the digits of numbering systems with simple digit mappings,
|
||||
* as specified in 11.3.2.
|
||||
*/
|
||||
|
||||
var numberingSystemDigits = {
|
||||
arab: "٠١٢٣٤٥٦٧٨٩",
|
||||
arabext: "۰۱۲۳۴۵۶۷۸۹",
|
||||
beng: "০১২৩৪৫৬৭৮৯",
|
||||
deva: "०१२३४५६७८९",
|
||||
fullwide: "0123456789",
|
||||
gujr: "૦૧૨૩૪૫૬૭૮૯",
|
||||
guru: "੦੧੨੩੪੫੬੭੮੯",
|
||||
hanidec: "〇一二三四五六七八九",
|
||||
khmr: "០១២៣៤៥៦៧៨៩",
|
||||
knda: "೦೧೨೩೪೫೬೭೮೯",
|
||||
laoo: "໐໑໒໓໔໕໖໗໘໙",
|
||||
latn: "0123456789",
|
||||
mlym: "൦൧൨൩൪൫൬൭൮൯",
|
||||
mong: "᠐᠑᠒᠓᠔᠕᠖᠗᠘᠙",
|
||||
mymr: "၀၁၂၃၄၅၆၇၈၉",
|
||||
orya: "୦୧୨୩୪୫୬୭୮୯",
|
||||
tamldec: "௦௧௨௩௪௫௬௭௮௯",
|
||||
telu: "౦౧౨౩౪౫౬౭౮౯",
|
||||
thai: "๐๑๒๓๔๕๖๗๘๙",
|
||||
tibt: "༠༡༢༣༤༥༦༧༨༩"
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tests that number formatting is handled correctly. The function checks that the
|
||||
* digit sequences in formatted output are as specified, converted to the
|
||||
* selected numbering system, and embedded in consistent localized patterns.
|
||||
* @param {Array} locales the locales to be tested.
|
||||
* @param {Array} numberingSystems the numbering systems to be tested.
|
||||
* @param {Object} options the options to pass to Intl.NumberFormat. Options
|
||||
* must include {useGrouping: false}, and must cause 1.1 to be formatted
|
||||
* pre- and post-decimal digits.
|
||||
* @param {Object} testData maps input data (in ES5 9.3.1 format) to expected output strings
|
||||
* in unlocalized format with Western digits.
|
||||
*/
|
||||
|
||||
function testNumberFormat(locales, numberingSystems, options, testData) {
|
||||
locales.forEach(function (locale) {
|
||||
numberingSystems.forEach(function (numbering) {
|
||||
var digits = numberingSystemDigits[numbering];
|
||||
var format = new Intl.NumberFormat([locale + "-u-nu-" + numbering], options);
|
||||
|
||||
function getPatternParts(positive) {
|
||||
var n = positive ? 1.1 : -1.1;
|
||||
var formatted = format.format(n);
|
||||
var oneoneRE = "([^" + digits + "]*)[" + digits + "]+([^" + digits + "]+)[" + digits + "]+([^" + digits + "]*)";
|
||||
var match = formatted.match(new RegExp(oneoneRE));
|
||||
if (match === null) {
|
||||
$ERROR("Unexpected formatted " + n + " for " +
|
||||
format.resolvedOptions().locale + " and options " +
|
||||
JSON.stringify(options) + ": " + formatted);
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
function toNumbering(raw) {
|
||||
return raw.replace(/[0-9]/g, function (digit) {
|
||||
return digits[digit.charCodeAt(0) - "0".charCodeAt(0)];
|
||||
});
|
||||
}
|
||||
|
||||
function buildExpected(raw, patternParts) {
|
||||
var period = raw.indexOf(".");
|
||||
if (period === -1) {
|
||||
return patternParts[1] + toNumbering(raw) + patternParts[3];
|
||||
} else {
|
||||
return patternParts[1] +
|
||||
toNumbering(raw.substring(0, period)) +
|
||||
patternParts[2] +
|
||||
toNumbering(raw.substring(period + 1)) +
|
||||
patternParts[3];
|
||||
}
|
||||
}
|
||||
|
||||
if (format.resolvedOptions().numberingSystem === numbering) {
|
||||
// figure out prefixes, infixes, suffixes for positive and negative values
|
||||
var posPatternParts = getPatternParts(true);
|
||||
var negPatternParts = getPatternParts(false);
|
||||
|
||||
Object.getOwnPropertyNames(testData).forEach(function (input) {
|
||||
var rawExpected = testData[input];
|
||||
var patternParts;
|
||||
if (rawExpected[0] === "-") {
|
||||
patternParts = negPatternParts;
|
||||
rawExpected = rawExpected.substring(1);
|
||||
} else {
|
||||
patternParts = posPatternParts;
|
||||
}
|
||||
var expected = buildExpected(rawExpected, patternParts);
|
||||
var actual = format.format(input);
|
||||
if (actual !== expected) {
|
||||
$ERROR("Formatted value for " + input + ", " +
|
||||
format.resolvedOptions().locale + " and options " +
|
||||
JSON.stringify(options) + " is " + actual + "; expected " + expected + ".");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the components of date-time formats.
|
||||
* @return {Array} an array with all date-time components.
|
||||
*/
|
||||
|
||||
function getDateTimeComponents() {
|
||||
return ["weekday", "era", "year", "month", "day", "hour", "minute", "second", "timeZoneName"];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the valid values for the given date-time component, as specified
|
||||
* by the table in section 12.1.1.
|
||||
* @param {string} component a date-time component.
|
||||
* @return {Array} an array with the valid values for the component.
|
||||
*/
|
||||
|
||||
function getDateTimeComponentValues(component) {
|
||||
|
||||
var components = {
|
||||
weekday: ["narrow", "short", "long"],
|
||||
era: ["narrow", "short", "long"],
|
||||
year: ["2-digit", "numeric"],
|
||||
month: ["2-digit", "numeric", "narrow", "short", "long"],
|
||||
day: ["2-digit", "numeric"],
|
||||
hour: ["2-digit", "numeric"],
|
||||
minute: ["2-digit", "numeric"],
|
||||
second: ["2-digit", "numeric"],
|
||||
timeZoneName: ["short", "long"]
|
||||
};
|
||||
|
||||
var result = components[component];
|
||||
if (result === undefined) {
|
||||
$ERROR("Internal error: No values defined for date-time component " + component + ".");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests that the given value is valid for the given date-time component.
|
||||
* @param {string} component a date-time component.
|
||||
* @param {string} value the value to be tested.
|
||||
* @return {boolean} true if the test succeeds.
|
||||
* @exception if the test fails.
|
||||
*/
|
||||
|
||||
function testValidDateTimeComponentValue(component, value) {
|
||||
if (getDateTimeComponentValues(component).indexOf(value) === -1) {
|
||||
$ERROR("Invalid value " + value + " for date-time component " + component + ".");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifies that the actual array matches the expected one in length, elements,
|
||||
* and element order.
|
||||
* @param {Array} expected the expected array.
|
||||
* @param {Array} actual the actual array.
|
||||
* @return {boolean} true if the test succeeds.
|
||||
* @exception if the test fails.
|
||||
*/
|
||||
function testArraysAreSame(expected, actual) {
|
||||
for (i = 0; i < Math.max(actual.length, expected.length); i++) {
|
||||
if (actual[i] !== expected[i]) {
|
||||
$ERROR("Result array element at index " + i + " should be \"" +
|
||||
expected[i] + "\" but is \"" + actual[i] + "\".");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -656,3 +656,474 @@ function isCanonicalizedStructurallyValidLanguageTag(locale) {
|
||||
canonicalizeLanguageTag(locale) === locale;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the named options property is correctly handled by the given constructor.
|
||||
* @param {object} Constructor the constructor to test.
|
||||
* @param {string} property the name of the options property to test.
|
||||
* @param {string} type the type that values of the property are expected to have
|
||||
* @param {Array} [values] an array of allowed values for the property. Not needed for boolean.
|
||||
* @param {any} fallback the fallback value that the property assumes if not provided.
|
||||
* @param {object} testOptions additional options:
|
||||
* @param {boolean} isOptional whether support for this property is optional for implementations.
|
||||
* @param {boolean} noReturn whether the resulting value of the property is not returned.
|
||||
* @param {boolean} isILD whether the resulting value of the property is implementation and locale dependent.
|
||||
* @param {object} extra additional option to pass along, properties are value -> {option: value}.
|
||||
* @return {boolean} whether the test succeeded.
|
||||
*/
|
||||
function testOption(Constructor, property, type, values, fallback, testOptions) {
|
||||
var isOptional = testOptions !== undefined && testOptions.isOptional === true;
|
||||
var noReturn = testOptions !== undefined && testOptions.noReturn === true;
|
||||
var isILD = testOptions !== undefined && testOptions.isILD === true;
|
||||
|
||||
function addExtraOptions(options, value, testOptions) {
|
||||
if (testOptions !== undefined && testOptions.extra !== undefined) {
|
||||
var extra;
|
||||
if (value !== undefined && testOptions.extra[value] !== undefined) {
|
||||
extra = testOptions.extra[value];
|
||||
} else if (testOptions.extra.any !== undefined) {
|
||||
extra = testOptions.extra.any;
|
||||
}
|
||||
if (extra !== undefined) {
|
||||
Object.getOwnPropertyNames(extra).forEach(function (prop) {
|
||||
options[prop] = extra[prop];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testValues, options, obj, expected, actual, error;
|
||||
|
||||
// test that the specified values are accepted. Also add values that convert to specified values.
|
||||
if (type === "boolean") {
|
||||
if (values === undefined) {
|
||||
values = [true, false];
|
||||
}
|
||||
testValues = values.slice(0);
|
||||
testValues.push(888);
|
||||
testValues.push(0);
|
||||
} else if (type === "string") {
|
||||
testValues = values.slice(0);
|
||||
testValues.push({toString: function () { return values[0]; }});
|
||||
}
|
||||
testValues.forEach(function (value) {
|
||||
options = {};
|
||||
options[property] = value;
|
||||
addExtraOptions(options, value, testOptions);
|
||||
obj = new Constructor(undefined, options);
|
||||
if (noReturn) {
|
||||
if (obj.resolvedOptions().hasOwnProperty(property)) {
|
||||
$ERROR("Option property " + property + " is returned, but shouldn't be.");
|
||||
}
|
||||
} else {
|
||||
actual = obj.resolvedOptions()[property];
|
||||
if (isILD) {
|
||||
if (actual !== undefined && values.indexOf(actual) === -1) {
|
||||
$ERROR("Invalid value " + actual + " returned for property " + property + ".");
|
||||
}
|
||||
} else {
|
||||
if (type === "boolean") {
|
||||
expected = Boolean(value);
|
||||
} else if (type === "string") {
|
||||
expected = String(value);
|
||||
}
|
||||
if (actual !== expected && !(isOptional && actual === undefined)) {
|
||||
$ERROR("Option value " + value + " for property " + property +
|
||||
" was not accepted; got " + actual + " instead.");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// test that invalid values are rejected
|
||||
if (type === "string") {
|
||||
var invalidValues = ["invalidValue", -1, null];
|
||||
// assume that we won't have values in caseless scripts
|
||||
if (values[0].toUpperCase() !== values[0]) {
|
||||
invalidValues.push(values[0].toUpperCase());
|
||||
} else {
|
||||
invalidValues.push(values[0].toLowerCase());
|
||||
}
|
||||
invalidValues.forEach(function (value) {
|
||||
options = {};
|
||||
options[property] = value;
|
||||
addExtraOptions(options, value, testOptions);
|
||||
error = undefined;
|
||||
try {
|
||||
obj = new Constructor(undefined, options);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Invalid option value " + value + " for property " + property + " was not rejected.");
|
||||
} else if (error.name !== "RangeError") {
|
||||
$ERROR("Invalid option value " + value + " for property " + property + " was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// test that fallback value or another valid value is used if no options value is provided
|
||||
if (!noReturn) {
|
||||
options = {};
|
||||
addExtraOptions(options, undefined, testOptions);
|
||||
obj = new Constructor(undefined, options);
|
||||
actual = obj.resolvedOptions()[property];
|
||||
if (!(isOptional && actual === undefined)) {
|
||||
if (fallback !== undefined) {
|
||||
if (actual !== fallback) {
|
||||
$ERROR("Option fallback value " + fallback + " for property " + property +
|
||||
" was not used; got " + actual + " instead.");
|
||||
}
|
||||
} else {
|
||||
if (values.indexOf(actual) === -1 && !(isILD && actual === undefined)) {
|
||||
$ERROR("Invalid value " + actual + " returned for property " + property + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the named property of the given object has a valid value
|
||||
* and the default attributes of the properties of an object literal.
|
||||
* @param {Object} obj the object to be tested.
|
||||
* @param {string} property the name of the property
|
||||
* @param {Function|Array} valid either a function that tests value for validity and returns a boolean,
|
||||
* an array of valid values.
|
||||
* @exception if the property has an invalid value.
|
||||
*/
|
||||
function testProperty(obj, property, valid) {
|
||||
var desc = Object.getOwnPropertyDescriptor(obj, property);
|
||||
if (!desc.writable) {
|
||||
$ERROR("Property " + property + " must be writable.");
|
||||
}
|
||||
if (!desc.enumerable) {
|
||||
$ERROR("Property " + property + " must be enumerable.");
|
||||
}
|
||||
if (!desc.configurable) {
|
||||
$ERROR("Property " + property + " must be configurable.");
|
||||
}
|
||||
var value = desc.value;
|
||||
var isValid = (typeof valid === "function") ? valid(value) : (valid.indexOf(value) !== -1);
|
||||
if (!isValid) {
|
||||
$ERROR("Property value " + value + " is not allowed for property " + property + ".");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the named property of the given object, if present at all, has a valid value
|
||||
* and the default attributes of the properties of an object literal.
|
||||
* @param {Object} obj the object to be tested.
|
||||
* @param {string} property the name of the property
|
||||
* @param {Function|Array} valid either a function that tests value for validity and returns a boolean,
|
||||
* an array of valid values.
|
||||
* @exception if the property is present and has an invalid value.
|
||||
*/
|
||||
function mayHaveProperty(obj, property, valid) {
|
||||
if (obj.hasOwnProperty(property)) {
|
||||
testProperty(obj, property, valid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the given object has the named property with a valid value
|
||||
* and the default attributes of the properties of an object literal.
|
||||
* @param {Object} obj the object to be tested.
|
||||
* @param {string} property the name of the property
|
||||
* @param {Function|Array} valid either a function that tests value for validity and returns a boolean,
|
||||
* an array of valid values.
|
||||
* @exception if the property is missing or has an invalid value.
|
||||
*/
|
||||
function mustHaveProperty(obj, property, valid) {
|
||||
if (!obj.hasOwnProperty(property)) {
|
||||
$ERROR("Object is missing property " + property + ".");
|
||||
}
|
||||
testProperty(obj, property, valid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the given object does not have the named property.
|
||||
* @param {Object} obj the object to be tested.
|
||||
* @param {string} property the name of the property
|
||||
* @exception if the property is present.
|
||||
*/
|
||||
function mustNotHaveProperty(obj, property) {
|
||||
if (obj.hasOwnProperty(property)) {
|
||||
$ERROR("Object has property it mustn't have: " + property + ".");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether name is a valid BCP 47 numbering system name
|
||||
* and not excluded from use in the ECMAScript Internationalization API.
|
||||
* @param {string} name the name to be tested.
|
||||
* @return {boolean} whether name is a valid BCP 47 numbering system name and
|
||||
* allowed for use in the ECMAScript Internationalization API.
|
||||
*/
|
||||
|
||||
function isValidNumberingSystem(name) {
|
||||
|
||||
// source: CLDR file common/bcp47/number.xml; version CLDR 21.
|
||||
var numberingSystems = [
|
||||
"arab",
|
||||
"arabext",
|
||||
"armn",
|
||||
"armnlow",
|
||||
"bali",
|
||||
"beng",
|
||||
"brah",
|
||||
"cakm",
|
||||
"cham",
|
||||
"deva",
|
||||
"ethi",
|
||||
"finance",
|
||||
"fullwide",
|
||||
"geor",
|
||||
"grek",
|
||||
"greklow",
|
||||
"gujr",
|
||||
"guru",
|
||||
"hanidec",
|
||||
"hans",
|
||||
"hansfin",
|
||||
"hant",
|
||||
"hantfin",
|
||||
"hebr",
|
||||
"java",
|
||||
"jpan",
|
||||
"jpanfin",
|
||||
"kali",
|
||||
"khmr",
|
||||
"knda",
|
||||
"osma",
|
||||
"lana",
|
||||
"lanatham",
|
||||
"laoo",
|
||||
"latn",
|
||||
"lepc",
|
||||
"limb",
|
||||
"mlym",
|
||||
"mong",
|
||||
"mtei",
|
||||
"mymr",
|
||||
"mymrshan",
|
||||
"native",
|
||||
"nkoo",
|
||||
"olck",
|
||||
"orya",
|
||||
"roman",
|
||||
"romanlow",
|
||||
"saur",
|
||||
"shrd",
|
||||
"sora",
|
||||
"sund",
|
||||
"talu",
|
||||
"takr",
|
||||
"taml",
|
||||
"tamldec",
|
||||
"telu",
|
||||
"thai",
|
||||
"tibt",
|
||||
"traditio",
|
||||
"vaii"
|
||||
];
|
||||
|
||||
var excluded = [
|
||||
"finance",
|
||||
"native",
|
||||
"traditio"
|
||||
];
|
||||
|
||||
|
||||
return numberingSystems.indexOf(name) !== -1 && excluded.indexOf(name) === -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides the digits of numbering systems with simple digit mappings,
|
||||
* as specified in 11.3.2.
|
||||
*/
|
||||
|
||||
var numberingSystemDigits = {
|
||||
arab: "٠١٢٣٤٥٦٧٨٩",
|
||||
arabext: "۰۱۲۳۴۵۶۷۸۹",
|
||||
beng: "০১২৩৪৫৬৭৮৯",
|
||||
deva: "०१२३४५६७८९",
|
||||
fullwide: "0123456789",
|
||||
gujr: "૦૧૨૩૪૫૬૭૮૯",
|
||||
guru: "੦੧੨੩੪੫੬੭੮੯",
|
||||
hanidec: "〇一二三四五六七八九",
|
||||
khmr: "០១២៣៤៥៦៧៨៩",
|
||||
knda: "೦೧೨೩೪೫೬೭೮೯",
|
||||
laoo: "໐໑໒໓໔໕໖໗໘໙",
|
||||
latn: "0123456789",
|
||||
mlym: "൦൧൨൩൪൫൬൭൮൯",
|
||||
mong: "᠐᠑᠒᠓᠔᠕᠖᠗᠘᠙",
|
||||
mymr: "၀၁၂၃၄၅၆၇၈၉",
|
||||
orya: "୦୧୨୩୪୫୬୭୮୯",
|
||||
tamldec: "௦௧௨௩௪௫௬௭௮௯",
|
||||
telu: "౦౧౨౩౪౫౬౭౮౯",
|
||||
thai: "๐๑๒๓๔๕๖๗๘๙",
|
||||
tibt: "༠༡༢༣༤༥༦༧༨༩"
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tests that number formatting is handled correctly. The function checks that the
|
||||
* digit sequences in formatted output are as specified, converted to the
|
||||
* selected numbering system, and embedded in consistent localized patterns.
|
||||
* @param {Array} locales the locales to be tested.
|
||||
* @param {Array} numberingSystems the numbering systems to be tested.
|
||||
* @param {Object} options the options to pass to Intl.NumberFormat. Options
|
||||
* must include {useGrouping: false}, and must cause 1.1 to be formatted
|
||||
* pre- and post-decimal digits.
|
||||
* @param {Object} testData maps input data (in ES5 9.3.1 format) to expected output strings
|
||||
* in unlocalized format with Western digits.
|
||||
*/
|
||||
|
||||
function testNumberFormat(locales, numberingSystems, options, testData) {
|
||||
locales.forEach(function (locale) {
|
||||
numberingSystems.forEach(function (numbering) {
|
||||
var digits = numberingSystemDigits[numbering];
|
||||
var format = new Intl.NumberFormat([locale + "-u-nu-" + numbering], options);
|
||||
|
||||
function getPatternParts(positive) {
|
||||
var n = positive ? 1.1 : -1.1;
|
||||
var formatted = format.format(n);
|
||||
var oneoneRE = "([^" + digits + "]*)[" + digits + "]+([^" + digits + "]+)[" + digits + "]+([^" + digits + "]*)";
|
||||
var match = formatted.match(new RegExp(oneoneRE));
|
||||
if (match === null) {
|
||||
$ERROR("Unexpected formatted " + n + " for " +
|
||||
format.resolvedOptions().locale + " and options " +
|
||||
JSON.stringify(options) + ": " + formatted);
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
function toNumbering(raw) {
|
||||
return raw.replace(/[0-9]/g, function (digit) {
|
||||
return digits[digit.charCodeAt(0) - "0".charCodeAt(0)];
|
||||
});
|
||||
}
|
||||
|
||||
function buildExpected(raw, patternParts) {
|
||||
var period = raw.indexOf(".");
|
||||
if (period === -1) {
|
||||
return patternParts[1] + toNumbering(raw) + patternParts[3];
|
||||
} else {
|
||||
return patternParts[1] +
|
||||
toNumbering(raw.substring(0, period)) +
|
||||
patternParts[2] +
|
||||
toNumbering(raw.substring(period + 1)) +
|
||||
patternParts[3];
|
||||
}
|
||||
}
|
||||
|
||||
if (format.resolvedOptions().numberingSystem === numbering) {
|
||||
// figure out prefixes, infixes, suffixes for positive and negative values
|
||||
var posPatternParts = getPatternParts(true);
|
||||
var negPatternParts = getPatternParts(false);
|
||||
|
||||
Object.getOwnPropertyNames(testData).forEach(function (input) {
|
||||
var rawExpected = testData[input];
|
||||
var patternParts;
|
||||
if (rawExpected[0] === "-") {
|
||||
patternParts = negPatternParts;
|
||||
rawExpected = rawExpected.substring(1);
|
||||
} else {
|
||||
patternParts = posPatternParts;
|
||||
}
|
||||
var expected = buildExpected(rawExpected, patternParts);
|
||||
var actual = format.format(input);
|
||||
if (actual !== expected) {
|
||||
$ERROR("Formatted value for " + input + ", " +
|
||||
format.resolvedOptions().locale + " and options " +
|
||||
JSON.stringify(options) + " is " + actual + "; expected " + expected + ".");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the components of date-time formats.
|
||||
* @return {Array} an array with all date-time components.
|
||||
*/
|
||||
|
||||
function getDateTimeComponents() {
|
||||
return ["weekday", "era", "year", "month", "day", "hour", "minute", "second", "timeZoneName"];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the valid values for the given date-time component, as specified
|
||||
* by the table in section 12.1.1.
|
||||
* @param {string} component a date-time component.
|
||||
* @return {Array} an array with the valid values for the component.
|
||||
*/
|
||||
|
||||
function getDateTimeComponentValues(component) {
|
||||
|
||||
var components = {
|
||||
weekday: ["narrow", "short", "long"],
|
||||
era: ["narrow", "short", "long"],
|
||||
year: ["2-digit", "numeric"],
|
||||
month: ["2-digit", "numeric", "narrow", "short", "long"],
|
||||
day: ["2-digit", "numeric"],
|
||||
hour: ["2-digit", "numeric"],
|
||||
minute: ["2-digit", "numeric"],
|
||||
second: ["2-digit", "numeric"],
|
||||
timeZoneName: ["short", "long"]
|
||||
};
|
||||
|
||||
var result = components[component];
|
||||
if (result === undefined) {
|
||||
$ERROR("Internal error: No values defined for date-time component " + component + ".");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests that the given value is valid for the given date-time component.
|
||||
* @param {string} component a date-time component.
|
||||
* @param {string} value the value to be tested.
|
||||
* @return {boolean} true if the test succeeds.
|
||||
* @exception if the test fails.
|
||||
*/
|
||||
|
||||
function testValidDateTimeComponentValue(component, value) {
|
||||
if (getDateTimeComponentValues(component).indexOf(value) === -1) {
|
||||
$ERROR("Invalid value " + value + " for date-time component " + component + ".");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifies that the actual array matches the expected one in length, elements,
|
||||
* and element order.
|
||||
* @param {Array} expected the expected array.
|
||||
* @param {Array} actual the actual array.
|
||||
* @return {boolean} true if the test succeeds.
|
||||
* @exception if the test fails.
|
||||
*/
|
||||
function testArraysAreSame(expected, actual) {
|
||||
for (i = 0; i < Math.max(actual.length, expected.length); i++) {
|
||||
if (actual[i] !== expected[i]) {
|
||||
$ERROR("Result array element at index " + i + " should be \"" +
|
||||
expected[i] + "\" but is \"" + actual[i] + "\".");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
43
test/suite/intl402/ch10/10.1/10.1.1_1.js
Normal file
43
test/suite/intl402/ch10/10.1/10.1.1_1.js
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that an object can't be re-initialized as a Collator.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
testWithIntlConstructors(function (Constructor) {
|
||||
var obj, error;
|
||||
|
||||
// variant 1: use constructor in a "new" expression
|
||||
obj = new Constructor();
|
||||
try {
|
||||
Intl.Collator.call(obj);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Re-initializing object created with \"new\" as Collator was not rejected.");
|
||||
} else if (error.name !== "TypeError") {
|
||||
$ERROR("Re-initializing object created with \"new\" as Collator was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
|
||||
// variant 2: use constructor as a function
|
||||
obj = Constructor.call({});
|
||||
error = undefined;
|
||||
try {
|
||||
Intl.Collator.call(obj);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Re-initializing object created with constructor as function as Collator was not rejected.");
|
||||
} else if (error.name !== "TypeError") {
|
||||
$ERROR("Re-initializing object created with constructor as function as Collator was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
18
test/suite/intl402/ch10/10.1/10.1.1_10.js
Normal file
18
test/suite/intl402/ch10/10.1/10.1.1_10.js
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the behavior of a Record is not affected by adversarial
|
||||
* changes to Object.prototype.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
taintProperties(["localeMatcher", "kn", "kk", "kf"]);
|
||||
|
||||
var locale = new Intl.Collator(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale;
|
||||
if (!isCanonicalizedStructurallyValidLanguageTag(locale)) {
|
||||
$ERROR("Collator returns invalid locale " + locale + ".");
|
||||
}
|
||||
|
12
test/suite/intl402/ch10/10.1/10.1.1_11.js
Normal file
12
test/suite/intl402/ch10/10.1/10.1.1_11.js
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the option localeMatcher is processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
testOption(Intl.Collator, "localeMatcher", "string", ["lookup", "best fit"], "best fit", {noReturn: true});
|
||||
|
14
test/suite/intl402/ch10/10.1/10.1.1_13.js
Normal file
14
test/suite/intl402/ch10/10.1/10.1.1_13.js
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the options numeric, normalization, and caseFirst are processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
testOption(Intl.Collator, "numeric", "boolean", undefined, undefined, {isOptional: true});
|
||||
testOption(Intl.Collator, "normalization", "boolean", undefined, undefined, {isOptional: true});
|
||||
testOption(Intl.Collator, "caseFirst", "string", ["upper", "lower", "false"], undefined, {isOptional: true});
|
||||
|
44
test/suite/intl402/ch10/10.1/10.1.1_19_b.js
Normal file
44
test/suite/intl402/ch10/10.1/10.1.1_19_b.js
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests the special handling of the "co" key in Intl.Collator.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
function checkCollation(extensionCoValue, usageValue, expectedCollations, expectedUsage) {
|
||||
var requestLocale = extensionCoValue !== undefined ? "de-DE-u-co-" + extensionCoValue : "de-DE";
|
||||
var options = usageValue !== undefined ? { usage: usageValue } : undefined;
|
||||
var collator = new Intl.Collator([requestLocale], options);
|
||||
|
||||
var collation = collator.resolvedOptions().collation;
|
||||
if (expectedCollations.indexOf(collation) === -1) {
|
||||
$ERROR((extensionCoValue === undefined ? "Default collation" : "Collation for \"" + extensionCoValue) +
|
||||
"\" should be " + expectedCollations.join(" or ") + ", but is " + collation + ".");
|
||||
}
|
||||
|
||||
var usage = collator.resolvedOptions().usage;
|
||||
if (expectedUsage !== usage) {
|
||||
$ERROR((usageValue === undefined ? "Default usage" : "Usage") +
|
||||
" should be " + expectedUsage + ", but is " + usage + ".");
|
||||
}
|
||||
}
|
||||
|
||||
checkCollation(undefined, undefined, ["default"], "sort");
|
||||
|
||||
checkCollation("phonebk", undefined, ["phonebk", "default"], "sort");
|
||||
|
||||
checkCollation("invalid", undefined, ["default"], "sort");
|
||||
|
||||
checkCollation("standard", undefined, ["default"], "sort");
|
||||
|
||||
checkCollation("standard", "search", ["default"], "search");
|
||||
|
||||
checkCollation("standard", "sort", ["default"], "sort");
|
||||
|
||||
checkCollation("search", undefined, ["default"], "sort");
|
||||
|
||||
checkCollation("search", "search", ["default"], "search");
|
||||
|
||||
checkCollation("search", "sort", ["default"], "sort");
|
||||
|
64
test/suite/intl402/ch10/10.1/10.1.1_19_c.js
Normal file
64
test/suite/intl402/ch10/10.1/10.1.1_19_c.js
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the options numeric, normalization, and caseFirst can be
|
||||
* set through either the locale or the options.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var options = [
|
||||
{key: "kn", property: "numeric", type: "boolean", values: [true, false]},
|
||||
{key: "kk", property: "normalization", type: "boolean", values: [true, false]},
|
||||
{key: "kf", property: "caseFirst", type: "string", values: ["upper", "lower", "false"]}
|
||||
];
|
||||
|
||||
options.forEach(function (option) {
|
||||
var defaultLocale = new Intl.Collator().resolvedOptions().locale;
|
||||
var collator, opt, result;
|
||||
|
||||
// find out which values are supported for a property in the default locale
|
||||
var supportedValues = [];
|
||||
option.values.forEach(function (value) {
|
||||
opt = {};
|
||||
opt[option.property] = value;
|
||||
collator = new Intl.Collator([defaultLocale], opt);
|
||||
result = collator.resolvedOptions()[option.property];
|
||||
if (result !== undefined && supportedValues.indexOf(result) === -1) {
|
||||
supportedValues.push(result);
|
||||
}
|
||||
});
|
||||
|
||||
// verify that the supported values can also be set through the locale
|
||||
supportedValues.forEach(function (value) {
|
||||
collator = new Intl.Collator([defaultLocale + "-u-" + option.key + "-" + value]);
|
||||
result = collator.resolvedOptions()[option.property];
|
||||
if (result !== value) {
|
||||
$ERROR("Property " + option.property + " couldn't be set through locale extension key " +
|
||||
option.key + "; requested value: " + value + "; actual value: " + result + ".");
|
||||
}
|
||||
});
|
||||
|
||||
// verify that the options setting overrides the locale setting
|
||||
supportedValues.forEach(function (value) {
|
||||
var otherValue;
|
||||
option.values.forEach(function (possibleValue) {
|
||||
if (possibleValue !== value) {
|
||||
otherValue = possibleValue;
|
||||
}
|
||||
});
|
||||
if (otherValue !== undefined) {
|
||||
opt = {};
|
||||
opt[option.property] = value;
|
||||
collator = new Intl.Collator([defaultLocale + "-u-" + option.key + "-" + otherValue], opt);
|
||||
result = collator.resolvedOptions()[option.property];
|
||||
if (result !== value) {
|
||||
$ERROR("Options value for property " + option.property + " doesn't override locale extension key " +
|
||||
option.key + "; requested value: " + value + "; actual value: " + result + ".");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
13
test/suite/intl402/ch10/10.1/10.1.1_20.js
Normal file
13
test/suite/intl402/ch10/10.1/10.1.1_20.js
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the option sensitivity is processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
// the fallback is variant only for usage === sort, but that happens to be the fallback for usage
|
||||
testOption(Intl.Collator, "sensitivity", "string", ["base", "accent", "case", "variant"], "variant");
|
||||
|
13
test/suite/intl402/ch10/10.1/10.1.1_23.js
Normal file
13
test/suite/intl402/ch10/10.1/10.1.1_23.js
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the option ignorePunctuation is processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
// the fallback is variant only for usage === sort, but that happens to be the fallback for usage
|
||||
testOption(Intl.Collator, "ignorePunctuation", "boolean", undefined, false);
|
||||
|
12
test/suite/intl402/ch10/10.1/10.1.1_6.js
Normal file
12
test/suite/intl402/ch10/10.1/10.1.1_6.js
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the option usage is processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
testOption(Intl.Collator, "usage", "string", ["sort", "search"], "sort");
|
||||
|
30
test/suite/intl402/ch10/10.1/10.1.2_a.js
Normal file
30
test/suite/intl402/ch10/10.1/10.1.2_a.js
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.Collator can be subclassed.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
// get a collator and have it sort an array for comparison with the subclass
|
||||
var locales = ["tlh", "id", "en"];
|
||||
var a = ["A", "C", "E", "B", "D", "F"];
|
||||
var referenceCollator = new Intl.Collator(locales);
|
||||
var referenceSorted = a.slice().sort(referenceCollator.compare);
|
||||
|
||||
function MyCollator(locales, options) {
|
||||
Intl.Collator.call(this, locales, options);
|
||||
// could initialize MyCollator properties
|
||||
}
|
||||
|
||||
MyCollator.prototype = Object.create(Intl.Collator.prototype);
|
||||
MyCollator.prototype.constructor = MyCollator;
|
||||
// could add methods to MyCollator.prototype
|
||||
|
||||
var collator = new MyCollator(locales);
|
||||
a.sort(collator.compare);
|
||||
testArraysAreSame(referenceSorted, a);
|
||||
|
19
test/suite/intl402/ch10/10.1/10.1.3.js
Normal file
19
test/suite/intl402/ch10/10.1/10.1.3.js
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that objects constructed by Intl.Collator have the specified internal properties.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var obj = new Intl.Collator();
|
||||
|
||||
var actualPrototype = Object.getPrototypeOf(obj);
|
||||
if (actualPrototype !== Intl.Collator.prototype) {
|
||||
$ERROR("Prototype of object constructed by Intl.Collator isn't Intl.Collator.prototype; got " + actualPrototype);
|
||||
}
|
||||
|
||||
if (!Object.isExtensible(obj)) {
|
||||
$ERROR("Object constructed by Intl.Collator must be extensible.");
|
||||
}
|
||||
|
22
test/suite/intl402/ch10/10.2/10.2.1.js
Normal file
22
test/suite/intl402/ch10/10.2/10.2.1.js
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.Collator.prototype has the required attributes.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var desc = Object.getOwnPropertyDescriptor(Intl.Collator, "prototype");
|
||||
if (desc === undefined) {
|
||||
$ERROR("Intl.Collator.prototype is not defined.");
|
||||
}
|
||||
if (desc.writable) {
|
||||
$ERROR("Intl.Collator.prototype must not be writable.");
|
||||
}
|
||||
if (desc.enumerable) {
|
||||
$ERROR("Intl.Collator.prototype must not be enumerable.");
|
||||
}
|
||||
if (desc.configurable) {
|
||||
$ERROR("Intl.Collator.prototype must not be configurable.");
|
||||
}
|
||||
|
47
test/suite/intl402/ch10/10.2/10.2.3_b.js
Normal file
47
test/suite/intl402/ch10/10.2/10.2.3_b.js
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.Collator does not accept Unicode locale
|
||||
* extension keys and values that are not allowed.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var defaultCollator = new Intl.Collator();
|
||||
var defaultOptions = defaultCollator.resolvedOptions();
|
||||
var defaultOptionsJSON = JSON.stringify(defaultOptions);
|
||||
var defaultLocale = defaultOptions.locale;
|
||||
var defaultSortedArray = ["hello", "你好", "こんにちは", "pêche", "peché", "9", "10"].sort(defaultCollator.compare);
|
||||
|
||||
|
||||
var keyValues = {
|
||||
"co": ["standard", "search", "invalid"],
|
||||
"ka": ["noignore", "shifted", "invalid"],
|
||||
"kb": ["true", "false", "invalid"],
|
||||
"kc": ["true", "false", "invalid"],
|
||||
"kh": ["true", "false", "invalid"],
|
||||
"kr": ["latn-hira-hani", "hani-hira-latn", "invalid"],
|
||||
"ks": ["level1", "level2", "level3", "level4", "identic", "invalid"],
|
||||
"vt": ["1234-5678-9abc-edf0", "invalid"]
|
||||
};
|
||||
|
||||
var testArray = defaultSortedArray.slice(0);
|
||||
|
||||
Object.getOwnPropertyNames(keyValues).forEach(function (key) {
|
||||
keyValues[key].forEach(function (value) {
|
||||
var collator = new Intl.Collator([defaultLocale + "-u-" + key + "-" + value]);
|
||||
var options = collator.resolvedOptions();
|
||||
if (options.locale !== defaultLocale) {
|
||||
$ERROR("Locale " + options.locale + " is affected by key " +
|
||||
key + "; value " + value + ".");
|
||||
}
|
||||
if (JSON.stringify(options) !== defaultOptionsJSON) {
|
||||
$ERROR("Resolved options " + JSON.stringify(options) + " are affected by key " +
|
||||
key + "; value " + value + ".");
|
||||
}
|
||||
testArraysAreSame(defaultSortedArray, testArray.sort(collator.compare));
|
||||
});
|
||||
});
|
||||
|
36
test/suite/intl402/ch10/10.3/10.3.2_1_c.js
Normal file
36
test/suite/intl402/ch10/10.3/10.3.2_1_c.js
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that compare function is bound to its Intl.Collator.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var strings = ["d", "O", "od", "oe", "of", "ö", "o\u0308", "X", "y", "Z", "Z.", "\uD842\uDFB7野家", "吉野家", "!A", "A", "b", "C"];
|
||||
var locales = [undefined, ["de"], ["de-u-co-phonebk"], ["en"], ["ja"], ["sv"]];
|
||||
var options = [
|
||||
undefined,
|
||||
{usage: "search"},
|
||||
{sensitivity: "base", ignorePunctuation: true}
|
||||
];
|
||||
|
||||
locales.forEach(function (locales) {
|
||||
options.forEach(function (options) {
|
||||
var collatorObj = new Intl.Collator(locales, options);
|
||||
var compareFunc = collatorObj.compare;
|
||||
var referenceSorted = strings.slice();
|
||||
referenceSorted.sort(function (a, b) { return collatorObj.compare(a, b); });
|
||||
var sorted = strings;
|
||||
sorted.sort(compareFunc);
|
||||
try {
|
||||
testArraysAreSame(referenceSorted, sorted);
|
||||
} catch (e) {
|
||||
e.message += " (Testing with locales " + locales + "; options " +
|
||||
(options ? JSON.stringify(options) : options) + ".)";
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
56
test/suite/intl402/ch10/10.3/10.3.2_CS_a.js
Normal file
56
test/suite/intl402/ch10/10.3/10.3.2_CS_a.js
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2012 Norbert Lindenberg. All rights reserved.
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the function returned by Intl.Collator.prototype.compare
|
||||
* returns 0 when comparing Strings that are considered canonically equivalent
|
||||
* by the Unicode standard.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var collator = new Intl.Collator();
|
||||
var 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", "北"]
|
||||
|
||||
];
|
||||
var i;
|
||||
for (i = 0; i < pairs.length; i++) {
|
||||
var pair = pairs[i];
|
||||
if (collator.compare(pair[0], pair[1]) !== 0) {
|
||||
$ERROR("Collator.compare considers " + pair[0] + " ≠ " + pair[1] + ".");
|
||||
}
|
||||
}
|
||||
|
22
test/suite/intl402/ch10/10.3/10.3.2_CS_b_NN.js
Normal file
22
test/suite/intl402/ch10/10.3/10.3.2_CS_b_NN.js
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the compare function isn't entirely unreasonable.
|
||||
* This test is not normative.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
// this test should be valid at least for the following locales
|
||||
var locales = ["de", "en", "es", "fr", "it"];
|
||||
locales = Intl.Collator.supportedLocalesOf(locales, {localeMatcher: "lookup"});
|
||||
locales.forEach(function (locale) {
|
||||
var collator = new Intl.Collator([locale], {sensitivity: "variant", localeMatcher: "lookup"});
|
||||
var a = ["L", "X", "C", "k", "Z", "H", "d", "m", "w", "A", "i", "f", "y", "E", "N", "V", "g", "J", "b"];
|
||||
a.sort(collator.compare);
|
||||
var expected = ["A", "b", "C", "d", "E", "f", "g", "H", "i", "J", "k", "L", "m", "N", "V", "w", "X", "y", "Z"];
|
||||
testArraysAreSame(expected, a);
|
||||
});
|
||||
|
22
test/suite/intl402/ch10/10.3/10.3.2_CS_c_NN.js
Normal file
22
test/suite/intl402/ch10/10.3/10.3.2_CS_c_NN.js
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the compare function supports phonebook sorting if it says it does.
|
||||
* This test is not normative.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
// this test should be valid at least for the following locales
|
||||
var locales = ["de-DE-u-co-phonebk", "de-u-co-phonebk"];
|
||||
var collator = new Intl.Collator(locales, {localeMatcher: "lookup"});
|
||||
if (locales.indexOf(collator.resolvedOptions().locale) !== -1) {
|
||||
var a = ["A", "b", "Af", "Ab", "od", "off", "Ä", "ö"];
|
||||
a.sort(collator.compare);
|
||||
var expected = ["A", "Ab", "Ä", "Af", "b", "od", "ö", "off"];
|
||||
testArraysAreSame(expected, a);
|
||||
}
|
||||
|
34
test/suite/intl402/ch10/10.3/10.3.2_CS_d_NN.js
Normal file
34
test/suite/intl402/ch10/10.3/10.3.2_CS_d_NN.js
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the compare function supports different sensitivity settings.
|
||||
* This test is not normative.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
// this test should be valid at least for the following locales
|
||||
var locales = ["de", "en", "es", "it"];
|
||||
locales = Intl.Collator.supportedLocalesOf(locales, {localeMatcher: "lookup"});
|
||||
locales.forEach(function (locale) {
|
||||
var target = "Aa";
|
||||
var input = ["Aa", "bA", "E", "b", "aA", "fC", "áÁ", "Aã"];
|
||||
var expected = {
|
||||
"base": ["Aa", "aA", "áÁ", "Aã"],
|
||||
"accent": ["Aa", "aA"],
|
||||
"case": ["Aa", "Aã"],
|
||||
"variant": ["Aa"]
|
||||
};
|
||||
Object.getOwnPropertyNames(expected).forEach(function (sensitivity) {
|
||||
var collator = new Intl.Collator([locale], {usage: "search",
|
||||
sensitivity: sensitivity, localeMatcher: "lookup"});
|
||||
var matches = input.filter(function (v) {
|
||||
return collator.compare(v, target) === 0;
|
||||
});
|
||||
testArraysAreSame(expected[sensitivity], matches);
|
||||
});
|
||||
});
|
||||
|
48
test/suite/intl402/ch10/10.3/10.3.3.js
Normal file
48
test/suite/intl402/ch10/10.3/10.3.3.js
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the object returned by Intl.Collator.prototype.resolvedOptions
|
||||
* has the right properties.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var actual = new Intl.Collator().resolvedOptions();
|
||||
|
||||
var actual2 = new Intl.Collator().resolvedOptions();
|
||||
if (actual2 === actual) {
|
||||
$ERROR("resolvedOptions returned the same object twice.");
|
||||
}
|
||||
|
||||
// source: CLDR file common/bcp47/collation.xml; version CLDR 21.
|
||||
var collations = [
|
||||
"default", // added
|
||||
"big5han",
|
||||
"dict",
|
||||
"direct",
|
||||
"ducet",
|
||||
"gb2312",
|
||||
"phonebk",
|
||||
"phonetic",
|
||||
"pinyin",
|
||||
"reformed",
|
||||
// "search", // excluded
|
||||
"searchjl",
|
||||
// "standard", // excluded
|
||||
"stroke",
|
||||
"trad",
|
||||
"unihan"
|
||||
];
|
||||
|
||||
// this assumes the default values where the specification provides them
|
||||
mustHaveProperty(actual, "locale", isCanonicalizedStructurallyValidLanguageTag);
|
||||
mustHaveProperty(actual, "usage", ["sort"]);
|
||||
mustHaveProperty(actual, "sensitivity", ["variant"]);
|
||||
mustHaveProperty(actual, "ignorePunctuation", [false]);
|
||||
mustHaveProperty(actual, "collation", collations);
|
||||
mayHaveProperty(actual, "numeric", [true, false]);
|
||||
mayHaveProperty(actual, "normalization", [true, false]);
|
||||
mayHaveProperty(actual, "caseFirst", ["upper", "lower", "false"]);
|
||||
|
33
test/suite/intl402/ch10/10.3/10.3_b.js
Normal file
33
test/suite/intl402/ch10/10.3/10.3_b.js
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.Collator.prototype functions throw a
|
||||
* TypeError if called on a non-object value or an object that hasn't been
|
||||
* initialized as a Collator.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var functions = {
|
||||
"compare getter": Object.getOwnPropertyDescriptor(Intl.Collator.prototype, "compare").get,
|
||||
resolvedOptions: Intl.Collator.prototype.resolvedOptions
|
||||
};
|
||||
var invalidTargets = [undefined, null, true, 0, "Collator", [], {}];
|
||||
|
||||
Object.getOwnPropertyNames(functions).forEach(function (functionName) {
|
||||
var f = functions[functionName];
|
||||
invalidTargets.forEach(function (target) {
|
||||
var error;
|
||||
try {
|
||||
f.call(target);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Calling " + functionName + " on " + target + " was not rejected.");
|
||||
} else if (error.name !== "TypeError") {
|
||||
$ERROR("Calling " + functionName + " on " + target + " was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
15
test/suite/intl402/ch10/10.4/10.4_a.js
Normal file
15
test/suite/intl402/ch10/10.4/10.4_a.js
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.Collator instances have the specified properties.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var obj = new Intl.Collator();
|
||||
|
||||
var toStringValue = Object.prototype.toString.call(obj);
|
||||
if (toStringValue !== "[object Object]") {
|
||||
$ERROR("Intl.Collator instance produces wrong [[Class]] - toString returns " + toStringValue + ".");
|
||||
}
|
||||
|
43
test/suite/intl402/ch11/11.1/11.1.1_1.js
Normal file
43
test/suite/intl402/ch11/11.1/11.1.1_1.js
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that an object can't be re-initialized as a NumberFormat.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
testWithIntlConstructors(function (Constructor) {
|
||||
var obj, error;
|
||||
|
||||
// variant 1: use constructor in a "new" expression
|
||||
obj = new Constructor();
|
||||
try {
|
||||
Intl.NumberFormat.call(obj);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Re-initializing object created with \"new\" as NumberFormat was not rejected.");
|
||||
} else if (error.name !== "TypeError") {
|
||||
$ERROR("Re-initializing object created with \"new\" as NumberFormat was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
|
||||
// variant 2: use constructor as a function
|
||||
obj = Constructor.call({});
|
||||
error = undefined;
|
||||
try {
|
||||
Intl.NumberFormat.call(obj);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Re-initializing object created with constructor as function as NumberFormat was not rejected.");
|
||||
} else if (error.name !== "TypeError") {
|
||||
$ERROR("Re-initializing object created with constructor as function as NumberFormat was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
13
test/suite/intl402/ch11/11.1/11.1.1_15.js
Normal file
13
test/suite/intl402/ch11/11.1/11.1.1_15.js
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the option style is processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
testOption(Intl.NumberFormat, "style", "string", ["decimal", "percent", "currency"], "decimal",
|
||||
{extra: {"currency": {currency: "CNY"}}});
|
||||
|
81
test/suite/intl402/ch11/11.1/11.1.1_17.js
Normal file
81
test/suite/intl402/ch11/11.1/11.1.1_17.js
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the option currency is processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var validValues = ["CNY", "USD", "EUR", "IDR", "jpy", {toString: function () {return "INR";}}];
|
||||
var invalidValues = ["$", "SFr.", "US$", "ßP", {toString: function () {return;}}];
|
||||
|
||||
var defaultLocale = new Intl.NumberFormat().resolvedOptions().locale;
|
||||
|
||||
validValues.forEach(function (value) {
|
||||
var format, actual, expected;
|
||||
|
||||
// with currency style, we should get the upper case form back
|
||||
format = new Intl.NumberFormat([defaultLocale], {style: "currency", currency: value});
|
||||
actual = format.resolvedOptions().currency;
|
||||
expected = value.toString().toUpperCase();
|
||||
if (actual !== expected) {
|
||||
$ERROR("Incorrect resolved currency with currency style - expected " +
|
||||
expected + "; got " + actual + ".");
|
||||
}
|
||||
|
||||
// without currency style, we shouldn't get any currency back
|
||||
format = new Intl.NumberFormat([defaultLocale], {currency: value});
|
||||
actual = format.resolvedOptions().currency;
|
||||
expected = undefined;
|
||||
if (actual !== expected) {
|
||||
$ERROR("Incorrect resolved currency with non-currency style - expected " +
|
||||
expected + "; got " + actual + ".");
|
||||
}
|
||||
|
||||
// currencies specified through the locale must be ignored
|
||||
format = new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {style: "currency", currency: value});
|
||||
actual = format.resolvedOptions().currency;
|
||||
expected = value.toString().toUpperCase();
|
||||
if (actual !== expected) {
|
||||
$ERROR("Incorrect resolved currency with -u-cu- and currency style - expected " +
|
||||
expected + "; got " + actual + ".");
|
||||
}
|
||||
|
||||
format = new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {currency: value});
|
||||
actual = format.resolvedOptions().currency;
|
||||
expected = undefined;
|
||||
if (actual !== expected) {
|
||||
$ERROR("Incorrect resolved currency with -u-cu- and non-currency style - expected " +
|
||||
expected + "; got " + actual + ".");
|
||||
}
|
||||
});
|
||||
|
||||
invalidValues.forEach(function (value) {
|
||||
function expectError(f) {
|
||||
var error;
|
||||
try {
|
||||
f();
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Invalid currency value " + value + " was not rejected.");
|
||||
} else if (error.name !== "RangeError") {
|
||||
$ERROR("Invalid currency value " + value + " was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
}
|
||||
|
||||
expectError(function () {
|
||||
return new Intl.NumberFormat([defaultLocale], {style: "currency", currency: value});
|
||||
});
|
||||
expectError(function () {
|
||||
return new Intl.NumberFormat([defaultLocale], {currency: value});
|
||||
});
|
||||
expectError(function () {
|
||||
return new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {style: "currency", currency: value});
|
||||
});
|
||||
expectError(function () {
|
||||
return new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {currency: value});
|
||||
});
|
||||
});
|
||||
|
31
test/suite/intl402/ch11/11.1/11.1.1_19.js
Normal file
31
test/suite/intl402/ch11/11.1/11.1.1_19.js
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the currency style can not be used without a specified currency.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var defaultLocale = new Intl.NumberFormat().resolvedOptions().locale;
|
||||
|
||||
function expectError(f) {
|
||||
var error;
|
||||
try {
|
||||
f();
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Invalid currency value " + value + " was not rejected.");
|
||||
} else if (error.name !== "TypeError") {
|
||||
$ERROR("Invalid currency value " + value + " was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
}
|
||||
|
||||
expectError(function () {
|
||||
return new Intl.NumberFormat([defaultLocale], {style: "currency"});
|
||||
});
|
||||
expectError(function () {
|
||||
return new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {style: "currency"});
|
||||
});
|
||||
|
196
test/suite/intl402/ch11/11.1/11.1.1_20_c.js
Normal file
196
test/suite/intl402/ch11/11.1/11.1.1_20_c.js
Normal file
@ -0,0 +1,196 @@
|
||||
// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the number of fractional digits is determined correctly for currencies.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
// data from http://www.currency-iso.org/dl_iso_table_a1.xml, 2012-08-10
|
||||
var currencyDigits = {
|
||||
AED: 2,
|
||||
AFN: 2,
|
||||
ALL: 2,
|
||||
AMD: 2,
|
||||
ANG: 2,
|
||||
AOA: 2,
|
||||
ARS: 2,
|
||||
AUD: 2,
|
||||
AWG: 2,
|
||||
AZN: 2,
|
||||
BAM: 2,
|
||||
BBD: 2,
|
||||
BDT: 2,
|
||||
BGN: 2,
|
||||
BHD: 3,
|
||||
BIF: 0,
|
||||
BMD: 2,
|
||||
BND: 2,
|
||||
BOB: 2,
|
||||
BOV: 2,
|
||||
BRL: 2,
|
||||
BSD: 2,
|
||||
BTN: 2,
|
||||
BWP: 2,
|
||||
BYR: 0,
|
||||
BZD: 2,
|
||||
CAD: 2,
|
||||
CDF: 2,
|
||||
CHE: 2,
|
||||
CHF: 2,
|
||||
CHW: 2,
|
||||
CLF: 0,
|
||||
CLP: 0,
|
||||
CNY: 2,
|
||||
COP: 2,
|
||||
COU: 2,
|
||||
CRC: 2,
|
||||
CUC: 2,
|
||||
CUP: 2,
|
||||
CVE: 2,
|
||||
CZK: 2,
|
||||
DJF: 0,
|
||||
DKK: 2,
|
||||
DOP: 2,
|
||||
DZD: 2,
|
||||
EGP: 2,
|
||||
ERN: 2,
|
||||
ETB: 2,
|
||||
EUR: 2,
|
||||
FJD: 2,
|
||||
FKP: 2,
|
||||
GBP: 2,
|
||||
GEL: 2,
|
||||
GHS: 2,
|
||||
GIP: 2,
|
||||
GMD: 2,
|
||||
GNF: 0,
|
||||
GTQ: 2,
|
||||
GYD: 2,
|
||||
HKD: 2,
|
||||
HNL: 2,
|
||||
HRK: 2,
|
||||
HTG: 2,
|
||||
HUF: 2,
|
||||
IDR: 2,
|
||||
ILS: 2,
|
||||
INR: 2,
|
||||
IQD: 3,
|
||||
IRR: 2,
|
||||
ISK: 0,
|
||||
JMD: 2,
|
||||
JOD: 3,
|
||||
JPY: 0,
|
||||
KES: 2,
|
||||
KGS: 2,
|
||||
KHR: 2,
|
||||
KMF: 0,
|
||||
KPW: 2,
|
||||
KRW: 0,
|
||||
KWD: 3,
|
||||
KYD: 2,
|
||||
KZT: 2,
|
||||
LAK: 2,
|
||||
LBP: 2,
|
||||
LKR: 2,
|
||||
LRD: 2,
|
||||
LSL: 2,
|
||||
LTL: 2,
|
||||
LVL: 2,
|
||||
LYD: 3,
|
||||
MAD: 2,
|
||||
MDL: 2,
|
||||
MGA: 2,
|
||||
MKD: 2,
|
||||
MMK: 2,
|
||||
MNT: 2,
|
||||
MOP: 2,
|
||||
MRO: 2,
|
||||
MUR: 2,
|
||||
MVR: 2,
|
||||
MWK: 2,
|
||||
MXN: 2,
|
||||
MXV: 2,
|
||||
MYR: 2,
|
||||
MZN: 2,
|
||||
NAD: 2,
|
||||
NGN: 2,
|
||||
NIO: 2,
|
||||
NOK: 2,
|
||||
NPR: 2,
|
||||
NZD: 2,
|
||||
OMR: 3,
|
||||
PAB: 2,
|
||||
PEN: 2,
|
||||
PGK: 2,
|
||||
PHP: 2,
|
||||
PKR: 2,
|
||||
PLN: 2,
|
||||
PYG: 0,
|
||||
QAR: 2,
|
||||
RON: 2,
|
||||
RSD: 2,
|
||||
RUB: 2,
|
||||
RWF: 0,
|
||||
SAR: 2,
|
||||
SBD: 2,
|
||||
SCR: 2,
|
||||
SDG: 2,
|
||||
SEK: 2,
|
||||
SGD: 2,
|
||||
SHP: 2,
|
||||
SLL: 2,
|
||||
SOS: 2,
|
||||
SRD: 2,
|
||||
SSP: 2,
|
||||
STD: 2,
|
||||
SVC: 2,
|
||||
SYP: 2,
|
||||
SZL: 2,
|
||||
THB: 2,
|
||||
TJS: 2,
|
||||
TMT: 2,
|
||||
TND: 3,
|
||||
TOP: 2,
|
||||
TRY: 2,
|
||||
TTD: 2,
|
||||
TWD: 2,
|
||||
TZS: 2,
|
||||
UAH: 2,
|
||||
UGX: 2,
|
||||
USD: 2,
|
||||
USN: 2,
|
||||
USS: 2,
|
||||
UYI: 0,
|
||||
UYU: 2,
|
||||
UZS: 2,
|
||||
VEF: 2,
|
||||
VND: 0,
|
||||
VUV: 0,
|
||||
WST: 2,
|
||||
XAF: 0,
|
||||
XCD: 2,
|
||||
XOF: 0,
|
||||
XPF: 0,
|
||||
YER: 2,
|
||||
ZAR: 2,
|
||||
ZMK: 2,
|
||||
ZWL: 2
|
||||
};
|
||||
|
||||
Object.getOwnPropertyNames(currencyDigits).forEach(function (currency) {
|
||||
var digits = currencyDigits[currency];
|
||||
format = Intl.NumberFormat([], {style: "currency", currency: currency});
|
||||
var min = format.resolvedOptions().minimumFractionDigits;
|
||||
var max = format.resolvedOptions().maximumFractionDigits;
|
||||
if (min !== digits) {
|
||||
$ERROR("Didn't get correct minimumFractionDigits for currency " +
|
||||
currency + "; expected " + digits + ", got " + min + ".");
|
||||
}
|
||||
if (max !== digits) {
|
||||
$ERROR("Didn't get correct maximumFractionDigits for currency " +
|
||||
currency + "; expected " + digits + ", got " + max + ".");
|
||||
}
|
||||
});
|
||||
|
15
test/suite/intl402/ch11/11.1/11.1.1_21.js
Normal file
15
test/suite/intl402/ch11/11.1/11.1.1_21.js
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the option currencyDisplay is processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
testOption(Intl.NumberFormat, "currencyDisplay", "string", ["code", "symbol", "name"],
|
||||
"symbol", {extra: {any: {style: "currency", currency: "XDR"}}});
|
||||
testOption(Intl.NumberFormat, "currencyDisplay", "string", ["code", "symbol", "name"],
|
||||
undefined, {noReturn: true});
|
||||
|
12
test/suite/intl402/ch11/11.1/11.1.1_34.js
Normal file
12
test/suite/intl402/ch11/11.1/11.1.1_34.js
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the option useGrouping is processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
testOption(Intl.NumberFormat, "useGrouping", "boolean", undefined, true);
|
||||
|
18
test/suite/intl402/ch11/11.1/11.1.1_6.js
Normal file
18
test/suite/intl402/ch11/11.1/11.1.1_6.js
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the behavior of a Record is not affected by adversarial
|
||||
* changes to Object.prototype.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
taintProperties(["localeMatcher"]);
|
||||
|
||||
var locale = new Intl.NumberFormat(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale;
|
||||
if (!isCanonicalizedStructurallyValidLanguageTag(locale)) {
|
||||
$ERROR("NumberFormat returns invalid locale " + locale + ".");
|
||||
}
|
||||
|
12
test/suite/intl402/ch11/11.1/11.1.1_7.js
Normal file
12
test/suite/intl402/ch11/11.1/11.1.1_7.js
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the option localeMatcher is processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
testOption(Intl.NumberFormat, "localeMatcher", "string", ["lookup", "best fit"], "best fit", {noReturn: true});
|
||||
|
30
test/suite/intl402/ch11/11.1/11.1.2.js
Normal file
30
test/suite/intl402/ch11/11.1/11.1.2.js
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.NumberFormat can be subclassed.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
// get a number format and have it format an array of numbers for comparison with the subclass
|
||||
var locales = ["tlh", "id", "en"];
|
||||
var a = [0, 1, -1, -123456.789, -Infinity, NaN];
|
||||
var referenceNumberFormat = new Intl.NumberFormat(locales);
|
||||
var referenceFormatted = a.map(referenceNumberFormat.format);
|
||||
|
||||
function MyNumberFormat(locales, options) {
|
||||
Intl.NumberFormat.call(this, locales, options);
|
||||
// could initialize MyNumberFormat properties
|
||||
}
|
||||
|
||||
MyNumberFormat.prototype = Object.create(Intl.NumberFormat.prototype);
|
||||
MyNumberFormat.prototype.constructor = MyNumberFormat;
|
||||
// could add methods to MyNumberFormat.prototype
|
||||
|
||||
var format = new MyNumberFormat(locales);
|
||||
var actual = a.map(format.format);
|
||||
testArraysAreSame(referenceFormatted, actual);
|
||||
|
19
test/suite/intl402/ch11/11.1/11.1.3.js
Normal file
19
test/suite/intl402/ch11/11.1/11.1.3.js
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that objects constructed by Intl.NumberFormat have the specified internal properties.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var obj = new Intl.NumberFormat();
|
||||
|
||||
var actualPrototype = Object.getPrototypeOf(obj);
|
||||
if (actualPrototype !== Intl.NumberFormat.prototype) {
|
||||
$ERROR("Prototype of object constructed by Intl.NumberFormat isn't Intl.NumberFormat.prototype; got " + actualPrototype);
|
||||
}
|
||||
|
||||
if (!Object.isExtensible(obj)) {
|
||||
$ERROR("Object constructed by Intl.NumberFormat must be extensible.");
|
||||
}
|
||||
|
22
test/suite/intl402/ch11/11.2/11.2.1.js
Normal file
22
test/suite/intl402/ch11/11.2/11.2.1.js
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.NumberFormat.prototype has the required attributes.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var desc = Object.getOwnPropertyDescriptor(Intl.NumberFormat, "prototype");
|
||||
if (desc === undefined) {
|
||||
$ERROR("Intl.NumberFormat.prototype is not defined.");
|
||||
}
|
||||
if (desc.writable) {
|
||||
$ERROR("Intl.NumberFormat.prototype must not be writable.");
|
||||
}
|
||||
if (desc.enumerable) {
|
||||
$ERROR("Intl.NumberFormat.prototype must not be enumerable.");
|
||||
}
|
||||
if (desc.configurable) {
|
||||
$ERROR("Intl.NumberFormat.prototype must not be configurable.");
|
||||
}
|
||||
|
46
test/suite/intl402/ch11/11.2/11.2.3_b.js
Normal file
46
test/suite/intl402/ch11/11.2/11.2.3_b.js
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.NumberFormat does not accept Unicode locale
|
||||
* extension keys and values that are not allowed.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var locales = ["ja-JP", "zh-Hans-CN", "zh-Hant-TW"];
|
||||
var input = 1234567.89;
|
||||
|
||||
locales.forEach(function (locale) {
|
||||
var defaultNumberFormat = new Intl.NumberFormat([locale]);
|
||||
var defaultOptions = defaultNumberFormat.resolvedOptions();
|
||||
var defaultOptionsJSON = JSON.stringify(defaultOptions);
|
||||
var defaultLocale = defaultOptions.locale;
|
||||
var defaultFormatted = defaultNumberFormat.format(input);
|
||||
|
||||
var keyValues = {
|
||||
"cu": ["USD", "EUR", "JPY", "CNY", "TWD", "invalid"],
|
||||
"nu": ["native", "traditio", "finance", "invalid"]
|
||||
};
|
||||
|
||||
Object.getOwnPropertyNames(keyValues).forEach(function (key) {
|
||||
keyValues[key].forEach(function (value) {
|
||||
var numberFormat = new Intl.NumberFormat([locale + "-u-" + key + "-" + value]);
|
||||
var options = numberFormat.resolvedOptions();
|
||||
if (options.locale !== defaultLocale) {
|
||||
$ERROR("Locale " + options.locale + " is affected by key " +
|
||||
key + "; value " + value + ".");
|
||||
}
|
||||
if (JSON.stringify(options) !== defaultOptionsJSON) {
|
||||
$ERROR("Resolved options " + JSON.stringify(options) + " are affected by key " +
|
||||
key + "; value " + value + ".");
|
||||
}
|
||||
if (defaultFormatted !== numberFormat.format(input)) {
|
||||
$ERROR("Formatted value " + numberFormat.format(input) + " is affected by key " +
|
||||
key + "; value " + value + ".");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
41
test/suite/intl402/ch11/11.3/11.3.2_1_c.js
Normal file
41
test/suite/intl402/ch11/11.3/11.3.2_1_c.js
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that format function is bound to its Intl.NumberFormat.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var numbers = [0, -0, 1, -1, 5.5, 123, -123, -123.45, 123.44501, 0.001234,
|
||||
-0.00000000123, 0.00000000000000000000000000000123, 1.2, 0.0000000012344501,
|
||||
123445.01, 12344501000000000000000000000000000, -12344501000000000000000000000000000,
|
||||
Infinity, -Infinity, NaN];
|
||||
var locales = [undefined, ["de"], ["th-u-nu-thai"], ["en"], ["ja-u-nu-jpanfin"], ["ar-u-nu-arab"]];
|
||||
var options = [
|
||||
undefined,
|
||||
{style: "percent"},
|
||||
{style: "currency", currency: "EUR", currencyDisplay: "symbol"},
|
||||
{style: "currency", currency: "IQD", currencyDisplay: "symbol"},
|
||||
{style: "currency", currency: "KMF", currencyDisplay: "symbol"},
|
||||
{style: "currency", currency: "CLF", currencyDisplay: "symbol"},
|
||||
{useGrouping: false, minimumIntegerDigits: 3, minimumFractionDigits: 1, maximumFractionDigits: 3}
|
||||
];
|
||||
|
||||
locales.forEach(function (locales) {
|
||||
options.forEach(function (options) {
|
||||
var formatObj = new Intl.NumberFormat(locales, options);
|
||||
var formatFunc = formatObj.format;
|
||||
numbers.forEach(function (number) {
|
||||
var referenceFormatted = formatObj.format(number);
|
||||
var formatted = formatFunc(number);
|
||||
if (referenceFormatted !== formatted) {
|
||||
$ERROR("format function produces different result than format method for locales " +
|
||||
locales + "; options: " + (options ? JSON.stringify(options) : options) +
|
||||
" : " + formatted + " vs. " + referenceFormatted + ".");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
52
test/suite/intl402/ch11/11.3/11.3.2_TRF.js
Normal file
52
test/suite/intl402/ch11/11.3/11.3.2_TRF.js
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the digits are determined correctly when specifying pre/post decimal digits.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var locales = [
|
||||
new Intl.NumberFormat().resolvedOptions().locale,
|
||||
"ar", "de", "th", "ja"
|
||||
];
|
||||
var numberingSystems = [
|
||||
"arab",
|
||||
"latn",
|
||||
"thai",
|
||||
"hanidec"
|
||||
];
|
||||
var testData = {
|
||||
"0": "000.0",
|
||||
"-0": "000.0",
|
||||
"123": "123.0",
|
||||
"-123": "-123.0",
|
||||
"12345": "12345.0",
|
||||
"-12345": "-12345.0",
|
||||
"123.45": "123.45",
|
||||
"-123.45": "-123.45",
|
||||
"123.44501": "123.445",
|
||||
"-123.44501": "-123.445",
|
||||
"0.001234": "000.001",
|
||||
"-0.001234": "-000.001",
|
||||
"0.00000000123": "000.0",
|
||||
"-0.00000000123": "-000.0",
|
||||
"0.00000000000000000000000000000123": "000.0",
|
||||
"-0.00000000000000000000000000000123": "-000.0",
|
||||
"1.2": "001.2",
|
||||
"-1.2": "-001.2",
|
||||
"0.0000000012344501": "000.0",
|
||||
"-0.0000000012344501": "-000.0",
|
||||
"123445.01": "123445.01",
|
||||
"-123445.01": "-123445.01",
|
||||
"12344501000000000000000000000000000": "12344501000000000000000000000000000.0",
|
||||
"-12344501000000000000000000000000000": "-12344501000000000000000000000000000.0"
|
||||
};
|
||||
|
||||
testNumberFormat(locales, numberingSystems,
|
||||
{useGrouping: false, minimumIntegerDigits: 3, minimumFractionDigits: 1, maximumFractionDigits: 3},
|
||||
testData);
|
||||
|
52
test/suite/intl402/ch11/11.3/11.3.2_TRP.js
Normal file
52
test/suite/intl402/ch11/11.3/11.3.2_TRP.js
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the digits are determined correctly when specifying significant digits.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var locales = [
|
||||
new Intl.NumberFormat().resolvedOptions().locale,
|
||||
"ar", "de", "th", "ja"
|
||||
];
|
||||
var numberingSystems = [
|
||||
"arab",
|
||||
"latn",
|
||||
"thai",
|
||||
"hanidec"
|
||||
];
|
||||
var testData = {
|
||||
"0": "0.00",
|
||||
"-0": "0.00",
|
||||
"123": "123",
|
||||
"-123": "-123",
|
||||
"12345": "12345",
|
||||
"-12345": "-12345",
|
||||
"123.45": "123.45",
|
||||
"-123.45": "-123.45",
|
||||
"123.44501": "123.45",
|
||||
"-123.44501": "-123.45",
|
||||
"0.001234": "0.001234",
|
||||
"-0.001234": "-0.001234",
|
||||
"0.00000000123": "0.00000000123",
|
||||
"-0.00000000123": "-0.00000000123",
|
||||
"0.00000000000000000000000000000123": "0.00000000000000000000000000000123",
|
||||
"-0.00000000000000000000000000000123": "-0.00000000000000000000000000000123",
|
||||
"1.2": "1.20",
|
||||
"-1.2": "-1.20",
|
||||
"0.0000000012344501": "0.0000000012345",
|
||||
"-0.0000000012344501": "-0.0000000012345",
|
||||
"123445.01": "123450",
|
||||
"-123445.01": "-123450",
|
||||
"12344501000000000000000000000000000": "12345000000000000000000000000000000",
|
||||
"-12344501000000000000000000000000000": "-12345000000000000000000000000000000"
|
||||
};
|
||||
|
||||
testNumberFormat(locales, numberingSystems,
|
||||
{useGrouping: false, minimumSignificantDigits: 3, maximumSignificantDigits: 5},
|
||||
testData);
|
||||
|
31
test/suite/intl402/ch11/11.3/11.3.3.js
Normal file
31
test/suite/intl402/ch11/11.3/11.3.3.js
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the object returned by Intl.NumberFormat.prototype.resolvedOptions
|
||||
* has the right properties.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var actual = new Intl.NumberFormat().resolvedOptions();
|
||||
|
||||
var actual2 = new Intl.NumberFormat().resolvedOptions();
|
||||
if (actual2 === actual) {
|
||||
$ERROR("resolvedOptions returned the same object twice.");
|
||||
}
|
||||
|
||||
// this assumes the default values where the specification provides them
|
||||
mustHaveProperty(actual, "locale", isCanonicalizedStructurallyValidLanguageTag);
|
||||
mustHaveProperty(actual, "numberingSystem", isValidNumberingSystem);
|
||||
mustHaveProperty(actual, "style", ["decimal"]);
|
||||
mustNotHaveProperty(actual, "currency");
|
||||
mustNotHaveProperty(actual, "currencyDisplay");
|
||||
mustHaveProperty(actual, "minimumIntegerDigits", [1]);
|
||||
mustHaveProperty(actual, "minimumFractionDigits", [0]);
|
||||
mustHaveProperty(actual, "maximumFractionDigits", [3]);
|
||||
mustNotHaveProperty(actual, "minimumSignificantDigits");
|
||||
mustNotHaveProperty(actual, "maximumSignificantDigits");
|
||||
mustHaveProperty(actual, "useGrouping", [true, false]);
|
||||
|
33
test/suite/intl402/ch11/11.3/11.3_b.js
Normal file
33
test/suite/intl402/ch11/11.3/11.3_b.js
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.NumberFormat.prototype functions throw a
|
||||
* TypeError if called on a non-object value or an object that hasn't been
|
||||
* initialized as a NumberFormat.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var functions = {
|
||||
"format getter": Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format").get,
|
||||
resolvedOptions: Intl.NumberFormat.prototype.resolvedOptions
|
||||
};
|
||||
var invalidTargets = [undefined, null, true, 0, "NumberFormat", [], {}];
|
||||
|
||||
Object.getOwnPropertyNames(functions).forEach(function (functionName) {
|
||||
var f = functions[functionName];
|
||||
invalidTargets.forEach(function (target) {
|
||||
var error;
|
||||
try {
|
||||
f.call(target);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Calling " + functionName + " on " + target + " was not rejected.");
|
||||
} else if (error.name !== "TypeError") {
|
||||
$ERROR("Calling " + functionName + " on " + target + " was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
15
test/suite/intl402/ch11/11.4/11.4_a.js
Normal file
15
test/suite/intl402/ch11/11.4/11.4_a.js
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.NumberFormat instances have the specified properties.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var obj = new Intl.NumberFormat();
|
||||
|
||||
var toStringValue = Object.prototype.toString.call(obj);
|
||||
if (toStringValue !== "[object Object]") {
|
||||
$ERROR("Intl.NumberFormat instance produces wrong [[Class]] - toString returns " + toStringValue + ".");
|
||||
}
|
||||
|
43
test/suite/intl402/ch12/12.1/12.1.1_1.js
Normal file
43
test/suite/intl402/ch12/12.1/12.1.1_1.js
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that an object can't be re-initialized as a DateTimeFormat.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
testWithIntlConstructors(function (Constructor) {
|
||||
var obj, error;
|
||||
|
||||
// variant 1: use constructor in a "new" expression
|
||||
obj = new Constructor();
|
||||
try {
|
||||
Intl.DateTimeFormat.call(obj);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Re-initializing object created with \"new\" as DateTimeFormat was not rejected.");
|
||||
} else if (error.name !== "TypeError") {
|
||||
$ERROR("Re-initializing object created with \"new\" as DateTimeFormat was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
|
||||
// variant 2: use constructor as a function
|
||||
obj = Constructor.call({});
|
||||
error = undefined;
|
||||
try {
|
||||
Intl.DateTimeFormat.call(obj);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Re-initializing object created with constructor as function as DateTimeFormat was not rejected.");
|
||||
} else if (error.name !== "TypeError") {
|
||||
$ERROR("Re-initializing object created with constructor as function as DateTimeFormat was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
12
test/suite/intl402/ch12/12.1/12.1.1_18.js
Normal file
12
test/suite/intl402/ch12/12.1/12.1.1_18.js
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the option hour12 is processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
testOption(Intl.DateTimeFormat, "hour12", "boolean");
|
||||
|
18
test/suite/intl402/ch12/12.1/12.1.1_22.js
Normal file
18
test/suite/intl402/ch12/12.1/12.1.1_22.js
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the behavior of a Record is not affected by adversarial
|
||||
* changes to Object.prototype.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
taintProperties(["weekday", "era", "year", "month", "day", "hour", "minute", "second", "timeZone"]);
|
||||
|
||||
var locale = new Intl.DateTimeFormat(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale;
|
||||
if (!isCanonicalizedStructurallyValidLanguageTag(locale)) {
|
||||
$ERROR("DateTimeFormat returns invalid locale " + locale + ".");
|
||||
}
|
||||
|
14
test/suite/intl402/ch12/12.1/12.1.1_23.js
Normal file
14
test/suite/intl402/ch12/12.1/12.1.1_23.js
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the options for the date and time components are processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
getDateTimeComponents().forEach(function (component) {
|
||||
testOption(Intl.DateTimeFormat, component, "string", getDateTimeComponentValues(component), undefined, {isILD: true});
|
||||
});
|
||||
|
12
test/suite/intl402/ch12/12.1/12.1.1_25.js
Normal file
12
test/suite/intl402/ch12/12.1/12.1.1_25.js
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the option formatMatcher is processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
testOption(Intl.DateTimeFormat, "formatMatcher", "string", ["basic", "best fit"], "best fit", {noReturn: true});
|
||||
|
18
test/suite/intl402/ch12/12.1/12.1.1_5.js
Normal file
18
test/suite/intl402/ch12/12.1/12.1.1_5.js
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the behavior of a Record is not affected by adversarial
|
||||
* changes to Object.prototype.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
taintProperties(["localeMatcher"]);
|
||||
|
||||
var locale = new Intl.DateTimeFormat(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale;
|
||||
if (!isCanonicalizedStructurallyValidLanguageTag(locale)) {
|
||||
$ERROR("DateTimeFormat returns invalid locale " + locale + ".");
|
||||
}
|
||||
|
12
test/suite/intl402/ch12/12.1/12.1.1_6.js
Normal file
12
test/suite/intl402/ch12/12.1/12.1.1_6.js
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the option localeMatcher is processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
testOption(Intl.DateTimeFormat, "localeMatcher", "string", ["lookup", "best fit"], "best fit", {noReturn: true});
|
||||
|
107
test/suite/intl402/ch12/12.1/12.1.1_TDTO.js
Normal file
107
test/suite/intl402/ch12/12.1/12.1.1_TDTO.js
Normal file
@ -0,0 +1,107 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the set of options for the date and time components is processed correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var locales = [[], ["zh-Hans-CN"], ["hi-IN"], ["en-US"], ["id-ID"]];
|
||||
var dates = [new Date(), new Date(0), new Date(Date.parse("1989-11-09T17:57:00Z"))];
|
||||
|
||||
function testWithDateTimeFormat(options, expected) {
|
||||
locales.forEach(function (locales) {
|
||||
var format = new Intl.DateTimeFormat(locales, options);
|
||||
var resolvedOptions = format.resolvedOptions();
|
||||
getDateTimeComponents().forEach(function (component) {
|
||||
if (resolvedOptions.hasOwnProperty(component)) {
|
||||
if (!expected.hasOwnProperty(component)) {
|
||||
$ERROR("Unrequested component " + component +
|
||||
" added to expected subset " + JSON.stringify(expected) +
|
||||
"; locales " + locales + ", options " +
|
||||
(options ? JSON.stringify(options) : options) + ".");
|
||||
}
|
||||
} else {
|
||||
if (expected.hasOwnProperty(component)) {
|
||||
$ERROR("Missing component " + component +
|
||||
" from expected subset " + JSON.stringify(expected) +
|
||||
"; locales " + locales + ", options " +
|
||||
(options ? JSON.stringify(options) : options) + ".");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testWithToLocale(f, options, expected) {
|
||||
// expected can be either one subset or an array of possible subsets
|
||||
if (expected.length === undefined) {
|
||||
expected = [expected];
|
||||
}
|
||||
locales.forEach(function (locales) {
|
||||
dates.forEach(function (date) {
|
||||
var formatted = Date.prototype[f].call(date, locales, options);
|
||||
var expectedStrings = [];
|
||||
expected.forEach(function (expected) {
|
||||
var referenceFormat = new Intl.DateTimeFormat(locales, expected);
|
||||
expectedStrings.push(referenceFormat.format(date));
|
||||
});
|
||||
if (expectedStrings.indexOf(formatted) === -1) {
|
||||
$ERROR("Function " + f + " did not return expected string for locales " +
|
||||
locales + ", options " + (options? JSON.stringify(options) : options) +
|
||||
"; expected " +
|
||||
(expectedStrings.length === 1 ? expectedStrings[0] : "one of " + expectedStrings) +
|
||||
", got " + formatted + ".");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// any/date: steps 5a, 6a, 7a
|
||||
testWithDateTimeFormat(undefined, {year: "numeric", month: "numeric", day: "numeric"});
|
||||
|
||||
// any/date: steps 5a, 6a
|
||||
testWithDateTimeFormat({year: "numeric", month: "numeric"}, {year: "numeric", month: "numeric"});
|
||||
|
||||
// any/date: steps 5a, 6a
|
||||
testWithDateTimeFormat({hour: "numeric", minute: "numeric"}, {hour: "numeric", minute: "numeric"});
|
||||
|
||||
// any/all: steps 5a, 6a, 7a, 8a
|
||||
testWithToLocale("toLocaleString", undefined, [
|
||||
// the first one is not guaranteed to be supported; the second one is
|
||||
{year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"},
|
||||
{weekday: "short", year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"}
|
||||
]);
|
||||
|
||||
// any/all: steps 5a, 6a
|
||||
testWithToLocale("toLocaleString", {year: "numeric", month: "numeric"}, {year: "numeric", month: "numeric"});
|
||||
|
||||
// any/all: steps 5a, 6a
|
||||
testWithToLocale("toLocaleString", {hour: "numeric", minute: "numeric"}, {hour: "numeric", minute: "numeric"});
|
||||
|
||||
// date/date: steps 5a, 7a
|
||||
testWithToLocale("toLocaleDateString", undefined, {year: "numeric", month: "numeric", day: "numeric"});
|
||||
|
||||
// date/date: steps 5a
|
||||
testWithToLocale("toLocaleDateString", {year: "numeric", month: "numeric"}, {year: "numeric", month: "numeric"});
|
||||
|
||||
// date/date: steps 5a, 7a
|
||||
testWithToLocale("toLocaleDateString", {hour: "numeric", minute: "numeric", second: "numeric"}, [
|
||||
// the first one is not guaranteed to be supported; the second one is
|
||||
{year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"},
|
||||
{weekday: "short", year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"}
|
||||
]);
|
||||
|
||||
// time/time: steps 6a, 8a
|
||||
testWithToLocale("toLocaleTimeString", undefined, {hour: "numeric", minute: "numeric", second: "numeric"});
|
||||
|
||||
// time/time: steps 6a, 8a
|
||||
testWithToLocale("toLocaleTimeString", {weekday: "short", year: "numeric", month: "numeric", day: "numeric"},
|
||||
{weekday: "short", year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"});
|
||||
|
||||
// time/time: steps 6a
|
||||
testWithToLocale("toLocaleTimeString", {hour: "numeric", minute: "numeric"}, {hour: "numeric", minute: "numeric"});
|
||||
|
||||
|
30
test/suite/intl402/ch12/12.1/12.1.2.js
Normal file
30
test/suite/intl402/ch12/12.1/12.1.2.js
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.DateTimeFormat can be subclassed.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
// get a date-time format and have it format an array of dates for comparison with the subclass
|
||||
var locales = ["tlh", "id", "en"];
|
||||
var a = [new Date(0), Date.now(), new Date(Date.parse("1989-11-09T17:57:00Z"))];
|
||||
var referenceDateTimeFormat = new Intl.DateTimeFormat(locales);
|
||||
var referenceFormatted = a.map(referenceDateTimeFormat.format);
|
||||
|
||||
function MyDateTimeFormat(locales, options) {
|
||||
Intl.DateTimeFormat.call(this, locales, options);
|
||||
// could initialize MyDateTimeFormat properties
|
||||
}
|
||||
|
||||
MyDateTimeFormat.prototype = Object.create(Intl.DateTimeFormat.prototype);
|
||||
MyDateTimeFormat.prototype.constructor = MyDateTimeFormat;
|
||||
// could add methods to MyDateTimeFormat.prototype
|
||||
|
||||
var format = new MyDateTimeFormat(locales);
|
||||
var actual = a.map(format.format);
|
||||
testArraysAreSame(referenceFormatted, actual);
|
||||
|
19
test/suite/intl402/ch12/12.1/12.1.3.js
Normal file
19
test/suite/intl402/ch12/12.1/12.1.3.js
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that objects constructed by Intl.DateTimeFormat have the specified internal properties.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var obj = new Intl.DateTimeFormat();
|
||||
|
||||
var actualPrototype = Object.getPrototypeOf(obj);
|
||||
if (actualPrototype !== Intl.DateTimeFormat.prototype) {
|
||||
$ERROR("Prototype of object constructed by Intl.DateTimeFormat isn't Intl.DateTimeFormat.prototype; got " + actualPrototype);
|
||||
}
|
||||
|
||||
if (!Object.isExtensible(obj)) {
|
||||
$ERROR("Object constructed by Intl.DateTimeFormat must be extensible.");
|
||||
}
|
||||
|
22
test/suite/intl402/ch12/12.2/12.2.1.js
Normal file
22
test/suite/intl402/ch12/12.2/12.2.1.js
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.DateTimeFormat.prototype has the required attributes.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var desc = Object.getOwnPropertyDescriptor(Intl.DateTimeFormat, "prototype");
|
||||
if (desc === undefined) {
|
||||
$ERROR("Intl.DateTimeFormat.prototype is not defined.");
|
||||
}
|
||||
if (desc.writable) {
|
||||
$ERROR("Intl.DateTimeFormat.prototype must not be writable.");
|
||||
}
|
||||
if (desc.enumerable) {
|
||||
$ERROR("Intl.DateTimeFormat.prototype must not be enumerable.");
|
||||
}
|
||||
if (desc.configurable) {
|
||||
$ERROR("Intl.DateTimeFormat.prototype must not be configurable.");
|
||||
}
|
||||
|
47
test/suite/intl402/ch12/12.2/12.2.3_b.js
Normal file
47
test/suite/intl402/ch12/12.2/12.2.3_b.js
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.DateTimeFormat does not accept Unicode locale
|
||||
* extension keys and values that are not allowed.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var locales = ["ja-JP", "zh-Hans-CN", "zh-Hant-TW"];
|
||||
var input = new Date(Date.parse("1989-11-09T17:57:00Z"));
|
||||
|
||||
locales.forEach(function (locale) {
|
||||
var defaultDateTimeFormat = new Intl.DateTimeFormat([locale]);
|
||||
var defaultOptions = defaultDateTimeFormat.resolvedOptions();
|
||||
var defaultOptionsJSON = JSON.stringify(defaultOptions);
|
||||
var defaultLocale = defaultOptions.locale;
|
||||
var defaultFormatted = defaultDateTimeFormat.format(input);
|
||||
|
||||
var keyValues = {
|
||||
"cu": ["USD", "EUR", "JPY", "CNY", "TWD", "invalid"], // DateTimeFormat internally uses NumberFormat
|
||||
"nu": ["native", "traditio", "finance", "invalid"],
|
||||
"tz": ["usnavajo", "utcw01", "aumel", "uslax", "usnyc", "deber", "invalid"]
|
||||
};
|
||||
|
||||
Object.getOwnPropertyNames(keyValues).forEach(function (key) {
|
||||
keyValues[key].forEach(function (value) {
|
||||
var dateTimeFormat = new Intl.DateTimeFormat([locale + "-u-" + key + "-" + value]);
|
||||
var options = dateTimeFormat.resolvedOptions();
|
||||
if (options.locale !== defaultLocale) {
|
||||
$ERROR("Locale " + options.locale + " is affected by key " +
|
||||
key + "; value " + value + ".");
|
||||
}
|
||||
if (JSON.stringify(options) !== defaultOptionsJSON) {
|
||||
$ERROR("Resolved options " + JSON.stringify(options) + " are affected by key " +
|
||||
key + "; value " + value + ".");
|
||||
}
|
||||
if (defaultFormatted !== dateTimeFormat.format(input)) {
|
||||
$ERROR("Formatted value " + dateTimeFormat.format(input) + " is affected by key " +
|
||||
key + "; value " + value + ".");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
52
test/suite/intl402/ch12/12.2/12.2.3_c.js
Normal file
52
test/suite/intl402/ch12/12.2/12.2.3_c.js
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.DateTimeFormat provides the required date-time
|
||||
* format component subsets.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var locales = ["de-DE", "en-US", "hi-IN", "id-ID", "ja-JP", "th-TH", "zh-Hans-CN", "zh-Hant-TW", "zxx"];
|
||||
var subsets = [
|
||||
{weekday: "long", year: "numeric", month: "numeric", day: "numeric",
|
||||
hour: "numeric", minute: "numeric", second: "numeric"},
|
||||
{weekday: "long", year: "numeric", month: "numeric", day: "numeric"},
|
||||
{year: "numeric", month: "numeric", day: "numeric"},
|
||||
{year: "numeric", month: "numeric"},
|
||||
{month: "numeric", day: "numeric"},
|
||||
{hour: "numeric", minute: "numeric", second: "numeric"},
|
||||
{hour: "numeric", minute: "numeric"}
|
||||
];
|
||||
|
||||
locales.forEach(function (locale) {
|
||||
subsets.forEach(function (subset) {
|
||||
var format = new Intl.DateTimeFormat([locale], subset);
|
||||
var actual = format.resolvedOptions();
|
||||
getDateTimeComponents().forEach(function (component) {
|
||||
if (actual.hasOwnProperty(component)) {
|
||||
if (!subset.hasOwnProperty(component)) {
|
||||
$ERROR("Unrequested component " + component +
|
||||
" added to requested subset " + JSON.stringify(subset) +
|
||||
"; locale " + locale + ".");
|
||||
}
|
||||
try {
|
||||
testValidDateTimeComponentValue(component, actual[component]);
|
||||
} catch (e) {
|
||||
e.message += " (Testing locale " + locale + "; subset " +
|
||||
JSON.stringify(subset) + ")";
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
if (subset.hasOwnProperty(component)) {
|
||||
$ERROR("Missing component " + component +
|
||||
" from requested subset " + JSON.stringify(subset) +
|
||||
"; locale " + locale + ".");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
34
test/suite/intl402/ch12/12.3/12.3.2_1_c.js
Normal file
34
test/suite/intl402/ch12/12.3/12.3.2_1_c.js
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that format function is bound to its Intl.DateTimeFormat.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var dates = [new Date(), new Date(0), new Date(Date.parse("1989-11-09T17:57:00Z"))];
|
||||
var locales = [undefined, ["de"], ["th-u-ca-gregory-nu-thai"], ["en"], ["ja-u-ca-japanese"], ["ar-u-ca-islamicc-nu-arab"]];
|
||||
var options = [
|
||||
undefined,
|
||||
{hour12: false},
|
||||
{month: "long", day: "numeric", hour: "2-digit", minute: "2-digit"}
|
||||
];
|
||||
|
||||
locales.forEach(function (locales) {
|
||||
options.forEach(function (options) {
|
||||
var formatObj = new Intl.DateTimeFormat(locales, options);
|
||||
var formatFunc = formatObj.format;
|
||||
dates.forEach(function (date) {
|
||||
var referenceFormatted = formatObj.format(date);
|
||||
var formatted = formatFunc(date);
|
||||
if (referenceFormatted !== formatted) {
|
||||
$ERROR("format function produces different result than format method for locales " +
|
||||
locales + "; options: " + (options ? JSON.stringify(options) : options) +
|
||||
" : " + formatted + " vs. " + referenceFormatted + ".");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
26
test/suite/intl402/ch12/12.3/12.3.2_FDT_1.js
Normal file
26
test/suite/intl402/ch12/12.3/12.3.2_FDT_1.js
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that format handles non-finite values correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var invalidValues = [NaN, Infinity, -Infinity];
|
||||
|
||||
var format = new Intl.DateTimeFormat();
|
||||
|
||||
invalidValues.forEach(function (value) {
|
||||
var error;
|
||||
try {
|
||||
var result = format.format(value);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Invalid value " + value + " was not rejected.");
|
||||
} else if (error.name !== "RangeError") {
|
||||
$ERROR("Invalid value " + value + " was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
});
|
||||
|
16
test/suite/intl402/ch12/12.3/12.3.2_TLT_2.js
Normal file
16
test/suite/intl402/ch12/12.3/12.3.2_TLT_2.js
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the behavior of a Record is not affected by adversarial
|
||||
* changes to Object.prototype.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
taintProperties(["weekday", "era", "year", "month", "day", "hour", "minute", "second", "inDST"]);
|
||||
|
||||
var format = new Intl.DateTimeFormat();
|
||||
var time = format.format();
|
||||
|
52
test/suite/intl402/ch12/12.3/12.3.3.js
Normal file
52
test/suite/intl402/ch12/12.3/12.3.3.js
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that the object returned by Intl.DateTimeFormat.prototype.resolvedOptions
|
||||
* has the right properties.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var actual = new Intl.DateTimeFormat().resolvedOptions();
|
||||
|
||||
var actual2 = new Intl.DateTimeFormat().resolvedOptions();
|
||||
if (actual2 === actual) {
|
||||
$ERROR("resolvedOptions returned the same object twice.");
|
||||
}
|
||||
|
||||
// source: CLDR file common/bcp47/calendar.xml; version CLDR 21.
|
||||
var calendars = [
|
||||
"buddhist",
|
||||
"chinese",
|
||||
"coptic",
|
||||
"ethioaa",
|
||||
"ethiopic",
|
||||
"gregory",
|
||||
"hebrew",
|
||||
"indian",
|
||||
"islamic",
|
||||
"islamicc",
|
||||
"iso8601",
|
||||
"japanese",
|
||||
"persian",
|
||||
"roc"
|
||||
];
|
||||
|
||||
// this assumes the default values where the specification provides them
|
||||
mustHaveProperty(actual, "locale", isCanonicalizedStructurallyValidLanguageTag);
|
||||
mustHaveProperty(actual, "calendar", calendars);
|
||||
mustHaveProperty(actual, "numberingSystem", isValidNumberingSystem);
|
||||
mustHaveProperty(actual, "timeZone", [undefined]);
|
||||
mustHaveProperty(actual, "hour12", [true, false]);
|
||||
mustNotHaveProperty(actual, "weekday");
|
||||
mustNotHaveProperty(actual, "era");
|
||||
mustHaveProperty(actual, "year", ["2-digit", "numeric"]);
|
||||
mustHaveProperty(actual, "month", ["2-digit", "numeric", "narrow", "short", "long"]);
|
||||
mustHaveProperty(actual, "day", ["2-digit", "numeric"]);
|
||||
mustNotHaveProperty(actual, "hour");
|
||||
mustNotHaveProperty(actual, "minute");
|
||||
mustNotHaveProperty(actual, "second");
|
||||
mustNotHaveProperty(actual, "timeZoneName");
|
||||
|
33
test/suite/intl402/ch12/12.3/12.3_b.js
Normal file
33
test/suite/intl402/ch12/12.3/12.3_b.js
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.DateTimeFormat.prototype functions throw a
|
||||
* TypeError if called on a non-object value or an object that hasn't been
|
||||
* initialized as a DateTimeFormat.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var functions = {
|
||||
"format getter": Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, "format").get,
|
||||
resolvedOptions: Intl.DateTimeFormat.prototype.resolvedOptions
|
||||
};
|
||||
var invalidTargets = [undefined, null, true, 0, "DateTimeFormat", [], {}];
|
||||
|
||||
Object.getOwnPropertyNames(functions).forEach(function (functionName) {
|
||||
var f = functions[functionName];
|
||||
invalidTargets.forEach(function (target) {
|
||||
var error;
|
||||
try {
|
||||
f.call(target);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Calling " + functionName + " on " + target + " was not rejected.");
|
||||
} else if (error.name !== "TypeError") {
|
||||
$ERROR("Calling " + functionName + " on " + target + " was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
15
test/suite/intl402/ch12/12.4/12.4_a.js
Normal file
15
test/suite/intl402/ch12/12.4/12.4_a.js
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Intl.DateTimeFormat instances have the specified properties.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var obj = new Intl.DateTimeFormat();
|
||||
|
||||
var toStringValue = Object.prototype.toString.call(obj);
|
||||
if (toStringValue !== "[object Object]") {
|
||||
$ERROR("Intl.DateTimeFormat instance produces wrong [[Class]] - toString returns " + toStringValue + ".");
|
||||
}
|
||||
|
24
test/suite/intl402/ch13/13.1/13.1.1_1.js
Normal file
24
test/suite/intl402/ch13/13.1/13.1.1_1.js
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that localeCompare rejects values that can't be coerced to an object.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var invalidValues = [undefined, null];
|
||||
|
||||
invalidValues.forEach(function (value) {
|
||||
var error;
|
||||
try {
|
||||
var result = String.prototype.localeCompare.call(value, "");
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("String.prototype.localeCompare did not reject this = " + value + ".");
|
||||
} else if (error.name !== "TypeError") {
|
||||
$ERROR("String.prototype.localeCompare rejected this = " + value + " with wrong error " + error.name + ".");
|
||||
}
|
||||
});
|
||||
|
26
test/suite/intl402/ch13/13.1/13.1.1_2.js
Normal file
26
test/suite/intl402/ch13/13.1/13.1.1_2.js
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that localeCompare coerces this to a string.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var thisValues = [true, 5, "hello", {toString: function () { return "good bye"; }}];
|
||||
var thatValues = ["true", "5", "hello", "good bye"];
|
||||
|
||||
var i;
|
||||
for (i = 0; i < thisValues.length; i++) {
|
||||
var j;
|
||||
for (j = 0; j < thatValues.length; j++) {
|
||||
var result = String.prototype.localeCompare.call(thisValues[i], thatValues[j]);
|
||||
if ((result === 0) !== (i === j)) {
|
||||
if (result === 0) {
|
||||
$ERROR("localeCompare treats " + thisValues[i] + " and " + thatValues[j] + " as equal.");
|
||||
} else {
|
||||
$ERROR("localeCompare treats " + thisValues[i] + " and " + thatValues[j] + " as different.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
26
test/suite/intl402/ch13/13.1/13.1.1_3.js
Normal file
26
test/suite/intl402/ch13/13.1/13.1.1_3.js
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that localeCompare coerces that to a string.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var thisValues = ["true", "5", "hello", "good bye"];
|
||||
var thatValues = [true, 5, "hello", {toString: function () { return "good bye"; }}];
|
||||
|
||||
var i;
|
||||
for (i = 0; i < thisValues.length; i++) {
|
||||
var j;
|
||||
for (j = 0; j < thatValues.length; j++) {
|
||||
var result = String.prototype.localeCompare.call(thisValues[i], thatValues[j]);
|
||||
if ((result === 0) !== (i === j)) {
|
||||
if (result === 0) {
|
||||
$ERROR("localeCompare treats " + thisValues[i] + " and " + thatValues[j] + " as equal.");
|
||||
} else {
|
||||
$ERROR("localeCompare treats " + thisValues[i] + " and " + thatValues[j] + " as different.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
65
test/suite/intl402/ch13/13.1/13.1.1_6.js
Normal file
65
test/suite/intl402/ch13/13.1/13.1.1_6.js
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that String.prototype.localeCompare throws the same exceptions as Intl.Collator.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var locales = [null, [NaN], ["i"], ["de_DE"]];
|
||||
var options = [
|
||||
{localeMatcher: null},
|
||||
{usage: "invalid"},
|
||||
{sensitivity: "invalid"}
|
||||
];
|
||||
|
||||
locales.forEach(function (locales) {
|
||||
var referenceError, error;
|
||||
try {
|
||||
var collator = new Intl.Collator(locales);
|
||||
} catch (e) {
|
||||
referenceError = e;
|
||||
}
|
||||
if (referenceError === undefined) {
|
||||
$ERROR("Internal error: Expected exception was not thrown by Intl.Collator for locales " + locales + ".");
|
||||
}
|
||||
|
||||
try {
|
||||
var result = "".localeCompare("", locales);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("String.prototype.localeCompare didn't throw exception for locales " + locales + ".");
|
||||
} else if (error.name !== referenceError.name) {
|
||||
$ERROR("String.prototype.localeCompare threw exception " + error.name +
|
||||
" for locales " + locales + "; expected " + referenceError.name + ".");
|
||||
}
|
||||
});
|
||||
|
||||
options.forEach(function (options) {
|
||||
var referenceError, error;
|
||||
try {
|
||||
var collator = new Intl.Collator([], options);
|
||||
} catch (e) {
|
||||
referenceError = e;
|
||||
}
|
||||
if (referenceError === undefined) {
|
||||
$ERROR("Internal error: Expected exception was not thrown by Intl.Collator for options " +
|
||||
JSON.stringify(options) + ".");
|
||||
}
|
||||
|
||||
try {
|
||||
var result = "".localeCompare("", [], options);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("String.prototype.localeCompare didn't throw exception for options " +
|
||||
JSON.stringify(options) + ".");
|
||||
} else if (error.name !== referenceError.name) {
|
||||
$ERROR("String.prototype.localeCompare threw exception " + error.name +
|
||||
" for options " + JSON.stringify(options) + "; expected " + referenceError.name + ".");
|
||||
}
|
||||
});
|
||||
|
33
test/suite/intl402/ch13/13.1/13.1.1_7.js
Normal file
33
test/suite/intl402/ch13/13.1/13.1.1_7.js
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that localeCompare produces the same results as Intl.Collator.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var strings = ["d", "O", "od", "oe", "of", "ö", "o\u0308", "X", "y", "Z", "Z.", "\uD842\uDFB7野家", "吉野家", "!A", "A", "b", "C"];
|
||||
var locales = [undefined, ["de"], ["de-u-co-phonebk"], ["en"], ["ja"], ["sv"]];
|
||||
var options = [
|
||||
undefined,
|
||||
{usage: "search"},
|
||||
{sensitivity: "base", ignorePunctuation: true}
|
||||
];
|
||||
|
||||
locales.forEach(function (locales) {
|
||||
options.forEach(function (options) {
|
||||
var referenceCollator = new Intl.Collator(locales, options);
|
||||
var referenceSorted = strings.slice().sort(referenceCollator.compare);
|
||||
|
||||
strings.sort(function (a, b) { return a.localeCompare(b, locales, options); });
|
||||
try {
|
||||
testArraysAreSame(referenceSorted, strings);
|
||||
} catch (e) {
|
||||
e.message += " (Testing with locales " + locales + "; options " + JSON.stringify(options) + ".)";
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
37
test/suite/intl402/ch13/13.2/13.2.1_1.js
Normal file
37
test/suite/intl402/ch13/13.2/13.2.1_1.js
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that toLocaleString handles "this Number value" correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var invalidValues = [undefined, null, "5", false, {valueOf: function () { return 5; }}];
|
||||
var validValues = [5, NaN, -1234567.89, -Infinity];
|
||||
|
||||
invalidValues.forEach(function (value) {
|
||||
var error;
|
||||
try {
|
||||
var result = Number.prototype.toLocaleString.call(value);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Number.prototype.toLocaleString did not reject this = " + value + ".");
|
||||
} else if (error.name !== "TypeError") {
|
||||
$ERROR("Number.prototype.toLocaleString rejected this = " + value + " with wrong error " + error.name + ".");
|
||||
}
|
||||
});
|
||||
|
||||
// for valid values, just check that a Number value and the corresponding
|
||||
// Number object get the same result.
|
||||
validValues.forEach(function (value) {
|
||||
var Constructor = Number; // to keep jshint happy
|
||||
var valueResult = Number.prototype.toLocaleString.call(value);
|
||||
var objectResult = Number.prototype.toLocaleString.call(new Constructor(value));
|
||||
if (valueResult !== objectResult) {
|
||||
$ERROR("Number.prototype.toLocaleString produces different results for Number value " +
|
||||
value + " and corresponding Number object: " + valueResult + " vs. " + objectResult + ".");
|
||||
}
|
||||
});
|
||||
|
67
test/suite/intl402/ch13/13.2/13.2.1_4.js
Normal file
67
test/suite/intl402/ch13/13.2/13.2.1_4.js
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Number.prototype.toLocaleString throws the same exceptions as Intl.NumberFormat.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var locales = [null, [NaN], ["i"], ["de_DE"]];
|
||||
var options = [
|
||||
{localeMatcher: null},
|
||||
{style: "invalid"},
|
||||
{style: "currency"},
|
||||
{style: "currency", currency: "ßP"},
|
||||
{maximumSignificantDigits: -Infinity}
|
||||
];
|
||||
|
||||
locales.forEach(function (locales) {
|
||||
var referenceError, error;
|
||||
try {
|
||||
var format = new Intl.NumberFormat(locales);
|
||||
} catch (e) {
|
||||
referenceError = e;
|
||||
}
|
||||
if (referenceError === undefined) {
|
||||
$ERROR("Internal error: Expected exception was not thrown by Intl.NumberFormat for locales " + locales + ".");
|
||||
}
|
||||
|
||||
try {
|
||||
var result = (0).toLocaleString(locales);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Number.prototype.toLocaleString didn't throw exception for locales " + locales + ".");
|
||||
} else if (error.name !== referenceError.name) {
|
||||
$ERROR("Number.prototype.toLocaleString threw exception " + error.name +
|
||||
" for locales " + locales + "; expected " + referenceError.name + ".");
|
||||
}
|
||||
});
|
||||
|
||||
options.forEach(function (options) {
|
||||
var referenceError, error;
|
||||
try {
|
||||
var format = new Intl.NumberFormat([], options);
|
||||
} catch (e) {
|
||||
referenceError = e;
|
||||
}
|
||||
if (referenceError === undefined) {
|
||||
$ERROR("Internal error: Expected exception was not thrown by Intl.NumberFormat for options " +
|
||||
JSON.stringify(options) + ".");
|
||||
}
|
||||
|
||||
try {
|
||||
var result = (0).toLocaleString([], options);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Number.prototype.toLocaleString didn't throw exception for options " +
|
||||
JSON.stringify(options) + ".");
|
||||
} else if (error.name !== referenceError.name) {
|
||||
$ERROR("Number.prototype.toLocaleString threw exception " + error.name +
|
||||
" for options " + JSON.stringify(options) + "; expected " + referenceError.name + ".");
|
||||
}
|
||||
});
|
||||
|
41
test/suite/intl402/ch13/13.2/13.2.1_5.js
Normal file
41
test/suite/intl402/ch13/13.2/13.2.1_5.js
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Number.prototype.toLocaleString produces the same results as Intl.NumberFormat.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var numbers = [0, -0, 1, -1, 5.5, 123, -123, -123.45, 123.44501, 0.001234,
|
||||
-0.00000000123, 0.00000000000000000000000000000123, 1.2, 0.0000000012344501,
|
||||
123445.01, 12344501000000000000000000000000000, -12344501000000000000000000000000000,
|
||||
Infinity, -Infinity, NaN];
|
||||
var locales = [undefined, ["de"], ["th-u-nu-thai"], ["en"], ["ja-u-nu-jpanfin"], ["ar-u-nu-arab"]];
|
||||
var options = [
|
||||
undefined,
|
||||
{style: "percent"},
|
||||
{style: "currency", currency: "EUR", currencyDisplay: "symbol"},
|
||||
{style: "currency", currency: "IQD", currencyDisplay: "symbol"},
|
||||
{style: "currency", currency: "KMF", currencyDisplay: "symbol"},
|
||||
{style: "currency", currency: "CLF", currencyDisplay: "symbol"},
|
||||
{useGrouping: false, minimumIntegerDigits: 3, minimumFractionDigits: 1, maximumFractionDigits: 3}
|
||||
];
|
||||
|
||||
locales.forEach(function (locales) {
|
||||
options.forEach(function (options) {
|
||||
var referenceNumberFormat = new Intl.NumberFormat(locales, options);
|
||||
var referenceFormatted = numbers.map(referenceNumberFormat.format);
|
||||
|
||||
var formatted = numbers.map(function (a) { return a.toLocaleString(locales, options); });
|
||||
try {
|
||||
testArraysAreSame(referenceFormatted, formatted);
|
||||
} catch (e) {
|
||||
e.message += " (Testing with locales " + locales + "; options " +
|
||||
(options ? JSON.stringify(options) : options) + ".)";
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
32
test/suite/intl402/ch13/13.3/13.3.0_1.js
Normal file
32
test/suite/intl402/ch13/13.3/13.3.0_1.js
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Date.prototype.toLocaleString & Co. handle "this time value" correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var functions = {
|
||||
toLocaleString: Date.prototype.toLocaleString,
|
||||
toLocaleDateString: Date.prototype.toLocaleDateString,
|
||||
toLocaleTimeString: Date.prototype.toLocaleTimeString
|
||||
};
|
||||
var invalidValues = [undefined, null, 5, "5", false, {valueOf: function () { return 5; }}];
|
||||
|
||||
Object.getOwnPropertyNames(functions).forEach(function (p) {
|
||||
var f = functions[p];
|
||||
invalidValues.forEach(function (value) {
|
||||
var error;
|
||||
try {
|
||||
var result = f.call(value);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Date.prototype." + p + " did not reject this = " + value + ".");
|
||||
} else if (error.name !== "TypeError") {
|
||||
$ERROR("Date.prototype." + p + " rejected this = " + value + " with wrong error " + error.name + ".");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
26
test/suite/intl402/ch13/13.3/13.3.0_2.js
Normal file
26
test/suite/intl402/ch13/13.3/13.3.0_2.js
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Date.prototype.toLocaleString & Co. handle non-finite values correctly.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var functions = {
|
||||
toLocaleString: Date.prototype.toLocaleString,
|
||||
toLocaleDateString: Date.prototype.toLocaleDateString,
|
||||
toLocaleTimeString: Date.prototype.toLocaleTimeString
|
||||
};
|
||||
var invalidValues = [NaN, Infinity, -Infinity];
|
||||
|
||||
Object.getOwnPropertyNames(functions).forEach(function (p) {
|
||||
var f = functions[p];
|
||||
invalidValues.forEach(function (value) {
|
||||
var result = f.call(new Date(value));
|
||||
if (result !== "Invalid Date") {
|
||||
$ERROR("Date.prototype." + p + " did not return \"Invalid Date\" for " +
|
||||
value + " – got " + result + " instead.");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
74
test/suite/intl402/ch13/13.3/13.3.0_6.js
Normal file
74
test/suite/intl402/ch13/13.3/13.3.0_6.js
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Date.prototype.toLocaleString & Co. throws the same exceptions as Intl.DateTimeFormat.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
var functions = {
|
||||
toLocaleString: Date.prototype.toLocaleString,
|
||||
toLocaleDateString: Date.prototype.toLocaleDateString,
|
||||
toLocaleTimeString: Date.prototype.toLocaleTimeString
|
||||
};
|
||||
var locales = [null, [NaN], ["i"], ["de_DE"]];
|
||||
var options = [
|
||||
{localeMatcher: null},
|
||||
{timeZone: "invalid"},
|
||||
{hour: "long"},
|
||||
{formatMatcher: "invalid"}
|
||||
];
|
||||
|
||||
Object.getOwnPropertyNames(functions).forEach(function (p) {
|
||||
var f = functions[p];
|
||||
locales.forEach(function (locales) {
|
||||
var referenceError, error;
|
||||
try {
|
||||
var format = new Intl.DateTimeFormat(locales);
|
||||
} catch (e) {
|
||||
referenceError = e;
|
||||
}
|
||||
if (referenceError === undefined) {
|
||||
$ERROR("Internal error: Expected exception was not thrown by Intl.DateTimeFormat for locales " + locales + ".");
|
||||
}
|
||||
|
||||
try {
|
||||
var result = f.call(new Date(), locales);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Date.prototype." + p + " didn't throw exception for locales " + locales + ".");
|
||||
} else if (error.name !== referenceError.name) {
|
||||
$ERROR("Date.prototype." + p + " threw exception " + error.name +
|
||||
" for locales " + locales + "; expected " + referenceError.name + ".");
|
||||
}
|
||||
});
|
||||
|
||||
options.forEach(function (options) {
|
||||
var referenceError, error;
|
||||
try {
|
||||
var format = new Intl.DateTimeFormat([], options);
|
||||
} catch (e) {
|
||||
referenceError = e;
|
||||
}
|
||||
if (referenceError === undefined) {
|
||||
$ERROR("Internal error: Expected exception was not thrown by Intl.DateTimeFormat for options " +
|
||||
JSON.stringify(options) + ".");
|
||||
}
|
||||
|
||||
try {
|
||||
var result = f.call(new Date(), [], options);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Date.prototype." + p + " didn't throw exception for options " +
|
||||
JSON.stringify(options) + ".");
|
||||
} else if (error.name !== referenceError.name) {
|
||||
$ERROR("Date.prototype." + p + " threw exception " + error.name +
|
||||
" for options " + JSON.stringify(options) + "; expected " + referenceError.name + ".");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
58
test/suite/intl402/ch13/13.3/13.3.0_7.js
Normal file
58
test/suite/intl402/ch13/13.3/13.3.0_7.js
Normal file
@ -0,0 +1,58 @@
|
||||
// Copyright 2012 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/**
|
||||
* @description Tests that Date.prototype.toLocaleString & Co. produces the same results as Intl.DateTimeFormat.
|
||||
* @author Norbert Lindenberg
|
||||
*/
|
||||
|
||||
$INCLUDE("testIntl.js");
|
||||
|
||||
var functions = {
|
||||
toLocaleString: [Date.prototype.toLocaleString,
|
||||
{year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"}],
|
||||
toLocaleDateString: [Date.prototype.toLocaleDateString,
|
||||
{year: "numeric", month: "numeric", day: "numeric"}],
|
||||
toLocaleTimeString: [Date.prototype.toLocaleTimeString,
|
||||
{hour: "numeric", minute: "numeric", second: "numeric"}]
|
||||
};
|
||||
var dates = [new Date(), new Date(0), new Date(Date.parse("1989-11-09T17:57:00Z"))];
|
||||
var locales = [undefined, ["de"], ["th-u-ca-gregory-nu-thai"], ["en"], ["ja-u-ca-japanese"], ["ar-u-ca-islamicc-nu-arab"]];
|
||||
var options = [
|
||||
undefined,
|
||||
{hour12: false},
|
||||
{month: "long", day: "numeric", hour: "2-digit", minute: "2-digit"}
|
||||
];
|
||||
|
||||
Object.getOwnPropertyNames(functions).forEach(function (p) {
|
||||
var f = functions[p][0];
|
||||
var defaults = functions[p][1];
|
||||
locales.forEach(function (locales) {
|
||||
options.forEach(function (options) {
|
||||
var constructorOptions = options;
|
||||
if (options === undefined) {
|
||||
constructorOptions = defaults;
|
||||
} else if (options.day === undefined) {
|
||||
// for simplicity, our options above have either both date and time or neither
|
||||
constructorOptions = Object.create(defaults);
|
||||
for (var prop in options) {
|
||||
if (options.hasOwnProperty(prop)) {
|
||||
constructorOptions[prop] = options[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
var referenceDateTimeFormat = new Intl.DateTimeFormat(locales, constructorOptions);
|
||||
var referenceFormatted = dates.map(referenceDateTimeFormat.format);
|
||||
|
||||
var formatted = dates.map(function (a) { return f.call(a, locales, options); });
|
||||
try {
|
||||
testArraysAreSame(referenceFormatted, formatted);
|
||||
} catch (e) {
|
||||
e.message += " (Testing with locales " + locales + "; options " +
|
||||
(options ? JSON.stringify(options) : options) + ".)";
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -656,3 +656,474 @@ function isCanonicalizedStructurallyValidLanguageTag(locale) {
|
||||
canonicalizeLanguageTag(locale) === locale;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the named options property is correctly handled by the given constructor.
|
||||
* @param {object} Constructor the constructor to test.
|
||||
* @param {string} property the name of the options property to test.
|
||||
* @param {string} type the type that values of the property are expected to have
|
||||
* @param {Array} [values] an array of allowed values for the property. Not needed for boolean.
|
||||
* @param {any} fallback the fallback value that the property assumes if not provided.
|
||||
* @param {object} testOptions additional options:
|
||||
* @param {boolean} isOptional whether support for this property is optional for implementations.
|
||||
* @param {boolean} noReturn whether the resulting value of the property is not returned.
|
||||
* @param {boolean} isILD whether the resulting value of the property is implementation and locale dependent.
|
||||
* @param {object} extra additional option to pass along, properties are value -> {option: value}.
|
||||
* @return {boolean} whether the test succeeded.
|
||||
*/
|
||||
function testOption(Constructor, property, type, values, fallback, testOptions) {
|
||||
var isOptional = testOptions !== undefined && testOptions.isOptional === true;
|
||||
var noReturn = testOptions !== undefined && testOptions.noReturn === true;
|
||||
var isILD = testOptions !== undefined && testOptions.isILD === true;
|
||||
|
||||
function addExtraOptions(options, value, testOptions) {
|
||||
if (testOptions !== undefined && testOptions.extra !== undefined) {
|
||||
var extra;
|
||||
if (value !== undefined && testOptions.extra[value] !== undefined) {
|
||||
extra = testOptions.extra[value];
|
||||
} else if (testOptions.extra.any !== undefined) {
|
||||
extra = testOptions.extra.any;
|
||||
}
|
||||
if (extra !== undefined) {
|
||||
Object.getOwnPropertyNames(extra).forEach(function (prop) {
|
||||
options[prop] = extra[prop];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testValues, options, obj, expected, actual, error;
|
||||
|
||||
// test that the specified values are accepted. Also add values that convert to specified values.
|
||||
if (type === "boolean") {
|
||||
if (values === undefined) {
|
||||
values = [true, false];
|
||||
}
|
||||
testValues = values.slice(0);
|
||||
testValues.push(888);
|
||||
testValues.push(0);
|
||||
} else if (type === "string") {
|
||||
testValues = values.slice(0);
|
||||
testValues.push({toString: function () { return values[0]; }});
|
||||
}
|
||||
testValues.forEach(function (value) {
|
||||
options = {};
|
||||
options[property] = value;
|
||||
addExtraOptions(options, value, testOptions);
|
||||
obj = new Constructor(undefined, options);
|
||||
if (noReturn) {
|
||||
if (obj.resolvedOptions().hasOwnProperty(property)) {
|
||||
$ERROR("Option property " + property + " is returned, but shouldn't be.");
|
||||
}
|
||||
} else {
|
||||
actual = obj.resolvedOptions()[property];
|
||||
if (isILD) {
|
||||
if (actual !== undefined && values.indexOf(actual) === -1) {
|
||||
$ERROR("Invalid value " + actual + " returned for property " + property + ".");
|
||||
}
|
||||
} else {
|
||||
if (type === "boolean") {
|
||||
expected = Boolean(value);
|
||||
} else if (type === "string") {
|
||||
expected = String(value);
|
||||
}
|
||||
if (actual !== expected && !(isOptional && actual === undefined)) {
|
||||
$ERROR("Option value " + value + " for property " + property +
|
||||
" was not accepted; got " + actual + " instead.");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// test that invalid values are rejected
|
||||
if (type === "string") {
|
||||
var invalidValues = ["invalidValue", -1, null];
|
||||
// assume that we won't have values in caseless scripts
|
||||
if (values[0].toUpperCase() !== values[0]) {
|
||||
invalidValues.push(values[0].toUpperCase());
|
||||
} else {
|
||||
invalidValues.push(values[0].toLowerCase());
|
||||
}
|
||||
invalidValues.forEach(function (value) {
|
||||
options = {};
|
||||
options[property] = value;
|
||||
addExtraOptions(options, value, testOptions);
|
||||
error = undefined;
|
||||
try {
|
||||
obj = new Constructor(undefined, options);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
if (error === undefined) {
|
||||
$ERROR("Invalid option value " + value + " for property " + property + " was not rejected.");
|
||||
} else if (error.name !== "RangeError") {
|
||||
$ERROR("Invalid option value " + value + " for property " + property + " was rejected with wrong error " + error.name + ".");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// test that fallback value or another valid value is used if no options value is provided
|
||||
if (!noReturn) {
|
||||
options = {};
|
||||
addExtraOptions(options, undefined, testOptions);
|
||||
obj = new Constructor(undefined, options);
|
||||
actual = obj.resolvedOptions()[property];
|
||||
if (!(isOptional && actual === undefined)) {
|
||||
if (fallback !== undefined) {
|
||||
if (actual !== fallback) {
|
||||
$ERROR("Option fallback value " + fallback + " for property " + property +
|
||||
" was not used; got " + actual + " instead.");
|
||||
}
|
||||
} else {
|
||||
if (values.indexOf(actual) === -1 && !(isILD && actual === undefined)) {
|
||||
$ERROR("Invalid value " + actual + " returned for property " + property + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the named property of the given object has a valid value
|
||||
* and the default attributes of the properties of an object literal.
|
||||
* @param {Object} obj the object to be tested.
|
||||
* @param {string} property the name of the property
|
||||
* @param {Function|Array} valid either a function that tests value for validity and returns a boolean,
|
||||
* an array of valid values.
|
||||
* @exception if the property has an invalid value.
|
||||
*/
|
||||
function testProperty(obj, property, valid) {
|
||||
var desc = Object.getOwnPropertyDescriptor(obj, property);
|
||||
if (!desc.writable) {
|
||||
$ERROR("Property " + property + " must be writable.");
|
||||
}
|
||||
if (!desc.enumerable) {
|
||||
$ERROR("Property " + property + " must be enumerable.");
|
||||
}
|
||||
if (!desc.configurable) {
|
||||
$ERROR("Property " + property + " must be configurable.");
|
||||
}
|
||||
var value = desc.value;
|
||||
var isValid = (typeof valid === "function") ? valid(value) : (valid.indexOf(value) !== -1);
|
||||
if (!isValid) {
|
||||
$ERROR("Property value " + value + " is not allowed for property " + property + ".");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the named property of the given object, if present at all, has a valid value
|
||||
* and the default attributes of the properties of an object literal.
|
||||
* @param {Object} obj the object to be tested.
|
||||
* @param {string} property the name of the property
|
||||
* @param {Function|Array} valid either a function that tests value for validity and returns a boolean,
|
||||
* an array of valid values.
|
||||
* @exception if the property is present and has an invalid value.
|
||||
*/
|
||||
function mayHaveProperty(obj, property, valid) {
|
||||
if (obj.hasOwnProperty(property)) {
|
||||
testProperty(obj, property, valid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the given object has the named property with a valid value
|
||||
* and the default attributes of the properties of an object literal.
|
||||
* @param {Object} obj the object to be tested.
|
||||
* @param {string} property the name of the property
|
||||
* @param {Function|Array} valid either a function that tests value for validity and returns a boolean,
|
||||
* an array of valid values.
|
||||
* @exception if the property is missing or has an invalid value.
|
||||
*/
|
||||
function mustHaveProperty(obj, property, valid) {
|
||||
if (!obj.hasOwnProperty(property)) {
|
||||
$ERROR("Object is missing property " + property + ".");
|
||||
}
|
||||
testProperty(obj, property, valid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the given object does not have the named property.
|
||||
* @param {Object} obj the object to be tested.
|
||||
* @param {string} property the name of the property
|
||||
* @exception if the property is present.
|
||||
*/
|
||||
function mustNotHaveProperty(obj, property) {
|
||||
if (obj.hasOwnProperty(property)) {
|
||||
$ERROR("Object has property it mustn't have: " + property + ".");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether name is a valid BCP 47 numbering system name
|
||||
* and not excluded from use in the ECMAScript Internationalization API.
|
||||
* @param {string} name the name to be tested.
|
||||
* @return {boolean} whether name is a valid BCP 47 numbering system name and
|
||||
* allowed for use in the ECMAScript Internationalization API.
|
||||
*/
|
||||
|
||||
function isValidNumberingSystem(name) {
|
||||
|
||||
// source: CLDR file common/bcp47/number.xml; version CLDR 21.
|
||||
var numberingSystems = [
|
||||
"arab",
|
||||
"arabext",
|
||||
"armn",
|
||||
"armnlow",
|
||||
"bali",
|
||||
"beng",
|
||||
"brah",
|
||||
"cakm",
|
||||
"cham",
|
||||
"deva",
|
||||
"ethi",
|
||||
"finance",
|
||||
"fullwide",
|
||||
"geor",
|
||||
"grek",
|
||||
"greklow",
|
||||
"gujr",
|
||||
"guru",
|
||||
"hanidec",
|
||||
"hans",
|
||||
"hansfin",
|
||||
"hant",
|
||||
"hantfin",
|
||||
"hebr",
|
||||
"java",
|
||||
"jpan",
|
||||
"jpanfin",
|
||||
"kali",
|
||||
"khmr",
|
||||
"knda",
|
||||
"osma",
|
||||
"lana",
|
||||
"lanatham",
|
||||
"laoo",
|
||||
"latn",
|
||||
"lepc",
|
||||
"limb",
|
||||
"mlym",
|
||||
"mong",
|
||||
"mtei",
|
||||
"mymr",
|
||||
"mymrshan",
|
||||
"native",
|
||||
"nkoo",
|
||||
"olck",
|
||||
"orya",
|
||||
"roman",
|
||||
"romanlow",
|
||||
"saur",
|
||||
"shrd",
|
||||
"sora",
|
||||
"sund",
|
||||
"talu",
|
||||
"takr",
|
||||
"taml",
|
||||
"tamldec",
|
||||
"telu",
|
||||
"thai",
|
||||
"tibt",
|
||||
"traditio",
|
||||
"vaii"
|
||||
];
|
||||
|
||||
var excluded = [
|
||||
"finance",
|
||||
"native",
|
||||
"traditio"
|
||||
];
|
||||
|
||||
|
||||
return numberingSystems.indexOf(name) !== -1 && excluded.indexOf(name) === -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides the digits of numbering systems with simple digit mappings,
|
||||
* as specified in 11.3.2.
|
||||
*/
|
||||
|
||||
var numberingSystemDigits = {
|
||||
arab: "٠١٢٣٤٥٦٧٨٩",
|
||||
arabext: "۰۱۲۳۴۵۶۷۸۹",
|
||||
beng: "০১২৩৪৫৬৭৮৯",
|
||||
deva: "०१२३४५६७८९",
|
||||
fullwide: "0123456789",
|
||||
gujr: "૦૧૨૩૪૫૬૭૮૯",
|
||||
guru: "੦੧੨੩੪੫੬੭੮੯",
|
||||
hanidec: "〇一二三四五六七八九",
|
||||
khmr: "០១២៣៤៥៦៧៨៩",
|
||||
knda: "೦೧೨೩೪೫೬೭೮೯",
|
||||
laoo: "໐໑໒໓໔໕໖໗໘໙",
|
||||
latn: "0123456789",
|
||||
mlym: "൦൧൨൩൪൫൬൭൮൯",
|
||||
mong: "᠐᠑᠒᠓᠔᠕᠖᠗᠘᠙",
|
||||
mymr: "၀၁၂၃၄၅၆၇၈၉",
|
||||
orya: "୦୧୨୩୪୫୬୭୮୯",
|
||||
tamldec: "௦௧௨௩௪௫௬௭௮௯",
|
||||
telu: "౦౧౨౩౪౫౬౭౮౯",
|
||||
thai: "๐๑๒๓๔๕๖๗๘๙",
|
||||
tibt: "༠༡༢༣༤༥༦༧༨༩"
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tests that number formatting is handled correctly. The function checks that the
|
||||
* digit sequences in formatted output are as specified, converted to the
|
||||
* selected numbering system, and embedded in consistent localized patterns.
|
||||
* @param {Array} locales the locales to be tested.
|
||||
* @param {Array} numberingSystems the numbering systems to be tested.
|
||||
* @param {Object} options the options to pass to Intl.NumberFormat. Options
|
||||
* must include {useGrouping: false}, and must cause 1.1 to be formatted
|
||||
* pre- and post-decimal digits.
|
||||
* @param {Object} testData maps input data (in ES5 9.3.1 format) to expected output strings
|
||||
* in unlocalized format with Western digits.
|
||||
*/
|
||||
|
||||
function testNumberFormat(locales, numberingSystems, options, testData) {
|
||||
locales.forEach(function (locale) {
|
||||
numberingSystems.forEach(function (numbering) {
|
||||
var digits = numberingSystemDigits[numbering];
|
||||
var format = new Intl.NumberFormat([locale + "-u-nu-" + numbering], options);
|
||||
|
||||
function getPatternParts(positive) {
|
||||
var n = positive ? 1.1 : -1.1;
|
||||
var formatted = format.format(n);
|
||||
var oneoneRE = "([^" + digits + "]*)[" + digits + "]+([^" + digits + "]+)[" + digits + "]+([^" + digits + "]*)";
|
||||
var match = formatted.match(new RegExp(oneoneRE));
|
||||
if (match === null) {
|
||||
$ERROR("Unexpected formatted " + n + " for " +
|
||||
format.resolvedOptions().locale + " and options " +
|
||||
JSON.stringify(options) + ": " + formatted);
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
function toNumbering(raw) {
|
||||
return raw.replace(/[0-9]/g, function (digit) {
|
||||
return digits[digit.charCodeAt(0) - "0".charCodeAt(0)];
|
||||
});
|
||||
}
|
||||
|
||||
function buildExpected(raw, patternParts) {
|
||||
var period = raw.indexOf(".");
|
||||
if (period === -1) {
|
||||
return patternParts[1] + toNumbering(raw) + patternParts[3];
|
||||
} else {
|
||||
return patternParts[1] +
|
||||
toNumbering(raw.substring(0, period)) +
|
||||
patternParts[2] +
|
||||
toNumbering(raw.substring(period + 1)) +
|
||||
patternParts[3];
|
||||
}
|
||||
}
|
||||
|
||||
if (format.resolvedOptions().numberingSystem === numbering) {
|
||||
// figure out prefixes, infixes, suffixes for positive and negative values
|
||||
var posPatternParts = getPatternParts(true);
|
||||
var negPatternParts = getPatternParts(false);
|
||||
|
||||
Object.getOwnPropertyNames(testData).forEach(function (input) {
|
||||
var rawExpected = testData[input];
|
||||
var patternParts;
|
||||
if (rawExpected[0] === "-") {
|
||||
patternParts = negPatternParts;
|
||||
rawExpected = rawExpected.substring(1);
|
||||
} else {
|
||||
patternParts = posPatternParts;
|
||||
}
|
||||
var expected = buildExpected(rawExpected, patternParts);
|
||||
var actual = format.format(input);
|
||||
if (actual !== expected) {
|
||||
$ERROR("Formatted value for " + input + ", " +
|
||||
format.resolvedOptions().locale + " and options " +
|
||||
JSON.stringify(options) + " is " + actual + "; expected " + expected + ".");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the components of date-time formats.
|
||||
* @return {Array} an array with all date-time components.
|
||||
*/
|
||||
|
||||
function getDateTimeComponents() {
|
||||
return ["weekday", "era", "year", "month", "day", "hour", "minute", "second", "timeZoneName"];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the valid values for the given date-time component, as specified
|
||||
* by the table in section 12.1.1.
|
||||
* @param {string} component a date-time component.
|
||||
* @return {Array} an array with the valid values for the component.
|
||||
*/
|
||||
|
||||
function getDateTimeComponentValues(component) {
|
||||
|
||||
var components = {
|
||||
weekday: ["narrow", "short", "long"],
|
||||
era: ["narrow", "short", "long"],
|
||||
year: ["2-digit", "numeric"],
|
||||
month: ["2-digit", "numeric", "narrow", "short", "long"],
|
||||
day: ["2-digit", "numeric"],
|
||||
hour: ["2-digit", "numeric"],
|
||||
minute: ["2-digit", "numeric"],
|
||||
second: ["2-digit", "numeric"],
|
||||
timeZoneName: ["short", "long"]
|
||||
};
|
||||
|
||||
var result = components[component];
|
||||
if (result === undefined) {
|
||||
$ERROR("Internal error: No values defined for date-time component " + component + ".");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests that the given value is valid for the given date-time component.
|
||||
* @param {string} component a date-time component.
|
||||
* @param {string} value the value to be tested.
|
||||
* @return {boolean} true if the test succeeds.
|
||||
* @exception if the test fails.
|
||||
*/
|
||||
|
||||
function testValidDateTimeComponentValue(component, value) {
|
||||
if (getDateTimeComponentValues(component).indexOf(value) === -1) {
|
||||
$ERROR("Invalid value " + value + " for date-time component " + component + ".");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifies that the actual array matches the expected one in length, elements,
|
||||
* and element order.
|
||||
* @param {Array} expected the expected array.
|
||||
* @param {Array} actual the actual array.
|
||||
* @return {boolean} true if the test succeeds.
|
||||
* @exception if the test fails.
|
||||
*/
|
||||
function testArraysAreSame(expected, actual) {
|
||||
for (i = 0; i < Math.max(actual.length, expected.length); i++) {
|
||||
if (actual[i] !== expected[i]) {
|
||||
$ERROR("Result array element at index " + i + " should be \"" +
|
||||
expected[i] + "\" but is \"" + actual[i] + "\".");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
{"numTests":66,"testSuite":["json/intl402.json"]}
|
||||
{"numTests":137,"testSuite":["json/intl402.json"]}
|
Loading…
x
Reference in New Issue
Block a user