Updated tests to reflect that daysInMonth are the count of days in a month

See https://github.com/tc39/proposal-temporal/issues/1315
This commit is contained in:
Guillaume Emont 2023-04-25 16:23:19 +02:00 committed by Philip Chimento
parent 1a352aac50
commit d7fa398364
11 changed files with 54 additions and 113 deletions

View File

@ -77,8 +77,13 @@ class CustomCalendar extends Temporal.Calendar {
return new Temporal.PlainMonthDay(isoMonth, isoDay, this, isoYear);
}
dateAdd(date, duration, options) {
if (duration.months) throw new Error("adding months not implemented in this test");
return super.dateAdd(date, duration, options).withCalendar(this);
const {isoYear, isoMonth, isoDay} = date.getISOFields();
let {years, months, weeks, days} = duration;
let iter = new Temporal.PlainDate(isoYear + years, isoMonth, isoDay, "iso8601");
const monthsDays = months * 36;
if (iter.dayOfYear + monthsDays > iter.daysInYear || iter.dayOfYear + monthsDays < 1)
throw new Error("complicated addition not implemented in this test");
return iter.add({ weeks, days: monthsDays + days }).withCalendar(this);
}
toString() {
return "thirty-six";
@ -132,9 +137,9 @@ TemporalHelpers.assertPlainYearMonth(
"adding negative less than one month's worth of days yields the same month",
/* era = */ undefined, /* eraYear = */ undefined, /* referenceISODay = */ 6
);
assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called");
assert.sameValue(calendar.dateFromFieldsCalls.length, 2, "dateFromFields was called twice");
assert.deepEqual(
calendar.dateFromFieldsCalls[0][0],
calendar.dateFromFieldsCalls[1][0],
{ year: 2022, monthCode: "M02", day: 36 },
"last day of month 2 passed to dateFromFields when adding negative duration"
);
@ -147,9 +152,9 @@ TemporalHelpers.assertPlainYearMonth(
"adding negative one month's worth of days yields the previous month",
/* era = */ undefined, /* eraYear = */ undefined, /* referenceISODay = */ 1
);
assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called");
assert.sameValue(calendar.dateFromFieldsCalls.length, 2, "dateFromFields was called twice");
assert.deepEqual(
calendar.dateFromFieldsCalls[0][0],
calendar.dateFromFieldsCalls[1][0],
{ year: 2022, monthCode: "M02", day: 36 },
"last day of month 2 passed to dateFromFields when adding negative duration"
);

View File

@ -1,42 +0,0 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plainyearmonth.prototype.add
description: >
The appropriate error is thrown if the calendar's daysInMonth method returns a
value that cannot be converted to a positive integer
includes: [compareArray.js]
features: [BigInt, Symbol, Temporal]
---*/
const actual = [];
class CalendarDaysInMonthWrongValue extends Temporal.Calendar {
constructor(badValue) {
super("iso8601");
this._badValue = badValue;
}
dateFromFields(fields, options) {
actual.push("call dateFromFields");
return super.dateFromFields(fields, options);
}
daysInMonth() {
return this._badValue;
}
}
// daysInMonth is only called if we are adding a negative duration
const duration = new Temporal.Duration(-1, -1);
[Infinity, -Infinity, -42].forEach((badValue) => {
const calendar = new CalendarDaysInMonthWrongValue(badValue);
const yearMonth = new Temporal.PlainYearMonth(2000, 5, calendar);
assert.throws(RangeError, () => yearMonth.add(duration), `daysInMonth ${badValue}`);
assert.compareArray(actual, [], "dateFromFields not called");
});
[Symbol('foo'), 31n].forEach((badValue) => {
const calendar = new CalendarDaysInMonthWrongValue(badValue);
const yearMonth = new Temporal.PlainYearMonth(2000, 5, calendar);
assert.throws(TypeError, () => yearMonth.add(duration), `daysInMonth ${typeof badValue}`);
assert.compareArray(actual, [], "dateFromFields not called");
});

View File

@ -51,12 +51,12 @@ const expected = [
// CalendarDateFromFields
"get this.calendar.dateFromFields",
"call this.calendar.dateFromFields",
"get this.calendar.dateAdd",
// CopyDataProperties
"ownKeys options",
"getOwnPropertyDescriptor options.overflow",
"get options.overflow",
// CalendarDateAdd
"get this.calendar.dateAdd",
"call this.calendar.dateAdd",
// inside Calendar.p.dateAdd
"get options.overflow",

View File

@ -25,13 +25,16 @@ const expected = [
];
const options = TemporalHelpers.propertyBagObserver(actual, { extra: 5 }, "options");
let dateAddCalls = 0;
class CustomCalendar extends Temporal.Calendar {
constructor() {
super("iso8601");
}
dateAdd(date, duration, options) {
const result = super.dateAdd(date, duration, options);
options.overflow = 'meatloaf';
dateAddCalls++;
if (dateAddCalls == 3)
options.overflow = 'meatloaf';
return result;
}
yearMonthFromFields(...args) {

View File

@ -30,13 +30,16 @@ const expected = [
];
const options = TemporalHelpers.propertyBagObserver(actual, { overflow: "constrain" }, "options");
let dateAddCalls = 0;
class CustomCalendar extends Temporal.Calendar {
constructor() {
super("iso8601");
}
dateAdd(date, duration, options) {
const result = super.dateAdd(date, duration, options);
options.overflow = 'meatloaf';
dateAddCalls++;
if (dateAddCalls == 3)
options.overflow = 'meatloaf';
return result;
}
yearMonthFromFields(...args) {

View File

@ -15,10 +15,12 @@ class CustomCalendar extends Temporal.Calendar {
}
dateAdd(plainDate, duration, options) {
++calls;
TemporalHelpers.assertPlainDate(plainDate, 2000, 3, "M03", 31, "plainDate argument");
TemporalHelpers.assertDuration(duration, 0, -10, 0, 0, 0, 0, 0, 0, 0, 0, "duration argument");
assert.sameValue(typeof options, "object", "options argument: type");
assert.sameValue(Object.getPrototypeOf(options), null, "options argument: prototype");
if (calls == 3) {
TemporalHelpers.assertPlainDate(plainDate, 2000, 3, "M03", 31, "plainDate argument");
TemporalHelpers.assertDuration(duration, 0, -10, 0, 0, 0, 0, 0, 0, 0, 0, "duration argument");
assert.sameValue(typeof options, "object", "options argument: type");
assert.sameValue(Object.getPrototypeOf(options), null, "options argument: prototype");
}
return super.dateAdd(plainDate, duration, options);
}
}
@ -26,4 +28,4 @@ class CustomCalendar extends Temporal.Calendar {
const plainYearMonth = new Temporal.PlainYearMonth(2000, 3, new CustomCalendar());
const result = plainYearMonth.subtract({ months: 10 });
TemporalHelpers.assertPlainYearMonth(result, 1999, 5, "M05");
assert.sameValue(calls, 1, "should have called dateAdd");
assert.sameValue(calls, 3, "should have called dateAdd 3 times");

View File

@ -77,8 +77,13 @@ class CustomCalendar extends Temporal.Calendar {
return new Temporal.PlainMonthDay(isoMonth, isoDay, this, isoYear);
}
dateAdd(date, duration, options) {
if (duration.months) throw new Error("adding months not implemented in this test");
return super.dateAdd(date, duration, options).withCalendar(this);
const {isoYear, isoMonth, isoDay} = date.getISOFields();
let {years, months, weeks, days} = duration;
let iter = new Temporal.PlainDate(isoYear + years, isoMonth, isoDay, "iso8601");
const monthsDays = months * 36;
if (iter.dayOfYear + monthsDays > iter.daysInYear || iter.dayOfYear + monthsDays < 1)
throw new Error("complicated addition not implemented in this test");
return iter.add({ weeks, days: monthsDays + days }).withCalendar(this);
}
toString() {
return "thirty-six";
@ -102,9 +107,9 @@ TemporalHelpers.assertPlainYearMonth(
"subtracting positive less than one month's worth of days yields the same month",
/* era = */ undefined, /* eraYear = */ undefined, /* referenceISODay = */ 6
);
assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called");
assert.sameValue(calendar.dateFromFieldsCalls.length, 2, "dateFromFields was called twice");
assert.deepEqual(
calendar.dateFromFieldsCalls[0][0],
calendar.dateFromFieldsCalls[1][0],
{ year: 2022, monthCode: "M02", day: 36 },
"last day of month 2 passed to dateFromFields when subtracting positive duration"
);
@ -117,9 +122,9 @@ TemporalHelpers.assertPlainYearMonth(
"subtracting positive one month's worth of days yields the previous month",
/* era = */ undefined, /* eraYear = */ undefined, /* referenceISODay = */ 1
);
assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called");
assert.sameValue(calendar.dateFromFieldsCalls.length, 2, "dateFromFields was called twice");
assert.deepEqual(
calendar.dateFromFieldsCalls[0][0],
calendar.dateFromFieldsCalls[1][0],
{ year: 2022, monthCode: "M02", day: 36 },
"last day of month 2 passed to dateFromFields when subtracting positive duration"
);

View File

@ -1,42 +0,0 @@
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plainyearmonth.prototype.subtract
description: >
The appropriate error is thrown if the calendar's daysInMonth method returns a
value that cannot be converted to a positive integer
includes: [compareArray.js]
features: [BigInt, Symbol, Temporal]
---*/
const actual = [];
class CalendarDaysInMonthWrongValue extends Temporal.Calendar {
constructor(badValue) {
super("iso8601");
this._badValue = badValue;
}
dateFromFields(fields, options) {
actual.push("call dateFromFields");
return super.dateFromFields(fields, options);
}
daysInMonth() {
return this._badValue;
}
}
// daysInMonth is only called if we are subtracting a positive duration
const duration = new Temporal.Duration(1, 1);
[Infinity, -Infinity, -42].forEach((badValue) => {
const calendar = new CalendarDaysInMonthWrongValue(badValue);
const yearMonth = new Temporal.PlainYearMonth(2000, 5, calendar);
assert.throws(RangeError, () => yearMonth.subtract(duration), `daysInMonth ${badValue}`);
assert.compareArray(actual, [], "dateFromFields not called");
});
[Symbol('foo'), 31n].forEach((badValue) => {
const calendar = new CalendarDaysInMonthWrongValue(badValue);
const yearMonth = new Temporal.PlainYearMonth(2000, 5, calendar);
assert.throws(TypeError, () => yearMonth.subtract(duration), `daysInMonth ${typeof badValue}`);
assert.compareArray(actual, [], "dateFromFields not called");
});

View File

@ -12,5 +12,5 @@ features: [Temporal]
const calendar = TemporalHelpers.calendarCheckFieldsPrototypePollution();
const instance = new Temporal.PlainYearMonth(2000, 5, calendar);
instance.subtract(new Temporal.Duration(1));
assert.sameValue(calendar.dateFromFieldsCallCount, 1, "dateFromFields should have been called on the calendar");
assert.sameValue(calendar.dateFromFieldsCallCount, 2, "dateFromFields should have been called twice on the calendar");
assert.sameValue(calendar.yearMonthFromFieldsCallCount, 1, "yearMonthFromFields should have been called on the calendar");

View File

@ -12,10 +12,12 @@ features: [Temporal]
class CheckedAdd extends Temporal.Calendar {
constructor() {
super("iso8601");
this.called = 0;
}
dateAdd(date, duration, options, constructor) {
this.called = true;
assert.notSameValue(options, undefined, "options not undefined");
this.called += 1;
if (this.called == 3)
assert.notSameValue(options, undefined, "options not undefined");
return super.dateAdd(date, duration, options, constructor);
}
}
@ -25,6 +27,8 @@ const yearmonth = new Temporal.PlainYearMonth(2000, 3, calendar);
const duration = { months: 1 };
yearmonth.subtract(duration, undefined);
yearmonth.subtract(duration);
assert(calendar.called == 3);
assert(calendar.called);
calendar.called = 0;
yearmonth.subtract(duration);
assert(calendar.called == 3);

View File

@ -49,9 +49,13 @@ const expected = [
"get this.calendar.year",
"call this.calendar.year",
// CalendarDaysInMonth
"get this.calendar.daysInMonth",
"call this.calendar.daysInMonth",
// CalendarDateFromFields
"get this.calendar.dateFromFields",
"call this.calendar.dateFromFields",
"get this.calendar.dateAdd",
"call this.calendar.dateAdd",
"call this.calendar.dateAdd",
"get this.calendar.day",
"call this.calendar.day",
"get this.calendar.dateFromFields",
"call this.calendar.dateFromFields",
// CopyDataProperties
@ -59,7 +63,6 @@ const expected = [
"getOwnPropertyDescriptor options.overflow",
"get options.overflow",
// CalendarDateAdd
"get this.calendar.dateAdd",
"call this.calendar.dateAdd",
// inside Calendar.p.dateAdd
"get options.overflow",