mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
7f091cf057
Summary: The en-ZA locale was recently updated: https://github.com/nodejs/node/issues/48120 This caused test failures which I was happy about, until I saw af-ZA is still using the old separators. Test Plan: Tests failed locally when using the latest node 18, then passed after this change. Reviewers: jarek Reviewed By: jarek Differential Revision: https://phab.getgrist.com/D4079
186 lines
10 KiB
TypeScript
186 lines
10 KiB
TypeScript
import {DocumentSettings} from 'app/common/DocumentSettings';
|
||
import {NumberFormatOptions} from 'app/common/NumberFormat';
|
||
import {parseDateTime} from 'app/common/parseDate';
|
||
|
||
import {createFormatter, DateTimeFormatOptions} from "app/common/ValueFormatter";
|
||
import {assert} from 'chai';
|
||
|
||
const defaultDocSettings = {
|
||
locale: 'en-US'
|
||
};
|
||
|
||
const dateNumber = parseDateTime("2020-10-31 12:34:56", {});
|
||
|
||
describe("ValueFormatter", function() {
|
||
describe("DateFormatter", function() {
|
||
|
||
function check(expected: string, dateFormat?: string) {
|
||
for (const value of [dateNumber, ["d", dateNumber], ["D", dateNumber, "UTC"]]) {
|
||
const actual = createFormatter("Date", {dateFormat}, defaultDocSettings).formatAny(value);
|
||
assert.equal(actual, expected, String(value));
|
||
}
|
||
}
|
||
|
||
it("should format dates", function() {
|
||
check("31/10/2020", "DD/MM/YYYY");
|
||
check("10/31/2020", "MM/DD/YYYY");
|
||
check("2020-10-31"); // ISO by default
|
||
});
|
||
});
|
||
|
||
describe("DateTimeFormatter", function() {
|
||
function check(expected: string, options: DateTimeFormatOptions, timezone: string = "UTC") {
|
||
for (const value of [dateNumber, ["d", dateNumber], ["D", dateNumber, timezone]]) {
|
||
const actual = createFormatter(`DateTime:${timezone}`, options, defaultDocSettings).formatAny(value);
|
||
assert.equal(actual, expected, String(value));
|
||
}
|
||
}
|
||
|
||
it("should format datetimes", function() {
|
||
check("31/10/2020 12:34:56", {dateFormat: "DD/MM/YYYY", timeFormat: "HH:mm:ss"});
|
||
check("10/31/2020 12:34", {dateFormat: "MM/DD/YYYY", timeFormat: "HH:mm"});
|
||
check("2020-10-31 12:34pm", {}); // default formats
|
||
|
||
check("31/10/2020 08:34:56", {dateFormat: "DD/MM/YYYY", timeFormat: "HH:mm:ss"}, 'America/New_York');
|
||
check("10/31/2020 08:34", {dateFormat: "MM/DD/YYYY", timeFormat: "HH:mm"}, 'America/New_York');
|
||
check("2020-10-31 8:34am", {}, 'America/New_York'); // default formats
|
||
});
|
||
});
|
||
|
||
describe("NumericFormatter", function() {
|
||
function fmt(options: NumberFormatOptions, value: number, docSettings: DocumentSettings) {
|
||
return createFormatter("Numeric", options, docSettings).formatAny(value);
|
||
}
|
||
|
||
function checkDefault(options: NumberFormatOptions, value: number, expected: string) {
|
||
assert.equal(fmt(options, value, defaultDocSettings), expected);
|
||
}
|
||
|
||
it("should support plain format", function() {
|
||
checkDefault({}, 0, '0');
|
||
checkDefault({}, NaN, 'NaN');
|
||
checkDefault({}, Infinity, '∞');
|
||
checkDefault({}, -Infinity, '-∞');
|
||
checkDefault({}, 0.67, '0.67');
|
||
checkDefault({}, -1234.56, '-1234.56');
|
||
checkDefault({}, -121e+25, '-1210000000000000000000000000');
|
||
checkDefault({}, 1.015e-8, '0.0000000102'); // maxDecimals defaults to 10 here.
|
||
});
|
||
|
||
it('should support min/max decimals', function() {
|
||
checkDefault({decimals: 2, maxDecimals: 4}, 12, '12.00');
|
||
checkDefault({decimals: 2, maxDecimals: 4}, -1.00015, '-1.0002');
|
||
checkDefault({decimals: 2, maxDecimals: 6}, -1.00015, '-1.00015');
|
||
checkDefault({decimals: 6, maxDecimals: 6}, -1.00015, '-1.000150');
|
||
checkDefault({decimals: 6, maxDecimals: 0}, -1.00015, '-1.000150');
|
||
checkDefault({decimals: 0, maxDecimals: 2}, 12.0001, '12');
|
||
checkDefault({decimals: 0, maxDecimals: 2}, 12.001, '12');
|
||
checkDefault({decimals: 0, maxDecimals: 2}, 12.005, '12.01');
|
||
checkDefault({maxDecimals: 8}, 1.015e-8, '0.00000001');
|
||
checkDefault({maxDecimals: 7}, 1.015e-8, '0');
|
||
|
||
// Out-of-range values get clamped.
|
||
checkDefault({decimals:-2, maxDecimals:3}, -1.2345, "-1.235");
|
||
checkDefault({decimals:-2, maxDecimals:-3}, -1.2345, "-1");
|
||
});
|
||
|
||
it('should support thousand separators', function() {
|
||
checkDefault({numMode: 'decimal', decimals: 4}, 1000000, '1,000,000.0000');
|
||
checkDefault({numMode: 'decimal'}, -1234.56, '-1,234.56');
|
||
checkDefault({numMode: 'decimal'}, -121e+25, '-1,210,000,000,000,000,000,000,000,000');
|
||
checkDefault({numMode: 'decimal'}, 0.1234567, '0.123'); // maxDecimals defaults to 3 here
|
||
checkDefault({numMode: 'decimal'}, 1.015e-8, '0');
|
||
checkDefault({numMode: 'decimal', maxDecimals: 10}, 1.015e-8, '0.0000000102');
|
||
});
|
||
|
||
it('should support currency mode', function() {
|
||
// Test currency formatting with default doc settings (locale: 'en-US').
|
||
checkDefault({numMode: 'currency'}, 1000000, '$1,000,000.00');
|
||
checkDefault({numMode: 'currency', decimals: 4}, 1000000, '$1,000,000.0000');
|
||
checkDefault({numMode: 'currency'}, -1234.565, '-$1,234.57');
|
||
checkDefault({numMode: 'currency'}, -121e+25, '-$1,210,000,000,000,000,000,000,000,000.00');
|
||
checkDefault({numMode: 'currency'}, 0.1234567, '$0.12'); // maxDecimals defaults to 2 here
|
||
checkDefault({numMode: 'currency', maxDecimals: 0}, 12.34567, '$12.35');
|
||
checkDefault({numMode: 'currency', decimals: 0, maxDecimals: 0}, 12.34567, '$12');
|
||
checkDefault({numMode: 'currency'}, 1.015e-8, '$0.00');
|
||
checkDefault({numMode: 'currency', maxDecimals: 10}, 1.015e-8, '$0.0000000102');
|
||
checkDefault({numMode: 'currency'}, -1.015e-8, '-$0.00');
|
||
|
||
// Test currency formatting with custom locales.
|
||
assert.equal(fmt({numMode: 'currency'}, 1000000, {locale: 'es-ES'}), '1.000.000,00 €');
|
||
assert.equal(fmt({numMode: 'currency', decimals: 4}, 1000000, {locale: 'en-NZ'}), '$1,000,000.0000');
|
||
assert.equal(fmt({numMode: 'currency'}, -1234.565, {locale: 'de-CH'}), 'CHF-1’234.57');
|
||
assert.equal(fmt({numMode: 'currency'}, -121e+25, {locale: 'es-AR'}),
|
||
'-$ 1.210.000.000.000.000.000.000.000.000,00');
|
||
assert.equal(fmt({numMode: 'currency'}, 0.1234567, {locale: 'fr-BE'}), '0,12 €');
|
||
assert.equal(fmt({numMode: 'currency', maxDecimals: 0}, 12.34567, {locale: 'en-GB'}), '£12.35');
|
||
assert.equal(fmt({numMode: 'currency', decimals: 0, maxDecimals: 0}, 12.34567, {locale: 'en-IE'}), '€12');
|
||
assert.equal(fmt({numMode: 'currency'}, 1.015e-8, {locale: 'af-ZA'}), 'R 0,00');
|
||
assert.equal(fmt({numMode: 'currency', maxDecimals: 10}, 1.015e-8, {locale: 'en-CA'}), '$0.0000000102');
|
||
assert.equal(fmt({numMode: 'currency'}, -1.015e-8, {locale: 'nl-BE'}), '€ -0,00');
|
||
|
||
// Test currency formatting with custom currency AND locales (e.g. column-specific currency setting).
|
||
assert.equal(fmt({numMode: 'currency'}, 1000000, {locale: 'es-ES', currency: 'USD'}), '1.000.000,00 $');
|
||
assert.equal(
|
||
fmt({numMode: 'currency', decimals: 4}, 1000000, {locale: 'en-NZ', currency: 'JPY'}),
|
||
'¥1,000,000.0000');
|
||
assert.equal(fmt({numMode: 'currency'}, -1234.565, {locale: 'de-CH', currency: 'JMD'}), '$-1’234.57');
|
||
assert.equal(
|
||
fmt({numMode: 'currency'}, -121e+25, {locale: 'es-AR', currency: 'GBP'}),
|
||
'-£ 1.210.000.000.000.000.000.000.000.000,00');
|
||
assert.equal(fmt({numMode: 'currency'}, 0.1234567, {locale: 'fr-BE', currency: 'GBP'}), '0,12 £');
|
||
assert.equal(fmt({numMode: 'currency', maxDecimals: 0}, 12.34567, {locale: 'en-GB', currency: 'USD'}), '$12.35');
|
||
assert.equal(
|
||
fmt({numMode: 'currency', decimals: 0, maxDecimals: 0}, 12.34567, {locale: 'en-IE', currency: 'SGD'}),
|
||
'$12');
|
||
assert.equal(fmt({numMode: 'currency'}, 1.015e-8, {locale: 'af-ZA', currency: 'HKD'}), '$0,00');
|
||
assert.equal(
|
||
fmt({numMode: 'currency', maxDecimals: 10}, 1.015e-8, {locale: 'en-CA', currency: 'RUB'}),
|
||
'₽0.0000000102');
|
||
assert.equal(fmt({numMode: 'currency'}, -1.015e-8, {locale: 'nl-BE', currency: 'USD'}), '$ -0,00');
|
||
});
|
||
|
||
it('should support percentages', function() {
|
||
checkDefault({numMode: 'percent'}, 0.5, '50%');
|
||
checkDefault({numMode: 'percent'}, -0.15, '-15%');
|
||
checkDefault({numMode: 'percent'}, 0.105, '11%');
|
||
checkDefault({numMode: 'percent', maxDecimals: 5}, 0.105, '10.5%');
|
||
checkDefault({numMode: 'percent', decimals: 5}, 0.105, '10.50000%');
|
||
checkDefault({numMode: 'percent', maxDecimals: 2}, 1.2345, '123.45%');
|
||
checkDefault({numMode: 'percent'}, -1234.567, '-123,457%'); // maxDecimals defaults to 0 here
|
||
checkDefault({numMode: 'percent'}, 1.015e-8, '0%');
|
||
checkDefault({numMode: 'percent', maxDecimals: 10}, 1.015e-8, '0.000001015%');
|
||
});
|
||
|
||
it('should support parentheses for negative numbers', function() {
|
||
checkDefault({numSign: 'parens', numMode: 'decimal'}, -1234.56, '(1,234.56)');
|
||
checkDefault({numSign: 'parens', numMode: 'decimal'}, +1234.56, ' 1,234.56 ');
|
||
checkDefault({numSign: 'parens', numMode: 'decimal'}, -121e+25, '(1,210,000,000,000,000,000,000,000,000)');
|
||
checkDefault({numSign: 'parens', numMode: 'decimal'}, 0.1234567, ' 0.123 ');
|
||
checkDefault({numSign: 'parens', numMode: 'decimal'}, 1.015e-8, ' 0 ');
|
||
checkDefault({numSign: 'parens', numMode: 'currency'}, -1234.565, '($1,234.57)');
|
||
checkDefault({numSign: 'parens', numMode: 'currency'}, -121e+20, '($12,100,000,000,000,000,000,000.00)');
|
||
checkDefault({numSign: 'parens', numMode: 'currency'}, 121e+20, ' $12,100,000,000,000,000,000,000.00 ');
|
||
checkDefault({numSign: 'parens', numMode: 'currency'}, 1.015e-8, ' $0.00 ');
|
||
checkDefault({numSign: 'parens', numMode: 'currency'}, -1.015e-8, '($0.00)');
|
||
checkDefault({numSign: 'parens'}, -1234.56, '(1234.56)');
|
||
checkDefault({numSign: 'parens'}, +1234.56, ' 1234.56 ');
|
||
checkDefault({numSign: 'parens', numMode: 'percent'}, -0.1234, '(12%)');
|
||
checkDefault({numSign: 'parens', numMode: 'percent'}, +0.1234, ' 12% ');
|
||
});
|
||
|
||
it('should support scientific mode', function() {
|
||
checkDefault({numMode: 'scientific'}, 0.5, '5E-1');
|
||
checkDefault({numMode: 'scientific'}, -0.15, '-1.5E-1');
|
||
checkDefault({numMode: 'scientific'}, -1234.56, '-1.235E3');
|
||
checkDefault({numMode: 'scientific'}, +1234.56, '1.235E3');
|
||
checkDefault({numMode: 'scientific'}, 1.015e-8, '1.015E-8');
|
||
checkDefault({numMode: 'scientific', maxDecimals: 10}, 1.015e-8, '1.015E-8');
|
||
checkDefault({numMode: 'scientific', decimals: 10}, 1.015e-8, '1.0150000000E-8');
|
||
checkDefault({numMode: 'scientific', maxDecimals: 2}, 1.015e-8, '1.02E-8');
|
||
checkDefault({numMode: 'scientific', maxDecimals: 1}, 1.015e-8, '1E-8');
|
||
checkDefault({numMode: 'scientific'}, -121e+25, '-1.21E27');
|
||
});
|
||
});
|
||
});
|