Skip to content

Commit 465a098

Browse files
committed
Thorough tests for all types' string parsers
Snapshot tests for millions of string inputs to each Temporal type's from() method, covering as many variations of the string format as possible.
1 parent fe209c8 commit 465a098

10 files changed

Lines changed: 675 additions & 0 deletions

‎polyfill/test/thorough/all.sh‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,37 +20,45 @@ for test in \
2020
dateaddition \
2121
datedifference \
2222
datemodify \
23+
dateparsing \
2324
dateroundtrip \
2425
datetimeaddition \
2526
datetimedifference \
2627
datetimemodify \
28+
datetimeparsing \
2729
datetimerounding \
2830
datetimeroundtrip \
2931
durationaddition \
3032
durationmodify \
33+
durationparsing \
3134
durationroundtrip \
3235
durationtotal \
3336
instantaddition \
3437
instantdifference \
38+
instantparsing \
3539
instantrounding \
3640
instantroundtrip \
41+
monthdayparsing \
3742
monthdayrefyear \
3843
monthdaymodify \
3944
monthdayroundtrip \
4045
startofday \
4146
timeaddition \
4247
timedifference \
4348
timemodify \
49+
timeparsing \
4450
timerounding \
4551
timeroundtrip \
4652
yearcycle \
4753
yearmonthaddition \
4854
yearmonthdifference \
4955
yearmonthmodify \
56+
yearmonthparsing \
5057
yearmonthroundtrip \
5158
zonedaddition \
5259
zoneddifference \
5360
zonedmodify \
61+
zonedparsing \
5462
zonedrounding \
5563
zonedroundtrip
5664
do
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {
2+
assertTemporalEqual,
3+
getProgressBar,
4+
parseableAnnotations,
5+
parseableDates,
6+
parseableNegativeOffsets,
7+
parseablePlus1Zones,
8+
parseablePositiveOffsets,
9+
parseableTimes,
10+
parseableZeroOffsets,
11+
temporalImpl as T,
12+
time
13+
} from './support.mjs';
14+
15+
const zones = [...parseablePlus1Zones, 'Custom/Vienna'];
16+
17+
const testCases = [];
18+
19+
for (const [dstr, [y, m, d]] of parseableDates) {
20+
const expected = new T.PlainDate(y, m, d);
21+
22+
for (const annotation of parseableAnnotations) {
23+
testCases.push([`${dstr}${annotation}`, expected]);
24+
25+
for (const [tstr] of parseableTimes) {
26+
for (const t of ['T', 't', ' ']) {
27+
for (const offset of ['', ...parseableZeroOffsets, ...parseableNegativeOffsets, ...parseablePositiveOffsets]) {
28+
testCases.push([`${dstr}${t}${tstr}${offset}${annotation}`, expected]);
29+
}
30+
31+
for (const offset of ['', ...parseablePositiveOffsets]) {
32+
for (const zone of zones) {
33+
testCases.push([`${dstr}${t}${tstr}${offset}[${zone}]${annotation}`, expected]);
34+
}
35+
}
36+
}
37+
}
38+
39+
for (const zone of zones) {
40+
testCases.push([`${dstr}[${zone}]${annotation}`, expected]);
41+
}
42+
}
43+
}
44+
45+
const total = testCases.length;
46+
47+
await time((start) => {
48+
const progress = getProgressBar(start, total);
49+
50+
for (const [isoString, expected] of testCases) {
51+
progress.tick(1, { test: isoString.slice(0, 40) });
52+
const actual = T.PlainDate.from(isoString);
53+
assertTemporalEqual(actual, expected, isoString);
54+
}
55+
56+
return total;
57+
});
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import {
2+
assertTemporalEqual,
3+
getProgressBar,
4+
parseableAnnotations,
5+
parseableDates,
6+
parseableNegativeOffsets,
7+
parseablePlus1Zones,
8+
parseablePositiveOffsets,
9+
parseableTimes,
10+
parseableZeroOffsets,
11+
temporalImpl as T,
12+
time
13+
} from './support.mjs';
14+
15+
const zones = [...parseablePlus1Zones, 'Custom/Vienna'];
16+
17+
const testCases = [];
18+
19+
for (const [dstr, [y, mon, d]] of parseableDates) {
20+
for (const [tstr, [h, min = 0, s = 0, ms = 0, µs = 0, ns = 0]] of parseableTimes) {
21+
const expected = new T.PlainDateTime(y, mon, d, h, min, s, ms, µs, ns);
22+
23+
for (const t of ['T', 't', ' ']) {
24+
for (const annotation of parseableAnnotations) {
25+
for (const offset of ['', ...parseableZeroOffsets, ...parseableNegativeOffsets, ...parseablePositiveOffsets]) {
26+
testCases.push([`${dstr}${t}${tstr}${offset}${annotation}`, expected]);
27+
}
28+
29+
for (const offset of ['', ...parseablePositiveOffsets]) {
30+
for (const zone of zones) {
31+
testCases.push([`${dstr}${t}${tstr}${offset}[${zone}]${annotation}`, expected]);
32+
}
33+
}
34+
}
35+
}
36+
}
37+
38+
const expected = new T.PlainDateTime(y, mon, d);
39+
for (const annotation of parseableAnnotations) {
40+
testCases.push([`${dstr}${annotation}`, expected]);
41+
42+
for (const zone of zones) {
43+
testCases.push([`${dstr}[${zone}]${annotation}`, expected]);
44+
}
45+
}
46+
}
47+
48+
const total = testCases.length;
49+
50+
await time((start) => {
51+
const progress = getProgressBar(start, total);
52+
53+
for (const [isoString, expected] of testCases) {
54+
progress.tick(1, { test: isoString.slice(0, 40) });
55+
const actual = T.PlainDateTime.from(isoString);
56+
assertTemporalEqual(actual, expected, isoString);
57+
}
58+
59+
return total;
60+
});
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import { assertDurationsEqual, getProgressBar, time, temporalImpl as T } from './support.mjs';
2+
3+
const day = [
4+
['', {}],
5+
['1Y', { y: 1 }],
6+
['2M', { mon: 2 }],
7+
['4W', { w: 4 }],
8+
['3D', { d: 3 }],
9+
['1Y2M', { y: 1, mon: 2 }],
10+
['1Y4W', { y: 1, w: 4 }],
11+
['1Y3D', { y: 1, d: 3 }],
12+
['2M4W', { mon: 2, w: 4 }],
13+
['2M3D', { mon: 2, d: 3 }],
14+
['4W3D', { w: 4, d: 3 }],
15+
['1Y2M4W', { y: 1, mon: 2, w: 4 }],
16+
['1Y2M3D', { y: 1, mon: 2, d: 3 }],
17+
['1Y4W3D', { y: 1, w: 4, d: 3 }],
18+
['2M4W3D', { mon: 2, w: 4, d: 3 }],
19+
['1Y2M4W3D', { y: 1, mon: 2, w: 4, d: 3 }]
20+
];
21+
const times = [
22+
['', {}],
23+
['4H', { h: 4 }],
24+
['5M', { min: 5 }],
25+
['4H5M', { h: 4, min: 5 }]
26+
];
27+
const sec = [
28+
['', {}],
29+
['6S', { s: 6 }],
30+
['7.1S', { s: 7, ms: 100 }],
31+
['7.12S', { s: 7, ms: 120 }],
32+
['7.123S', { s: 7, ms: 123 }],
33+
['8.1234S', { s: 8, ms: 123, µs: 400 }],
34+
['8.12345S', { s: 8, ms: 123, µs: 450 }],
35+
['8.123456S', { s: 8, ms: 123, µs: 456 }],
36+
['9.1234567S', { s: 9, ms: 123, µs: 456, ns: 700 }],
37+
['9.12345678S', { s: 9, ms: 123, µs: 456, ns: 780 }],
38+
['9.123456789S', { s: 9, ms: 123, µs: 456, ns: 789 }],
39+
['0.123S', { ms: 123 }],
40+
['0.000456S', { µs: 456 }],
41+
['0.000000789S', { ns: 789 }],
42+
['0.123456S', { ms: 123, µs: 456 }],
43+
['0.123000789S', { ms: 123, ns: 789 }],
44+
['0.000456789S', { µs: 456, ns: 789 }],
45+
['0.123456789S', { ms: 123, µs: 456, ns: 789 }]
46+
];
47+
for (const [str, expect] of sec) {
48+
if (str.includes('.')) sec.push([str.replace('.', ','), expect]);
49+
}
50+
51+
var tim = sec
52+
.reduce((arr, [s, add]) => arr.concat(times.map(([p, expect]) => [`${p}${s}`, { ...expect, ...add }])), [])
53+
.slice(1);
54+
55+
const testCases = [];
56+
57+
for (const [str, expectation] of day.slice(1)) {
58+
const { y = 0, mon = 0, w = 0, d = 0 } = expectation;
59+
const expected = new T.Duration(y, mon, w, d);
60+
61+
for (const s of [str, str.toLowerCase()]) {
62+
for (const p of ['P', 'p']) {
63+
testCases.push([`${p}${s}`, expected]);
64+
}
65+
}
66+
}
67+
for (const [str, expectation] of tim) {
68+
const { h = 0, min = 0, s = 0, ms = 0, µs = 0, ns = 0 } = expectation;
69+
const expected = new T.Duration(0, 0, 0, 0, h, min, s, ms, µs, ns);
70+
71+
for (const s of [str, str.toLowerCase()]) {
72+
for (const p of ['P', 'p']) {
73+
for (const t of ['T', 't']) {
74+
testCases.push([`${p}${t}${s}`, expected]);
75+
}
76+
}
77+
}
78+
}
79+
for (const [dstr, { y = 0, mon = 0, w = 0, d = 0 }] of day) {
80+
for (const [tstr, { h = 0, min = 0, s = 0, ms = 0, µs = 0, ns = 0 }] of tim) {
81+
const expected = new T.Duration(y, mon, w, d, h, min, s, ms, µs, ns);
82+
83+
for (const ds of [dstr, dstr.toLowerCase()]) {
84+
for (const ts of [tstr, tstr.toLowerCase()]) {
85+
for (const p of ['P', 'p']) {
86+
for (const t of ['T', 't']) {
87+
testCases.push([`${p}${ds}${t}${ts}`, expected]);
88+
}
89+
}
90+
}
91+
}
92+
}
93+
}
94+
95+
const total = testCases.length;
96+
97+
await time(async (start) => {
98+
const progress = getProgressBar(start, total);
99+
100+
for (const [isoString, expected] of testCases) {
101+
progress.tick(1, { test: isoString });
102+
const actual = T.Duration.from(isoString);
103+
assertDurationsEqual(actual, expected, isoString);
104+
}
105+
106+
return total;
107+
});
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import {
2+
assertTemporalEqual,
3+
getProgressBar,
4+
parseableAnnotations,
5+
parseableDates,
6+
parseableNegativeOffsets,
7+
parseablePlus1Zones,
8+
parseablePositiveOffsets,
9+
parseableTimes,
10+
parseableZeroOffsets,
11+
temporalImpl as T,
12+
time
13+
} from './support.mjs';
14+
15+
const testCases = [];
16+
17+
for (const [dstr, [y, mon, d]] of parseableDates) {
18+
for (const [tstr, [h, min = 0, s = 0, ms = 0, µs = 0, ns = 0]] of parseableTimes) {
19+
const expected = new T.PlainDateTime(y, mon, d, h, min, s, ms, µs, ns);
20+
const negOffsetExpected = new T.PlainDateTime(y, mon, d, h + 4, min, s, ms, µs, ns);
21+
const posOffsetExpected = new T.PlainDateTime(y, mon, d, h - 1, min, s, ms, µs, ns);
22+
23+
for (const t of ['T', 't', ' ']) {
24+
for (const annotation of parseableAnnotations) {
25+
for (const z of ['Z', 'z', ...parseableZeroOffsets]) {
26+
testCases.push([`${dstr}${t}${tstr}${z}${annotation}`, expected]);
27+
}
28+
29+
for (const offset of parseableNegativeOffsets) {
30+
testCases.push([`${dstr}${t}${tstr}${offset}${annotation}`, negOffsetExpected]);
31+
}
32+
33+
for (const offset of parseablePositiveOffsets) {
34+
for (const zone of parseablePlus1Zones) {
35+
testCases.push([`${dstr}${t}${tstr}${offset}[${zone}]${annotation}`, posOffsetExpected]);
36+
}
37+
}
38+
}
39+
}
40+
}
41+
}
42+
43+
const total = testCases.length;
44+
45+
await time((start) => {
46+
const progress = getProgressBar(start, total);
47+
48+
for (const [isoString, expected] of testCases) {
49+
progress.tick(1, { test: isoString.slice(0, 40) });
50+
const instant = T.Instant.from(isoString);
51+
const datetime = instant.toZonedDateTimeISO('UTC').toPlainDateTime();
52+
assertTemporalEqual(datetime, expected, isoString);
53+
}
54+
55+
return total;
56+
});
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import {
2+
assertTemporalEqual,
3+
getProgressBar,
4+
parseableAnnotations,
5+
parseableDates,
6+
parseableNegativeOffsets,
7+
parseablePlus1Zones,
8+
parseablePositiveOffsets,
9+
parseableTimes,
10+
parseableZeroOffsets,
11+
temporalImpl as T,
12+
time
13+
} from './support.mjs';
14+
15+
const zones = [...parseablePlus1Zones, 'Custom/Vienna'];
16+
17+
const testCases = [];
18+
19+
for (const annotation of parseableAnnotations) {
20+
for (const [dstr] of parseableDates) {
21+
testCases.push(`${dstr}${annotation}`);
22+
23+
for (const [tstr] of parseableTimes) {
24+
for (const t of ['T', 't', ' ']) {
25+
for (const offset of ['', ...parseableZeroOffsets, ...parseableNegativeOffsets, ...parseablePositiveOffsets]) {
26+
testCases.push(`${dstr}${t}${tstr}${offset}${annotation}`);
27+
}
28+
29+
for (const offset of ['', ...parseablePositiveOffsets]) {
30+
for (const zone of zones) {
31+
testCases.push(`${dstr}${t}${tstr}${offset}[${zone}]${annotation}`);
32+
}
33+
}
34+
}
35+
}
36+
37+
for (const zone of zones) {
38+
testCases.push(`${dstr}[${zone}]${annotation}`);
39+
}
40+
}
41+
42+
for (const mdstr of ['11-18', '1118', '--11-18', '--1118']) {
43+
for (const zone of zones) {
44+
testCases.push(`${mdstr}[${zone}]${annotation}`);
45+
}
46+
}
47+
}
48+
49+
const total = testCases.length;
50+
const expected = new T.PlainMonthDay(11, 18);
51+
52+
await time((start) => {
53+
const progress = getProgressBar(start, total);
54+
55+
for (const isoString of testCases) {
56+
progress.tick(1, { test: isoString.slice(0, 40) });
57+
const actual = T.PlainMonthDay.from(isoString);
58+
assertTemporalEqual(actual, expected, isoString);
59+
}
60+
61+
return total;
62+
});

0 commit comments

Comments
 (0)