From fa0a3081bd6a81433d7b49aca3e12a1bed2ef213 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Thu, 17 Apr 2025 17:22:42 -0700 Subject: [PATCH] Temporal: Increase coverage of dateStyle and timeStyle Add coverage in particular for dateStyle: undefined and timeStyle: undefined, and for dateStyle applying to PlainMonthDay/PlainYearMonth which were not tested. --- .../dateStyle-timeStyle-undefined.js | 18 ++++++++ .../toLocaleString/options-conflict.js | 4 ++ .../dateStyle-timeStyle-undefined.js | 18 ++++++++ .../toLocaleString/options-conflict.js | 8 ++++ .../dateStyle-timeStyle-undefined.js | 18 ++++++++ .../toLocaleString/options-conflict.js | 4 ++ .../dateStyle-timeStyle-undefined.js | 16 +++++++ .../prototype/toLocaleString/dateStyle.js | 6 +++ .../toLocaleString/options-conflict.js | 41 ++++++++++++++++++ .../toLocaleString/options-conflict.js | 8 ++++ .../toLocaleString/timeStyle-undefined.js | 15 +++++++ .../toLocaleString/dateStyle-undefined.js | 16 +++++++ .../prototype/toLocaleString/dateStyle.js | 6 +++ .../toLocaleString/options-conflict.js | 42 +++++++++++++++++++ .../dateStyle-timeStyle-undefined.js | 27 ++++++++++++ .../toLocaleString/options-conflict.js | 4 ++ 16 files changed, 251 insertions(+) create mode 100644 test/intl402/Temporal/Instant/prototype/toLocaleString/dateStyle-timeStyle-undefined.js create mode 100644 test/intl402/Temporal/PlainDate/prototype/toLocaleString/dateStyle-timeStyle-undefined.js create mode 100644 test/intl402/Temporal/PlainDateTime/prototype/toLocaleString/dateStyle-timeStyle-undefined.js create mode 100644 test/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/dateStyle-timeStyle-undefined.js create mode 100644 test/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/options-conflict.js create mode 100644 test/intl402/Temporal/PlainTime/prototype/toLocaleString/timeStyle-undefined.js create mode 100644 test/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/dateStyle-undefined.js create mode 100644 test/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/options-conflict.js create mode 100644 test/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/dateStyle-timeStyle-undefined.js diff --git a/test/intl402/Temporal/Instant/prototype/toLocaleString/dateStyle-timeStyle-undefined.js b/test/intl402/Temporal/Instant/prototype/toLocaleString/dateStyle-timeStyle-undefined.js new file mode 100644 index 0000000000..5b9a843eaf --- /dev/null +++ b/test/intl402/Temporal/Instant/prototype/toLocaleString/dateStyle-timeStyle-undefined.js @@ -0,0 +1,18 @@ +// Copyright (C) 2025 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tolocalestring +description: dateStyle or timeStyle present but undefined +features: [BigInt, Temporal] +---*/ + +const instant = new Temporal.Instant(957270896_987_650_000n); +const defaultFormatter = new Intl.DateTimeFormat("en"); +const expected = defaultFormatter.format(instant); + +const actualDate = instant.toLocaleString("en", { dateStyle: undefined }); +assert.sameValue(actualDate, expected, "dateStyle undefined is the same as being absent"); + +const actualTime = instant.toLocaleString("en", { timeStyle: undefined }); +assert.sameValue(actualTime, expected, "timeStyle undefined is the same as being absent"); diff --git a/test/intl402/Temporal/Instant/prototype/toLocaleString/options-conflict.js b/test/intl402/Temporal/Instant/prototype/toLocaleString/options-conflict.js index 490d6c27df..9f9329b706 100644 --- a/test/intl402/Temporal/Instant/prototype/toLocaleString/options-conflict.js +++ b/test/intl402/Temporal/Instant/prototype/toLocaleString/options-conflict.js @@ -44,4 +44,8 @@ for (const [ option, value ] of conflictingOptions) { assert.throws(TypeError, function() { instant.toLocaleString("en", { [option]: value, timeStyle: "short" }); }, `instant.toLocaleString("en", { ${option}: "${value}", timeStyle: "short" }) throws TypeError`); + + // dateStyle or timeStyle present but undefined does not conflict + instant.toLocaleString("en", { [option]: value, dateStyle: undefined }); + instant.toLocaleString("en", { [option]: value, timeStyle: undefined }); } diff --git a/test/intl402/Temporal/PlainDate/prototype/toLocaleString/dateStyle-timeStyle-undefined.js b/test/intl402/Temporal/PlainDate/prototype/toLocaleString/dateStyle-timeStyle-undefined.js new file mode 100644 index 0000000000..7fed592273 --- /dev/null +++ b/test/intl402/Temporal/PlainDate/prototype/toLocaleString/dateStyle-timeStyle-undefined.js @@ -0,0 +1,18 @@ +// Copyright (C) 2025 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tolocalestring +description: dateStyle or timeStyle present but undefined +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); +const defaultFormatter = new Intl.DateTimeFormat("en"); +const expected = defaultFormatter.format(date); + +const actualDate = date.toLocaleString("en", { dateStyle: undefined }); +assert.sameValue(actualDate, expected, "dateStyle undefined is the same as being absent"); + +const actualTime = date.toLocaleString("en", { timeStyle: undefined }); +assert.sameValue(actualTime, expected, "timeStyle undefined is the same as being absent"); diff --git a/test/intl402/Temporal/PlainDate/prototype/toLocaleString/options-conflict.js b/test/intl402/Temporal/PlainDate/prototype/toLocaleString/options-conflict.js index 3deb4c2b24..ed0eec887f 100644 --- a/test/intl402/Temporal/PlainDate/prototype/toLocaleString/options-conflict.js +++ b/test/intl402/Temporal/PlainDate/prototype/toLocaleString/options-conflict.js @@ -30,8 +30,16 @@ const date = new Temporal.PlainDate(2000, 5, 2); assert.sameValue(typeof date.toLocaleString("en", { dateStyle: "short" }), "string"); +assert.throws(TypeError, function () { + date.toLocaleString("en", { timeStyle: "short" }); +}, "timeStyle conflicts with PlainDate"); + for (const [ option, value ] of conflictingOptions) { assert.throws(TypeError, function() { date.toLocaleString("en", { [option]: value, dateStyle: "short" }); }, `date.toLocaleString("en", { ${option}: "${value}", dateStyle: "short" }) throws TypeError`); + + // dateStyle or timeStyle present but undefined does not conflict + date.toLocaleString("en", { [option]: value, dateStyle: undefined }); + date.toLocaleString("en", { [option]: value, timeStyle: undefined }); } diff --git a/test/intl402/Temporal/PlainDateTime/prototype/toLocaleString/dateStyle-timeStyle-undefined.js b/test/intl402/Temporal/PlainDateTime/prototype/toLocaleString/dateStyle-timeStyle-undefined.js new file mode 100644 index 0000000000..2dec04fb15 --- /dev/null +++ b/test/intl402/Temporal/PlainDateTime/prototype/toLocaleString/dateStyle-timeStyle-undefined.js @@ -0,0 +1,18 @@ +// Copyright (C) 2025 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tolocalestring +description: dateStyle or timeStyle present but undefined +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const defaultFormatter = new Intl.DateTimeFormat("en"); +const expected = defaultFormatter.format(datetime); + +const actualDate = datetime.toLocaleString("en", { dateStyle: undefined }); +assert.sameValue(actualDate, expected, "dateStyle undefined is the same as being absent"); + +const actualTime = datetime.toLocaleString("en", { timeStyle: undefined }); +assert.sameValue(actualTime, expected, "timeStyle undefined is the same as being absent"); diff --git a/test/intl402/Temporal/PlainDateTime/prototype/toLocaleString/options-conflict.js b/test/intl402/Temporal/PlainDateTime/prototype/toLocaleString/options-conflict.js index 13fefadde6..c7b416ffdf 100644 --- a/test/intl402/Temporal/PlainDateTime/prototype/toLocaleString/options-conflict.js +++ b/test/intl402/Temporal/PlainDateTime/prototype/toLocaleString/options-conflict.js @@ -44,4 +44,8 @@ for (const [ option, value ] of conflictingOptions) { assert.throws(TypeError, function() { datetime.toLocaleString("en", { [option]: value, timeStyle: "short" }); }, `datetime.toLocaleString("en", { ${option}: "${value}", timeStyle: "short" }) throws TypeError`); + + // dateStyle or timeStyle present but undefined does not conflict + datetime.toLocaleString("en", { [option]: value, dateStyle: undefined }); + datetime.toLocaleString("en", { [option]: value, timeStyle: undefined }); } diff --git a/test/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/dateStyle-timeStyle-undefined.js b/test/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/dateStyle-timeStyle-undefined.js new file mode 100644 index 0000000000..565d83cb35 --- /dev/null +++ b/test/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/dateStyle-timeStyle-undefined.js @@ -0,0 +1,16 @@ +// Copyright (C) 2025 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tolocalestring +description: dateStyle present but undefined +features: [Temporal] +---*/ + +const defaultFormatter = new Intl.DateTimeFormat("en"); +const { calendar } = defaultFormatter.resolvedOptions(); +const monthday = new Temporal.PlainMonthDay(5, 2, calendar); +const expected = defaultFormatter.format(monthday); + +const actual = monthday.toLocaleString("en", { dateStyle: undefined }); +assert.sameValue(actual, expected, "dateStyle undefined is the same as being absent"); diff --git a/test/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/dateStyle.js b/test/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/dateStyle.js index 485fa0cf84..5c64a4eaa0 100644 --- a/test/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/dateStyle.js +++ b/test/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/dateStyle.js @@ -29,3 +29,9 @@ assert( !dateIslamic.toLocaleString("en-u-ca-islamic-tbla", { dateStyle: "short" }).includes("Ramadan"), "dateStyle: short does not write month of Ramadan out in full" ); + +const dateWithReferenceYear = new Temporal.PlainMonthDay(5, 31, "gregory", 2222); +assert( + !dateWithReferenceYear.toLocaleString("en", { dateStyle: "full" }).includes("2222"), + "dateStyle: full should not format reference year at all" +); diff --git a/test/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/options-conflict.js b/test/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/options-conflict.js new file mode 100644 index 0000000000..82e8784d69 --- /dev/null +++ b/test/intl402/Temporal/PlainMonthDay/prototype/toLocaleString/options-conflict.js @@ -0,0 +1,41 @@ +// Copyright (C) 2025 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sup-temporal.plainmonthday.prototype.tolocalestring +description: > + Conflicting properties of dateStyle must be rejected with a TypeError for the options argument +info: | + CreateDateTimeFormat: + + 45. If _dateStyle_ is not *undefined* or _timeStyle_ is not *undefined*, then + a. If _hasExplicitFormatComponents_ is *true*, then + i. Throw a *TypeError* exception. + b. If _required_ is ~date~ and _timeStyle_ is not *undefined*, then + i. Throw a *TypeError* exception. +features: [Temporal] +---*/ + +const conflictingOptions = [ + "month", + "day", +]; +const calendar = new Intl.DateTimeFormat("en").resolvedOptions().calendar; +const md = new Temporal.PlainMonthDay(4, 17, calendar); + +// dateStyle does not conflict with PlainMonthDay +md.toLocaleString("en", { dateStyle: "short" }); + +assert.throws(TypeError, function () { + md.toLocaleString("en", { timeStyle: "short" }); +}, "timeStyle conflicts with PlainMonthDay"); + +for (const option of conflictingOptions) { + assert.throws(TypeError, function() { + md.toLocaleString("en", { [option]: "numeric", dateStyle: "short" }); + }, `${option} conflicts with dateStyle`); + + // dateStyle or timeStyle present but undefined does not conflict + md.toLocaleString("en", { [option]: "numeric", dateStyle: undefined }); + md.toLocaleString("en", { [option]: "numeric", timeStyle: undefined }); +} diff --git a/test/intl402/Temporal/PlainTime/prototype/toLocaleString/options-conflict.js b/test/intl402/Temporal/PlainTime/prototype/toLocaleString/options-conflict.js index 3bc613c8f6..32a7a63a70 100644 --- a/test/intl402/Temporal/PlainTime/prototype/toLocaleString/options-conflict.js +++ b/test/intl402/Temporal/PlainTime/prototype/toLocaleString/options-conflict.js @@ -30,8 +30,16 @@ const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); assert.sameValue(typeof time.toLocaleString("en", { timeStyle: "short" }), "string"); +assert.throws(TypeError, function () { + time.toLocaleString("en", { dateStyle: "short" }); +}, "dateStyle conflicts with PlainTime"); + for (const [ option, value ] of conflictingOptions) { assert.throws(TypeError, function() { time.toLocaleString("en", { [option]: value, timeStyle: "short" }); }, `time.toLocaleString("en", { ${option}: "${value}", timeStyle: "short" }) throws TypeError`); + + // dateStyle or timeStyle present but undefined does not conflict + time.toLocaleString("en", { [option]: value, dateStyle: undefined }); + time.toLocaleString("en", { [option]: value, timeStyle: undefined }); } diff --git a/test/intl402/Temporal/PlainTime/prototype/toLocaleString/timeStyle-undefined.js b/test/intl402/Temporal/PlainTime/prototype/toLocaleString/timeStyle-undefined.js new file mode 100644 index 0000000000..bcd22b6e34 --- /dev/null +++ b/test/intl402/Temporal/PlainTime/prototype/toLocaleString/timeStyle-undefined.js @@ -0,0 +1,15 @@ +// Copyright (C) 2025 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: timeStyle present but undefined +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const defaultFormatter = new Intl.DateTimeFormat("en"); +const expected = defaultFormatter.format(time); + +const actual = time.toLocaleString("en", { timeStyle: undefined }); +assert.sameValue(actual, expected, "timeStyle undefined is the same as being absent"); diff --git a/test/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/dateStyle-undefined.js b/test/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/dateStyle-undefined.js new file mode 100644 index 0000000000..5ac3971bf6 --- /dev/null +++ b/test/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/dateStyle-undefined.js @@ -0,0 +1,16 @@ +// Copyright (C) 2025 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.tolocalestring +description: dateStyle present but undefined +features: [Temporal] +---*/ + +const defaultFormatter = new Intl.DateTimeFormat("en"); +const { calendar } = defaultFormatter.resolvedOptions(); +const yearmonth = new Temporal.PlainYearMonth(2000, 5, calendar); +const expected = defaultFormatter.format(yearmonth); + +const actual = yearmonth.toLocaleString("en", { dateStyle: undefined }); +assert.sameValue(actual, expected, "dateStyle undefined is the same as being absent"); diff --git a/test/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/dateStyle.js b/test/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/dateStyle.js index dd6a1ec5c7..d4f70bbbd6 100644 --- a/test/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/dateStyle.js +++ b/test/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/dateStyle.js @@ -29,3 +29,9 @@ assert( !dateIslamic.toLocaleString("en-u-ca-islamic-tbla", { dateStyle: "short" }).includes("Ramadan"), "dateStyle: short does not write month of Ramadan out in full" ); + +const dateWithReferenceDay = new Temporal.PlainYearMonth(2024, 5, "gregory", 31); +assert( + !dateWithReferenceDay.toLocaleString("en", { dateStyle: "full" }).includes("31"), + "dateStyle: full should not format reference day at all" +); diff --git a/test/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/options-conflict.js b/test/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/options-conflict.js new file mode 100644 index 0000000000..6bdf6c5c71 --- /dev/null +++ b/test/intl402/Temporal/PlainYearMonth/prototype/toLocaleString/options-conflict.js @@ -0,0 +1,42 @@ +// Copyright (C) 2025 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sup-temporal.plainyearmonth.prototype.tolocalestring +description: > + Conflicting properties of dateStyle must be rejected with a TypeError for the options argument +info: | + CreateDateTimeFormat: + + 45. If _dateStyle_ is not *undefined* or _timeStyle_ is not *undefined*, then + a. If _hasExplicitFormatComponents_ is *true*, then + i. Throw a *TypeError* exception. + b. If _required_ is ~date~ and _timeStyle_ is not *undefined*, then + i. Throw a *TypeError* exception. +features: [Temporal] +---*/ + +const conflictingOptions = [ + ["era", "short"], + ["year", "numeric"], + ["month", "numeric"], +]; +const calendar = new Intl.DateTimeFormat("en").resolvedOptions().calendar; +const ym = new Temporal.PlainYearMonth(2024, 4, calendar); + +// dateStyle does not conflict with PlainYearMonth +ym.toLocaleString("en", { dateStyle: "short" }); + +assert.throws(TypeError, function () { + ym.toLocaleString("en", { timeStyle: "short" }); +}, "timeStyle conflicts with PlainYearMonth"); + +for (const [option, value] of conflictingOptions) { + assert.throws(TypeError, function() { + ym.toLocaleString("en", { [option]: value, dateStyle: "short" }); + }, `${option} conflicts with dateStyle`); + + // dateStyle or timeStyle present but undefined does not conflict + ym.toLocaleString("en", { [option]: value, dateStyle: undefined }); + ym.toLocaleString("en", { [option]: value, timeStyle: undefined }); +} diff --git a/test/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/dateStyle-timeStyle-undefined.js b/test/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/dateStyle-timeStyle-undefined.js new file mode 100644 index 0000000000..8c663fcb50 --- /dev/null +++ b/test/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/dateStyle-timeStyle-undefined.js @@ -0,0 +1,27 @@ +// Copyright (C) 2025 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tolocalestring +description: dateStyle or timeStyle present but undefined +features: [BigInt, Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(957270896_987_650_000n, "UTC"); +const defaultFormatter = new Intl.DateTimeFormat("en", { + year: "numeric", + month: "numeric", + day: "numeric", + hour: "numeric", + minute: "numeric", + second: "numeric", + timeZoneName: "short", + timeZone: "UTC", +}); +const expected = defaultFormatter.format(datetime.toInstant()); + +const actualDate = datetime.toLocaleString("en", { dateStyle: undefined }); +assert.sameValue(actualDate, expected, "dateStyle undefined is the same as being absent"); + +const actualTime = datetime.toLocaleString("en", { timeStyle: undefined }); +assert.sameValue(actualTime, expected, "timeStyle undefined is the same as being absent"); diff --git a/test/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/options-conflict.js b/test/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/options-conflict.js index 5cc1162dc4..49313e2f25 100644 --- a/test/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/options-conflict.js +++ b/test/intl402/Temporal/ZonedDateTime/prototype/toLocaleString/options-conflict.js @@ -45,4 +45,8 @@ for (const [ option, value ] of conflictingOptions) { assert.throws(TypeError, function() { datetime.toLocaleString("en", { [option]: value, timeStyle: "short" }); }, `datetime.toLocaleString("en", { ${option}: "${value}", timeStyle: "short" }) throws TypeError`); + + // dateStyle or timeStyle present but undefined does not conflict + datetime.toLocaleString("en", { [option]: value, dateStyle: undefined }); + datetime.toLocaleString("en", { [option]: value, timeStyle: undefined }); }