Skip to content

Commit e058f47

Browse files
LiviaMedeirosRafaelGSS
authored andcommitted
test: improve observable ICU behaviour coverage
PR-URL: #42683 Refs: #42440 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent d23debb commit e058f47

File tree

2 files changed

+289
-6
lines changed

2 files changed

+289
-6
lines changed

test/parallel/test-icu-env.js

+288
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const { execFileSync } = require('child_process');
5+
6+
// system-icu should not be tested
7+
const hasBuiltinICU = process.config.variables.icu_gyp_path === 'tools/icu/icu-generic.gyp';
8+
if (!hasBuiltinICU)
9+
common.skip('system ICU');
10+
11+
// small-icu doesn't support non-English locales
12+
const hasFullICU = (() => {
13+
try {
14+
const january = new Date(9e8);
15+
const spanish = new Intl.DateTimeFormat('es', { month: 'long' });
16+
return spanish.format(january) === 'enero';
17+
} catch {
18+
return false;
19+
}
20+
})();
21+
if (!hasFullICU)
22+
common.skip('small ICU');
23+
24+
const icuVersionMajor = Number(process.config.variables.icu_ver_major ?? 0);
25+
if (icuVersionMajor < 71)
26+
common.skip('ICU too old');
27+
28+
29+
function runEnvOutside(addEnv, code, ...args) {
30+
return execFileSync(
31+
process.execPath,
32+
['-e', `process.stdout.write(String(${code}));`],
33+
{ env: { ...process.env, ...addEnv }, encoding: 'utf8' }
34+
);
35+
}
36+
37+
function runEnvInside(addEnv, func, ...args) {
38+
Object.assign(process.env, addEnv); // side effects!
39+
return func(...args);
40+
}
41+
42+
function isPack(array) {
43+
const firstItem = array[0];
44+
return array.every((item) => item === firstItem);
45+
}
46+
47+
function isSet(array) {
48+
const deduped = new Set(array);
49+
return array.length === deduped.size;
50+
}
51+
52+
53+
const localesISO639 = [
54+
'eng', 'cmn', 'hin', 'spa',
55+
'fra', 'arb', 'ben', 'rus',
56+
'por', 'urd', 'ind', 'deu',
57+
'jpn', 'pcm', 'mar', 'tel',
58+
];
59+
60+
const locales = [
61+
'en', 'zh', 'hi', 'es',
62+
'fr', 'ar', 'bn', 'ru',
63+
'pt', 'ur', 'id', 'de',
64+
'ja', 'pcm', 'mr', 'te',
65+
];
66+
67+
// These must not overlap
68+
const zones = [
69+
'America/New_York',
70+
'UTC',
71+
'Asia/Irkutsk',
72+
'Australia/North',
73+
'Antarctica/South_Pole',
74+
];
75+
76+
77+
assert.deepStrictEqual(Intl.getCanonicalLocales(localesISO639), locales);
78+
79+
80+
// On some platforms these keep original locale (for example, 'January')
81+
const enero = runEnvOutside(
82+
{ LANG: 'es' },
83+
'new Intl.DateTimeFormat(undefined, { month: "long" } ).format(new Date(9e8))'
84+
);
85+
const janvier = runEnvOutside(
86+
{ LANG: 'fr' },
87+
'new Intl.DateTimeFormat(undefined, { month: "long" } ).format(new Date(9e8))'
88+
);
89+
const isMockable = enero !== janvier;
90+
91+
// Tests with mocked env
92+
if (isMockable) {
93+
assert.strictEqual(
94+
isSet(zones.map((TZ) => runEnvOutside({ TZ }, 'new Date(333333333333).toString()'))),
95+
true
96+
);
97+
assert.strictEqual(
98+
isSet(zones.map((TZ) => runEnvOutside({ TZ }, 'new Date(333333333333).toLocaleString()'))),
99+
true
100+
);
101+
assert.deepStrictEqual(
102+
locales.map((LANG) => runEnvOutside({ LANG, TZ: 'Europe/Zurich' }, 'new Date(333333333333).toString()')),
103+
[
104+
'Fri Jul 25 1980 01:35:33 GMT+0100 (Central European Standard Time)',
105+
'Fri Jul 25 1980 01:35:33 GMT+0100 (中欧标准时间)',
106+
'Fri Jul 25 1980 01:35:33 GMT+0100 (मध्य यूरोपीय मानक समय)',
107+
'Fri Jul 25 1980 01:35:33 GMT+0100 (hora estándar de Europa central)',
108+
'Fri Jul 25 1980 01:35:33 GMT+0100 (heure normale d’Europe centrale)',
109+
'Fri Jul 25 1980 01:35:33 GMT+0100 (توقيت وسط أوروبا الرسمي)',
110+
'Fri Jul 25 1980 01:35:33 GMT+0100 (মধ্য ইউরোপীয় মানক সময়)',
111+
'Fri Jul 25 1980 01:35:33 GMT+0100 (Центральная Европа, стандартное время)',
112+
'Fri Jul 25 1980 01:35:33 GMT+0100 (Horário Padrão da Europa Central)',
113+
'Fri Jul 25 1980 01:35:33 GMT+0100 (وسطی یورپ کا معیاری وقت)',
114+
'Fri Jul 25 1980 01:35:33 GMT+0100 (Waktu Standar Eropa Tengah)',
115+
'Fri Jul 25 1980 01:35:33 GMT+0100 (Mitteleuropäische Normalzeit)',
116+
'Fri Jul 25 1980 01:35:33 GMT+0100 (中央ヨーロッパ標準時)',
117+
'Fri Jul 25 1980 01:35:33 GMT+0100 (Mídúl Yúrop Fíksd Taim)',
118+
'Fri Jul 25 1980 01:35:33 GMT+0100 (मध्‍य युरोपियन प्रमाण वेळ)',
119+
'Fri Jul 25 1980 01:35:33 GMT+0100 (సెంట్రల్ యూరోపియన్ ప్రామాణిక సమయం)',
120+
]
121+
);
122+
assert.deepStrictEqual(
123+
locales.map((LANG) => runEnvOutside({ LANG, TZ: 'Europe/Zurich' }, 'new Date(333333333333).toLocaleString()')),
124+
[
125+
'7/25/1980, 1:35:33 AM',
126+
'1980/7/25 01:35:33',
127+
'25/7/1980, 1:35:33 am',
128+
'25/7/1980, 1:35:33',
129+
'25/07/1980 01:35:33',
130+
'٢٥‏/٧‏/١٩٨٠, ١:٣٥:٣٣ ص',
131+
'২৫/৭/১৯৮০ ১:৩৫:৩৩ AM',
132+
'25.07.1980, 01:35:33',
133+
'25/07/1980 01:35:33',
134+
'25/7/1980 1:35:33 AM',
135+
'25/7/1980 01.35.33',
136+
'25.7.1980, 01:35:33',
137+
'1980/7/25 1:35:33',
138+
'25/7/1980 01:35:33',
139+
'२५/७/१९८०, १:३५:३३ AM',
140+
'25/7/1980 1:35:33 AM',
141+
]
142+
);
143+
assert.strictEqual(
144+
runEnvOutside({ LANG: 'en' }, '["z", "ä"].sort(new Intl.Collator().compare)'),
145+
'ä,z'
146+
);
147+
assert.strictEqual(
148+
runEnvOutside({ LANG: 'sv' }, '["z", "ä"].sort(new Intl.Collator().compare)'),
149+
'z,ä'
150+
);
151+
assert.deepStrictEqual(
152+
locales.map(
153+
(LANG) => runEnvOutside({ LANG, TZ: 'Europe/Zurich' }, 'new Intl.DateTimeFormat().format(333333333333)')
154+
),
155+
[
156+
'7/25/1980', '1980/7/25',
157+
'25/7/1980', '25/7/1980',
158+
'25/07/1980', '٢٥‏/٧‏/١٩٨٠',
159+
'২৫/৭/১৯৮০', '25.07.1980',
160+
'25/07/1980', '25/7/1980',
161+
'25/7/1980', '25.7.1980',
162+
'1980/7/25', '25/7/1980',
163+
'२५/७/१९८०', '25/7/1980',
164+
]
165+
);
166+
assert.deepStrictEqual(
167+
locales.map((LANG) => runEnvOutside({ LANG }, 'new Intl.DisplayNames(undefined, { type: "region" }).of("CH")')),
168+
[
169+
'Switzerland', '瑞士',
170+
'स्विट्ज़रलैंड', 'Suiza',
171+
'Suisse', 'سويسرا',
172+
'সুইজারল্যান্ড', 'Швейцария',
173+
'Suíça', 'سوئٹزر لینڈ',
174+
'Swiss', 'Schweiz',
175+
'スイス', 'Swítsaland',
176+
'स्वित्झर्लंड', 'స్విట్జర్లాండ్',
177+
]
178+
);
179+
assert.deepStrictEqual(
180+
locales.map((LANG) => runEnvOutside({ LANG }, 'new Intl.NumberFormat().format(275760.913)')),
181+
[
182+
'275,760.913', '275,760.913',
183+
'2,75,760.913', '275.760,913',
184+
'275 760,913', '٢٧٥٬٧٦٠٫٩١٣',
185+
'২,৭৫,৭৬০.৯১৩', '275 760,913',
186+
'275.760,913', '275,760.913',
187+
'275.760,913', '275.760,913',
188+
'275,760.913', '275,760.913',
189+
'२,७५,७६०.९१३', '2,75,760.913',
190+
]
191+
);
192+
assert.deepStrictEqual(
193+
locales.map((LANG) => runEnvOutside({ LANG }, 'new Intl.PluralRules().select(0)')),
194+
[
195+
'other', 'other', 'one', 'other',
196+
'one', 'zero', 'one', 'many',
197+
'one', 'other', 'other', 'other',
198+
'other', 'one', 'other', 'other',
199+
]
200+
);
201+
assert.deepStrictEqual(
202+
locales.map((LANG) => runEnvOutside({ LANG }, 'new Intl.RelativeTimeFormat().format(-586920.617, "hour")')),
203+
[
204+
'586,920.617 hours ago',
205+
'586,920.617小时前',
206+
'5,86,920.617 घंटे पहले',
207+
'hace 586.920,617 horas',
208+
'il y a 586 920,617 heures',
209+
'قبل ٥٨٦٬٩٢٠٫٦١٧ ساعة',
210+
'৫,৮৬,৯২০.৬১৭ ঘন্টা আগে',
211+
'586 920,617 часа назад',
212+
'há 586.920,617 horas',
213+
'586,920.617 گھنٹے پہلے',
214+
'586.920,617 jam yang lalu',
215+
'vor 586.920,617 Stunden',
216+
'586,920.617 時間前',
217+
'586,920.617 áwa wé dọ́n pas',
218+
'५,८६,९२०.६१७ तासांपूर्वी',
219+
'5,86,920.617 గంటల క్రితం',
220+
]
221+
);
222+
}
223+
224+
225+
// Tests with process.env mutated inside
226+
{
227+
// process.env.TZ is not intercepted in Workers
228+
if (common.isMainThread) {
229+
assert.strictEqual(
230+
isSet(zones.map((TZ) => runEnvInside({ TZ }, () => new Date(333333333333).toString()))),
231+
true
232+
);
233+
assert.strictEqual(
234+
isSet(zones.map((TZ) => runEnvInside({ TZ }, () => new Date(333333333333).toLocaleString()))),
235+
true
236+
);
237+
} else {
238+
assert.strictEqual(
239+
isPack(zones.map((TZ) => runEnvInside({ TZ }, () => new Date(333333333333).toString()))),
240+
true
241+
);
242+
assert.strictEqual(
243+
isPack(zones.map((TZ) => runEnvInside({ TZ }, () => new Date(333333333333).toLocaleString()))),
244+
true
245+
);
246+
}
247+
248+
assert.strictEqual(
249+
isPack(locales.map((LANG) => runEnvInside({ LANG, TZ: 'Europe/Zurich' }, () => new Date(333333333333).toString()))),
250+
true
251+
);
252+
assert.strictEqual(
253+
isPack(locales.map(
254+
(LANG) => runEnvInside({ LANG, TZ: 'Europe/Zurich' }, () => new Date(333333333333).toLocaleString())
255+
)),
256+
true
257+
);
258+
assert.deepStrictEqual(
259+
runEnvInside({ LANG: 'en' }, () => ['z', 'ä'].sort(new Intl.Collator().compare)),
260+
runEnvInside({ LANG: 'sv' }, () => ['z', 'ä'].sort(new Intl.Collator().compare))
261+
);
262+
assert.strictEqual(
263+
isPack(locales.map(
264+
(LANG) => runEnvInside({ LANG, TZ: 'Europe/Zurich' }, () => new Intl.DateTimeFormat().format(333333333333))
265+
)),
266+
true
267+
);
268+
assert.strictEqual(
269+
isPack(locales.map(
270+
(LANG) => runEnvInside({ LANG }, () => new Intl.DisplayNames(undefined, { type: 'region' }).of('CH'))
271+
)),
272+
true
273+
);
274+
assert.strictEqual(
275+
isPack(locales.map((LANG) => runEnvInside({ LANG }, () => new Intl.NumberFormat().format(275760.913)))),
276+
true
277+
);
278+
assert.strictEqual(
279+
isPack(locales.map((LANG) => runEnvInside({ LANG }, () => new Intl.PluralRules().select(0)))),
280+
true
281+
);
282+
assert.strictEqual(
283+
isPack(locales.map(
284+
(LANG) => runEnvInside({ LANG }, () => new Intl.RelativeTimeFormat().format(-586920.617, 'hour'))
285+
)),
286+
true
287+
);
288+
}

test/parallel/test-process-env-tz.js

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
11
'use strict';
2-
3-
// Set the locale to a known good value because it affects ICU's date string
4-
// formatting. Setting LC_ALL needs to happen before the first call to
5-
// `icu::Locale::getDefault()` because ICU caches the result.
6-
process.env.LC_ALL = 'C';
7-
82
const common = require('../common');
93
const assert = require('assert');
104

@@ -31,6 +25,7 @@ if (date.toString().includes('(Central European Time)') ||
3125
common.skip('tzdata too old');
3226
}
3327

28+
// Text representation of timezone depends on locale in environment
3429
assert.match(
3530
date.toString(),
3631
/^Sat Apr 14 2018 14:34:56 GMT\+0200 \(.+\)$/);

0 commit comments

Comments
 (0)