From 7b78d4be74e2f1c90549b4dce7ac2986ba3e954a Mon Sep 17 00:00:00 2001
From: Jesse Alama <jessealama@users.noreply.github.com>
Date: Mon, 21 Mar 2022 20:16:18 +0100
Subject: [PATCH] Port some basic Temporal.PlainDateTime tests from Demitasse
 to test262 (#3430)

* Create a Temporal.PlainDateTime with all arguments supplied.

Migrates some tests that currently exist in the
proposal-temporal repo.

* Check all data in Temporal.PlainDateTimes, variously constructed

Enrich existing tests to check all basic data in the
instance of `Temporal.PlainDateTime`, not just a single
field.

These additional checks were motivated by the migration of
existing Demitasse tests in the proposal-temporal repo to
test262. The Demitasse tests check more than a single
field.
---
 .../argument-object-insufficient-data.js      | 23 ++++++
 .../Temporal/PlainDateTime/compare/basic.js   | 29 +++++++
 .../Temporal/PlainDateTime/compare/cast.js    | 35 +++++++++
 .../PlainDateTime/constructor-full.js         | 23 ++++++
 .../Temporal/PlainDateTime/datetime-math.js   | 47 +++++++++++
 .../Temporal/PlainDateTime/hour-undefined.js  | 15 +++-
 .../PlainDateTime/microsecond-undefined.js    | 16 +++-
 .../PlainDateTime/millisecond-undefined.js    | 15 +++-
 .../PlainDateTime/minute-undefined.js         | 15 +++-
 .../PlainDateTime/nanosecond-undefined.js     | 15 +++-
 .../prototype/add/ambiguous-date.js           | 29 +++++++
 .../prototype/add/argument-duration.js        | 17 ++++
 .../add/argument-object-insufficient-data.js  | 35 +++++++++
 .../add/argument-plain-object-mixed-signs.js  | 18 +++++
 .../prototype/add/hour-overflow.js            | 25 ++++++
 .../prototype/add/negative-duration.js        | 23 ++++++
 .../prototype/add/options-empty.js            | 23 ++++++
 .../prototype/add/options-invalid.js          | 20 +++++
 .../prototype/add/overflow-invalid-string.js  | 10 ++-
 .../prototype/dayOfWeek/basic.js              | 12 +++
 .../prototype/dayOfYear/basic.js              | 12 +++
 .../prototype/daysInMonth/basic.js            | 12 +++
 .../prototype/daysInWeek/basic.js             | 12 +++
 .../prototype/daysInYear/basic.js             | 12 +++
 .../argument-object-insufficient-data.js      | 16 ++++
 .../PlainDateTime/prototype/equals/basic.js   | 14 ++++
 .../PlainDateTime/prototype/equals/cast.js    | 46 +++++++++++
 .../prototype/monthsInYear/basic.js           | 12 +++
 .../prototype/subtract/ambiguous-date.js      | 29 +++++++
 .../prototype/subtract/argument-duration.js   | 18 +++++
 .../argument-object-insufficient-data.js      | 35 +++++++++
 .../argument-plain-object-mixed-signs.js      | 18 +++++
 .../prototype/subtract/hour-overflow.js       | 30 ++++++++
 .../prototype/subtract/negative-duration.js   | 23 ++++++
 .../prototype/subtract/options-empty.js       | 23 ++++++
 .../prototype/subtract/options-invalid.js     | 20 +++++
 .../PlainDateTime/prototype/toString/basic.js | 13 ++++
 .../prototype/until/casts-argument.js         | 23 ++++++
 .../until/different-calendars-throws.js       | 22 ++++++
 .../PlainDateTime/prototype/until/inverse.js  | 14 ++++
 .../prototype/until/no-unnecessary-units.js   | 24 ++++++
 .../prototype/until/returns-days.js           | 38 +++++++++
 .../prototype/until/subseconds.js             | 36 +++++++++
 .../prototype/until/units-changed.js          | 66 ++++++++++++++++
 .../until/weeks-months-mutually-exclusive.js  | 24 ++++++
 .../PlainDateTime/prototype/valueOf/basic.js  | 23 ++++++
 .../prototype/weekOfYear/basic.js             | 12 +++
 .../with/argument-object-insufficient-data.js | 42 ++++++++++
 .../PlainDateTime/prototype/with/basic.js     | 77 +++++++++++++++++++
 .../prototype/with/calendar-throws.js         | 16 ++++
 .../with/month-and-monthcode-must-agree.js    | 16 ++++
 ...ultiple-unrecognized-properties-ignored.js | 23 ++++++
 .../prototype/with/options-empty.js           | 23 ++++++
 .../prototype/with/options-invalid.js         | 20 +++++
 .../prototype/with/overflow-invalid-string.js |  8 +-
 .../prototype/with/string-throws.js           | 20 +++++
 .../prototype/with/timezone-throws.js         | 16 ++++
 .../argument-object-insuffcient-data.js       | 35 +++++++++
 .../withPlainDate/argument-object.js          | 17 ++++
 .../withPlainDate/argument-plaindate.js       | 18 +++++
 .../argument-string-iso-calendar.js           | 36 +++++++++
 .../withPlainDate/argument-string.js          | 17 ++++
 .../non-compatible-calendars-throw.js         | 28 +++++++
 .../argument-object-insufficient-data.js      | 35 +++++++++
 ...argument-string-without-time-designator.js | 17 ++++
 .../prototype/withPlainTime/argument-time.js  | 29 +++++++
 .../no-argument-default-to-midnight.js        | 17 ++++
 .../PlainDateTime/second-undefined.js         | 15 +++-
 68 files changed, 1571 insertions(+), 26 deletions(-)
 create mode 100644 test/built-ins/Temporal/PlainDateTime/compare/argument-object-insufficient-data.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/compare/basic.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/compare/cast.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/constructor-full.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/datetime-math.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/add/ambiguous-date.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/add/argument-duration.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/add/argument-object-insufficient-data.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/add/argument-plain-object-mixed-signs.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/add/hour-overflow.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/add/negative-duration.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/add/options-empty.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/add/options-invalid.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/basic.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/basic.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/basic.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/basic.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/daysInYear/basic.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/equals/argument-object-insufficient-data.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/equals/cast.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/basic.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/subtract/ambiguous-date.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-duration.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-object-insufficient-data.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-plain-object-mixed-signs.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/subtract/hour-overflow.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-duration.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-empty.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-invalid.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toString/basic.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/until/casts-argument.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/until/different-calendars-throws.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/until/inverse.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/until/returns-days.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/until/subseconds.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/until/weeks-months-mutually-exclusive.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/valueOf/basic.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/basic.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/with/argument-object-insufficient-data.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/with/basic.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-throws.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/with/month-and-monthcode-must-agree.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/with/multiple-unrecognized-properties-ignored.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/with/options-empty.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/with/options-invalid.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/with/string-throws.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/with/timezone-throws.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insuffcient-data.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/non-compatible-calendars-throw.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-object-insufficient-data.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-without-time-designator.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-time.js
 create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/no-argument-default-to-midnight.js

diff --git a/test/built-ins/Temporal/PlainDateTime/compare/argument-object-insufficient-data.js b/test/built-ins/Temporal/PlainDateTime/compare/argument-object-insufficient-data.js
new file mode 100644
index 0000000000..5ef97473d6
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/compare/argument-object-insufficient-data.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.compare
+description: Plain object arguments may throw if they do not contain sufficient information
+features: [Temporal]
+---*/
+
+const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102);
+
+assert.throws(
+  TypeError,
+  () => Temporal.PlainDateTime.compare({ year: 1976 }, dt2),
+  "object must contain at least the required properties (first arg)"
+);
+
+assert.throws(
+  TypeError,
+  () => Temporal.PlainDateTime.compare(dt1, { year: 2019 }),
+  "object must contain at least the required properties (second arg)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/compare/basic.js b/test/built-ins/Temporal/PlainDateTime/compare/basic.js
new file mode 100644
index 0000000000..a47e91cd62
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/compare/basic.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.compare
+description: Checking a typical case (nothing undefined, no NaNs, does not throw, etc.)
+features: [Temporal]
+---*/
+
+const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102);
+
+assert.sameValue(
+  Temporal.PlainDateTime.compare(dt1, dt1),
+  0,
+  "equal"
+);
+
+assert.sameValue(
+  Temporal.PlainDateTime.compare(dt1, dt2),
+  -1,
+  "smaller/larger"
+);
+
+assert.sameValue(
+  Temporal.PlainDateTime.compare(dt2, dt1),
+  1,
+  "larger/smaller"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/compare/cast.js b/test/built-ins/Temporal/PlainDateTime/compare/cast.js
new file mode 100644
index 0000000000..a9a09dc09a
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/compare/cast.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.compare
+description: Arguments may be casted (string, plain object)
+features: [Temporal]
+---*/
+
+const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102);
+
+assert.sameValue(
+  Temporal.PlainDateTime.compare({ year: 1976, month: 11, day: 18, hour: 15 }, dt2),
+  -1,
+  "casts first argument (plain object)"
+);
+
+assert.sameValue(
+  Temporal.PlainDateTime.compare("1976-11-18T15:23:30.123456789", dt2),
+  -1,
+  "casts first argument (string)"
+);
+
+assert.sameValue(
+  Temporal.PlainDateTime.compare(dt1, { year: 2019, month: 10, day: 29, hour: 10 }),
+  -1,
+  "casts second argument (plain object)"
+);
+
+assert.sameValue(
+  Temporal.PlainDateTime.compare(dt1, "2019-10-29T10:46:38.271986102"),
+  -1,
+  "casts second argument (string)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/constructor-full.js b/test/built-ins/Temporal/PlainDateTime/constructor-full.js
new file mode 100644
index 0000000000..8715f22122
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/constructor-full.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime
+description: Checking an explicitly constructed instance with all arguments
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const calendar = Temporal.Calendar.from("iso8601");
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar);
+
+TemporalHelpers.assertPlainDateTime(datetime,
+  1976, 11, "M11", 18, 15, 23, 30, 123, 456, 789,
+  "check instance (all arguments supplied)"
+);
+
+assert.sameValue(
+  datetime.calendar,
+  calendar,
+  "calendar supplied in constructor can be extracted and is unchanged"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/datetime-math.js b/test/built-ins/Temporal/PlainDateTime/datetime-math.js
new file mode 100644
index 0000000000..0f2e05c694
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/datetime-math.js
@@ -0,0 +1,47 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime
+description: Testing combinations of since, until, add, subtract, and negated
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+const later = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102);
+const units = ["years", "months", "weeks", "days", "hours", "minutes", "seconds"];
+
+units.forEach((largestUnit) => {
+  const diff = later.since(earlier, { largestUnit });
+  TemporalHelpers.assertDurationsEqual(
+    earlier.since(later, { largestUnit }),
+    diff.negated(),
+    `(${earlier}).since(${later}) == (${later}).since(${earlier}).negated()`
+  );
+  TemporalHelpers.assertDurationsEqual(
+    earlier.until(later, { largestUnit }),
+    diff,
+    `(${earlier}).until(${later}) == (${later}).since(${earlier})`
+  );
+  assert.sameValue(
+    earlier.add(diff).equals(later),
+    true,
+    `(${earlier}).add(${diff}) == (${later})`
+  );
+  assert.sameValue(
+    later.subtract(diff).equals(earlier),
+    true,
+    `(${later}).subtract(${diff}) == (${earlier})`
+  );
+  assert.sameValue(
+    earlier.subtract(diff.negated()).equals(later),
+    true,
+    "symmetrical with regard to negative durations (1)"
+  );
+  assert.sameValue(
+    later.add(diff.negated()).equals(earlier),
+    true,
+    "symmetrical with regard to negative durations (2)"
+  );
+});
diff --git a/test/built-ins/Temporal/PlainDateTime/hour-undefined.js b/test/built-ins/Temporal/PlainDateTime/hour-undefined.js
index e42831dcd6..a27c964d1c 100644
--- a/test/built-ins/Temporal/PlainDateTime/hour-undefined.js
+++ b/test/built-ins/Temporal/PlainDateTime/hour-undefined.js
@@ -5,12 +5,19 @@
 esid: sec-temporal.plaindatetime
 description: Hour argument defaults to 0 if not given
 features: [Temporal]
+includes: [temporalHelpers.js]
 ---*/
 
 const args = [2000, 5, 2];
 
-const explicit = new Temporal.PlainDateTime(...args, undefined);
-assert.sameValue(explicit.hour, 0, "hour default argument");
+TemporalHelpers.assertPlainDateTime(
+  new Temporal.PlainDateTime(...args, undefined),
+  2000, 5, "M05", 2, 0, 0, 0, 0, 0, 0,
+  "hour default argument (argument present)"
+);
 
-const implicit = new Temporal.PlainDateTime(...args);
-assert.sameValue(implicit.hour, 0, "hour default argument");
+TemporalHelpers.assertPlainDateTime(
+  new Temporal.PlainDateTime(...args),
+  2000, 5, "M05", 2, 0, 0, 0, 0, 0, 0,
+  "hour default argument (argument missing)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/microsecond-undefined.js b/test/built-ins/Temporal/PlainDateTime/microsecond-undefined.js
index 83004a3130..e2fd092f4a 100644
--- a/test/built-ins/Temporal/PlainDateTime/microsecond-undefined.js
+++ b/test/built-ins/Temporal/PlainDateTime/microsecond-undefined.js
@@ -5,12 +5,20 @@
 esid: sec-temporal.plaindatetime
 description: Microsecond argument defaults to 0 if not given
 features: [Temporal]
+includes: [temporalHelpers.js]
 ---*/
 
 const args = [2000, 5, 2, 12, 34, 56, 123];
 
-const explicit = new Temporal.PlainDateTime(...args, undefined);
-assert.sameValue(explicit.microsecond, 0, "microsecond default argument");
+TemporalHelpers.assertPlainDateTime(
+  new Temporal.PlainDateTime(...args, undefined),
+  2000, 5, "M05", 2, 12, 34, 56, 123, 0, 0,
+  "microsecond default argument (argument present)"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  new Temporal.PlainDateTime(...args),
+  2000, 5, "M05", 2, 12, 34, 56, 123, 0, 0,
+  "microsecond default argument (argument missing)"
+);
 
-const implicit = new Temporal.PlainDateTime(...args);
-assert.sameValue(implicit.microsecond, 0, "microsecond default argument");
diff --git a/test/built-ins/Temporal/PlainDateTime/millisecond-undefined.js b/test/built-ins/Temporal/PlainDateTime/millisecond-undefined.js
index de0c1b8447..33c2a7ec63 100644
--- a/test/built-ins/Temporal/PlainDateTime/millisecond-undefined.js
+++ b/test/built-ins/Temporal/PlainDateTime/millisecond-undefined.js
@@ -5,12 +5,19 @@
 esid: sec-temporal.plaindatetime
 description: Millisecond argument defaults to 0 if not given
 features: [Temporal]
+includes: [temporalHelpers.js]
 ---*/
 
 const args = [2000, 5, 2, 12, 34, 56];
 
-const explicit = new Temporal.PlainDateTime(...args, undefined);
-assert.sameValue(explicit.millisecond, 0, "millisecond default argument");
+TemporalHelpers.assertPlainDateTime(
+  new Temporal.PlainDateTime(...args, undefined),
+  2000, 5, "M05", 2, 12, 34, 56, 0, 0, 0,
+  "millisecond default argument (argument present)"
+);
 
-const implicit = new Temporal.PlainDateTime(...args);
-assert.sameValue(implicit.millisecond, 0, "millisecond default argument");
+TemporalHelpers.assertPlainDateTime(
+  new Temporal.PlainDateTime(...args),
+  2000, 5, "M05", 2, 12, 34, 56, 0, 0, 0,
+  "millisecond default argument (argument missing)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/minute-undefined.js b/test/built-ins/Temporal/PlainDateTime/minute-undefined.js
index 9ac682fc95..8792608e82 100644
--- a/test/built-ins/Temporal/PlainDateTime/minute-undefined.js
+++ b/test/built-ins/Temporal/PlainDateTime/minute-undefined.js
@@ -5,12 +5,19 @@
 esid: sec-temporal.plaindatetime
 description: Minute argument defaults to 0 if not given
 features: [Temporal]
+includes: [temporalHelpers.js]
 ---*/
 
 const args = [2000, 5, 2, 12];
 
-const explicit = new Temporal.PlainDateTime(...args, undefined);
-assert.sameValue(explicit.minute, 0, "minute default argument");
+TemporalHelpers.assertPlainDateTime(
+  new Temporal.PlainDateTime(...args, undefined),
+  2000, 5, "M05", 2, 12, 0, 0, 0, 0, 0,
+  "minute default argument (argument present)"
+);
 
-const implicit = new Temporal.PlainDateTime(...args);
-assert.sameValue(implicit.minute, 0, "minute default argument");
+TemporalHelpers.assertPlainDateTime(
+  new Temporal.PlainDateTime(...args),
+  2000, 5, "M05", 2, 12, 0, 0, 0, 0, 0,
+  "minute default argument (argument missing)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/nanosecond-undefined.js b/test/built-ins/Temporal/PlainDateTime/nanosecond-undefined.js
index f3f8b52c5d..a913a005ad 100644
--- a/test/built-ins/Temporal/PlainDateTime/nanosecond-undefined.js
+++ b/test/built-ins/Temporal/PlainDateTime/nanosecond-undefined.js
@@ -5,12 +5,19 @@
 esid: sec-temporal.plaindatetime
 description: Nanosecond argument defaults to 0 if not given
 features: [Temporal]
+includes: [temporalHelpers.js]
 ---*/
 
 const args = [2000, 5, 2, 12, 34, 56, 123, 456];
 
-const explicit = new Temporal.PlainDateTime(...args, undefined);
-assert.sameValue(explicit.nanosecond, 0, "nanosecond default argument");
+TemporalHelpers.assertPlainDateTime(
+  new Temporal.PlainDateTime(...args, undefined),
+  2000, 5, "M05", 2, 12, 34, 56, 123, 456, 0,
+  "nanosecond default argument (argument present)"
+);
 
-const implicit = new Temporal.PlainDateTime(...args);
-assert.sameValue(implicit.nanosecond, 0, "nanosecond default argument");
+TemporalHelpers.assertPlainDateTime(
+  new Temporal.PlainDateTime(...args),
+  2000, 5, "M05", 2, 12, 34, 56, 123, 456, 0,
+  "nanosecond default argument (argument missing)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/ambiguous-date.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/ambiguous-date.js
new file mode 100644
index 0000000000..476129400d
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/ambiguous-date.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.add
+description: Ambiguous addition is handled according to the overflow option
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0);
+
+TemporalHelpers.assertPlainDateTime(
+  jan31.add({ months: 1 }),
+  2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0,
+  "constrain when ambiguous result (overflow options not supplied)"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  jan31.add({ months: 1 }, { overflow: "constrain" }),
+  2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0,
+  "constrain when ambiguous result (overflow options supplied)"
+);
+
+assert.throws(
+  RangeError,
+  () => jan31.add({ months: 1 }, { overflow: "reject" }),
+  "throw when ambiguous result with reject"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-duration.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-duration.js
new file mode 100644
index 0000000000..7fd1317644
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-duration.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.add
+description: Duration object arguments are handled
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0);
+
+TemporalHelpers.assertPlainDateTime(
+  jan31.add(Temporal.Duration.from("P1MT1S")),
+  2020, 2, "M02", 29, 15, 0, 1, 0, 0, 0,
+  "Duration argument"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-object-insufficient-data.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-object-insufficient-data.js
new file mode 100644
index 0000000000..4780d5ac08
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-object-insufficient-data.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.add
+description: At least one recognized property has to be present in argument
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0);
+
+assert.throws(
+  TypeError,
+  () => jan31.add({}),
+  "empty object not acceptable"
+);
+
+assert.throws(
+  TypeError,
+  () => jan31.add({ month: 12 }), // should be "months"
+  "misspelled property in argument throws if no other properties are present"
+);
+
+assert.throws(
+  TypeError,
+  () => jan31.add({ nonsense: true }),
+  "unrecognized properties throw if no other recognized property is present"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  jan31.add({ nonsense: 1, days: 1 }),
+  2020, 2, "M02", 1, 15, 0, 0, 0, 0, 0,
+  "unrecognized properties ignored provided at least one recognized property is present"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-plain-object-mixed-signs.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-plain-object-mixed-signs.js
new file mode 100644
index 0000000000..0a308a79a0
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-plain-object-mixed-signs.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.add
+description: Positive and negative values in the temporalDurationLike argument are not acceptable
+features: [Temporal]
+---*/
+
+const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0);
+
+["constrain", "reject"].forEach((overflow) => {
+  assert.throws(
+    RangeError,
+    () => jan31.add({ hours: 1, minutes: -30 }, { overflow }),
+    `mixed positive and negative values always throw (overflow = "${overflow}")`
+  );
+});
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/hour-overflow.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/hour-overflow.js
new file mode 100644
index 0000000000..fe6f83e3f6
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/hour-overflow.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.add
+description: Testing overflow hours (adding hours that push one to the next/previous day)
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2020, 5, 31, 23, 12, 38, 271, 986, 102);
+
+TemporalHelpers.assertPlainDateTime(
+  earlier.add({ hours: 2 }),
+  2020, 6, "M06", 1, 1, 12, 38, 271, 986, 102,
+  "hours overflow (push to next day)"
+);
+
+const later = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102);
+
+TemporalHelpers.assertPlainDateTime(
+  later.add({ hours: -12 }),
+  2019, 10, "M10", 28, 22, 46, 38, 271, 986, 102,
+  "hours overflow (push to previous day)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/negative-duration.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/negative-duration.js
new file mode 100644
index 0000000000..c60f871e61
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/negative-duration.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.add
+description: Negative durations can be supplied
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0);
+
+TemporalHelpers.assertPlainDateTime(
+  jan31.add({ minutes: -30 }),
+  2020, 1, "M01", 31, 14, 30, 0, 0, 0, 0,
+  "negative minutes"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  jan31.add({ seconds: -30 }),
+  2020, 1, "M01", 31, 14, 59, 30, 0, 0, 0,
+  "negative seconds"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/options-empty.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/options-empty.js
new file mode 100644
index 0000000000..d7c923f6f2
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/options-empty.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.add
+description: Verify that undefined options are handled correctly.
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0);
+
+TemporalHelpers.assertPlainDateTime(
+  jan31.add({ months: 1 }, {}),
+  2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0,
+  "options may be empty object"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  jan31.add({ months: 1 }, () => {}),
+  2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0,
+  "options may be function object"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/options-invalid.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/options-invalid.js
new file mode 100644
index 0000000000..9255c7a10f
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/options-invalid.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.add
+description: Various invalid (wrong type) values for options argument
+features: [Temporal, Symbol]
+---*/
+
+const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0);
+
+const badOptions = [null, 1, 'hello', true, Symbol('foo'), 1n];
+
+badOptions.forEach((bad) => {
+  assert.throws(
+    TypeError,
+    () => jan31.add({ years: 1 }, bad),
+    `invalid options (${typeof bad})`
+  );
+});
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js
index 2ff326b8d6..40124a8f32 100644
--- a/test/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js
@@ -20,4 +20,12 @@ features: [Temporal]
 
 const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12);
 const duration = new Temporal.Duration(3, 3, 0, 3, 3);
-assert.throws(RangeError, () => datetime.add(duration, { overflow: "other string" }));
+
+const badOverflows = ['', 'CONSTRAIN', 'balance', "other string"];
+badOverflows.forEach((overflow) => {
+  assert.throws(
+    RangeError,
+    () => datetime.add({ months: 1 }, { overflow }),
+    `invalid overflow ("${overflow}")`
+  );
+});
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/basic.js
new file mode 100644
index 0000000000..437ac74b60
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/basic.js
@@ -0,0 +1,12 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-temporal.plaindatetime.prototype.dayofweek
+description: Checking day of week for a "normal" case (non-undefined, non-boundary case, etc.)
+features: [Temporal]
+---*/
+
+const calendar = Temporal.Calendar.from("iso8601");
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar);
+assert.sameValue(datetime.dayOfWeek, 4, "check day of week information");
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/basic.js
new file mode 100644
index 0000000000..98ee0fbef0
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/basic.js
@@ -0,0 +1,12 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-temporal.plaindatetime.prototype.dayofyear
+description: Checking day of year for a "normal" case (non-undefined, non-boundary case, etc.)
+features: [Temporal]
+---*/
+
+const calendar = Temporal.Calendar.from("iso8601");
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar);
+assert.sameValue(datetime.dayOfYear, 323, "check day of year information");
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/basic.js
new file mode 100644
index 0000000000..7059e7a0cb
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/basic.js
@@ -0,0 +1,12 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-temporal.plaindatetime.prototype.daysinmonth
+description: Checking days in month for a "normal" case (non-undefined, non-boundary case, etc.)
+features: [Temporal]
+---*/
+
+const calendar = Temporal.Calendar.from("iso8601");
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar);
+assert.sameValue(datetime.daysInMonth, 30, "check days in month information");
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/basic.js
new file mode 100644
index 0000000000..f34e00f756
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/basic.js
@@ -0,0 +1,12 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-temporal.plaindatetime.prototype.daysinweek
+description: Checking days in week for a "normal" case (non-undefined, non-boundary case, etc.)
+features: [Temporal]
+---*/
+
+const calendar = Temporal.Calendar.from("iso8601");
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar);
+assert.sameValue(datetime.daysInWeek, 7, "check days in week information");
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/daysInYear/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/daysInYear/basic.js
new file mode 100644
index 0000000000..d3c7a5d8a9
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/daysInYear/basic.js
@@ -0,0 +1,12 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-temporal.plaindatetime.prototype.daysinyear
+description: Checking days in year for a "normal" case (non-undefined, non-boundary case, etc.)
+features: [Temporal]
+---*/
+
+const calendar = Temporal.Calendar.from("iso8601");
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar);
+assert.sameValue(datetime.daysInYear, 366, "check days in year information");
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/equals/argument-object-insufficient-data.js b/test/built-ins/Temporal/PlainDateTime/prototype/equals/argument-object-insufficient-data.js
new file mode 100644
index 0000000000..054e032ded
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/equals/argument-object-insufficient-data.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.equals
+description: If argument is an object, it must contain sufficient information
+features: [Temporal]
+---*/
+
+const dt = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102);
+
+assert.throws(
+  TypeError,
+  () => dt.equals({ year: 1976 }),
+  "object must contain required properties"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js
new file mode 100644
index 0000000000..c83cffeef4
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js
@@ -0,0 +1,14 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.equals
+description: Checking a typical case (everything defined, no NaNs, nothing throws, etc.)
+features: [Temporal]
+---*/
+
+const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102);
+
+assert.sameValue(dt1.equals(dt1), true, "equal");
+assert.sameValue(dt1.equals(dt2), false, "unequal");
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/equals/cast.js b/test/built-ins/Temporal/PlainDateTime/prototype/equals/cast.js
new file mode 100644
index 0000000000..bad87ec1d7
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/equals/cast.js
@@ -0,0 +1,46 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.equals
+description: Argument may be cast
+features: [Temporal]
+---*/
+
+const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102);
+
+assert.sameValue(
+  dt1.equals({
+    year: 1976,
+    month: 11,
+    day: 18,
+    hour: 15,
+    minute: 23,
+    second: 30,
+    millisecond: 123,
+    microsecond: 456,
+    nanosecond: 789
+  }),
+  true,
+  "casts argument (plain object, positive)"
+);
+
+
+assert.sameValue(
+  dt2.equals({ year: 1976, month: 11, day: 18, hour: 15 }),
+  false,
+  "casts argument (plain object, negative)"
+);
+
+assert.sameValue(
+  dt1.equals("1976-11-18T15:23:30.123456789"),
+  true,
+  "casts argument (string, positive)"
+);
+
+assert.sameValue(
+  dt2.equals("1976-11-18T15:23:30.123456789"),
+  false,
+  "casts argument (string, negative)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/basic.js
new file mode 100644
index 0000000000..f918a25355
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/basic.js
@@ -0,0 +1,12 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-temporal.plaindatetime.prototype.monthsinyear
+description: Checking months in year for a "normal" case (non-undefined, non-boundary case, etc.)
+features: [Temporal]
+---*/
+
+const calendar = Temporal.Calendar.from("iso8601");
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar);
+assert.sameValue(datetime.monthsInYear, 12, "check months in year information");
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/ambiguous-date.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/ambiguous-date.js
new file mode 100644
index 0000000000..f6fe8738ae
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/ambiguous-date.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.subtract
+description: Ambiguous subtraction is handled according to the overflow option
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const mar31 = new Temporal.PlainDateTime(2020, 3, 31, 15, 0);
+
+TemporalHelpers.assertPlainDateTime(
+  mar31.subtract({ months: 1 }),
+  2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0,
+  "constrain when ambiguous result (overflow options not supplied)"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  mar31.subtract({ months: 1 }, { overflow: "constrain" }),
+  2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0,
+  "constrain when ambiguous result (overflow options supplied)"
+);
+
+assert.throws(
+  RangeError,
+  () => mar31.subtract({ months: 1 }, { overflow: "reject" }),
+  "throw when ambiguous result with reject"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-duration.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-duration.js
new file mode 100644
index 0000000000..fb0d3d1f8e
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-duration.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.subtract
+description: Duration object arguments are handled
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0);
+
+const subtractWithDuration = jan31.subtract(new Temporal.Duration(0, 1, 0, 0, 0, 1));
+TemporalHelpers.assertPlainDateTime(
+  subtractWithDuration,
+  2019, 12, "M12", 31, 14, 59, 0, 0, 0, 0,
+  "Duration argument"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-object-insufficient-data.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-object-insufficient-data.js
new file mode 100644
index 0000000000..450d14cefe
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-object-insufficient-data.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.subtract
+description: At least one recognized property has to be present in argument
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0);
+
+assert.throws(
+  TypeError,
+  () => jan31.subtract({}),
+  "empty object not acceptable"
+);
+
+assert.throws(
+  TypeError,
+  () => jan31.subtract({ month: 12 }), // should be "months"
+  "misspelled property in argument throws if no other properties are present"
+);
+
+assert.throws(
+  TypeError,
+  () => jan31.subtract({ nonsense: true }),
+  "unrecognized properties throw if no other recognized property is present"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  jan31.subtract({ nonsense: 1, days: 1 }),
+  2020, 1, "M01", 30, 15, 0, 0, 0, 0, 0,
+  "unrecognized properties ignored provided at least one recognized property is present"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-plain-object-mixed-signs.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-plain-object-mixed-signs.js
new file mode 100644
index 0000000000..cabfd20939
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-plain-object-mixed-signs.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.subtract
+description: Positive and negative values in the temporalDurationLike argument are not acceptable
+features: [Temporal]
+---*/
+
+const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0);
+
+["constrain", "reject"].forEach((overflow) => {
+  assert.throws(
+    RangeError,
+    () => jan31.subtract({ hours: 1, minutes: -30 }, { overflow }),
+    `mixed positive and negative values always throw (overflow = "${overflow}")`
+  );
+});
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/hour-overflow.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/hour-overflow.js
new file mode 100644
index 0000000000..bda7309920
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/hour-overflow.js
@@ -0,0 +1,30 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.subtract
+description: Testing overflow hours (subtracting hours that push one to the next/previous day)
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const dt = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102);
+const later = new Temporal.PlainDateTime(2020, 5, 31, 23, 12, 38, 271, 986, 102);
+
+TemporalHelpers.assertPlainDateTime(
+  dt.subtract({ hours: 12 }),
+  2019, 10, "M10", 28, 22, 46, 38, 271, 986, 102,
+  "subtract result"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  dt.add({ hours: -12 }),
+  2019, 10, "M10", 28, 22, 46, 38, 271, 986, 102,
+  "hour overflow (pushes to previous day)"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  later.subtract({ hours: -2 }),
+  2020, 6, "M06", 1, 1, 12, 38, 271, 986, 102,
+  "subtracting a negative amount of hours is equivalent to adding hours"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-duration.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-duration.js
new file mode 100644
index 0000000000..672d87d9fc
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-duration.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.subtract
+description: Negative durations can be supplied
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0);
+
+TemporalHelpers.assertPlainDateTime(
+  jan31.subtract({ minutes: -30 }),
+  2020, 1, "M01", 31, 15, 30, 0, 0, 0, 0,
+  "negative minutes"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  jan31.subtract({ seconds: -30 }),
+  2020, 1, "M01", 31, 15, 0, 30, 0, 0, 0,
+  "negative seconds"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-empty.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-empty.js
new file mode 100644
index 0000000000..ca9fd5112a
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-empty.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.subtract
+description: Verify that undefined options are handled correctly.
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0);
+
+TemporalHelpers.assertPlainDateTime(
+  jan31.subtract({ months: 2 }, {}),
+  2019, 11, "M11", 30, 15, 0, 0, 0, 0, 0,
+  "options may be empty object"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  jan31.subtract({ months: 2 }, () => {}),
+  2019, 11, "M11", 30, 15, 0, 0, 0, 0, 0,
+  "options may be function object"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-invalid.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-invalid.js
new file mode 100644
index 0000000000..ad8b1244e5
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-invalid.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.subtract
+description: Various invalid (wrong type) values for options argument
+features: [Temporal, Symbol]
+---*/
+
+const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0);
+
+const badOptions = [null, 1, 'hello', true, Symbol('foo'), 1n];
+
+badOptions.forEach((bad) => {
+  assert.throws(
+    TypeError,
+    () => jan31.subtract({ years: 1 }, bad),
+    `invalid options (${typeof bad})`
+  );
+});
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/basic.js
new file mode 100644
index 0000000000..5e5b7596a4
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/basic.js
@@ -0,0 +1,13 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tostring
+description: Checking the string form of an explicitly constructed instance with all arguments
+features: [Temporal]
+---*/
+
+const calendar = Temporal.Calendar.from("iso8601");
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar);
+
+assert.sameValue(datetime.toString(), "1976-11-18T15:23:30.123456789", "check string value");
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/casts-argument.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/casts-argument.js
new file mode 100644
index 0000000000..979759ddf6
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/casts-argument.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: String and object arguments get cast
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+
+TemporalHelpers.assertDuration(
+  datetime.until({ year: 2019, month: 10, day: 29, hour: 10 }),
+  0, 0, 0, 15684, 18, 36, 29, 876, 543, 211,
+  "plain object argument"
+);
+
+TemporalHelpers.assertDuration(
+  datetime.until("2019-10-29T10:46:38.271986102"),
+  0, 0, 0, 15684, 19, 23, 8, 148, 529, 313,
+  "string argument gets cast"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/different-calendars-throws.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/different-calendars-throws.js
new file mode 100644
index 0000000000..9a8e31791c
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/different-calendars-throws.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: Using different calendars is not acceptable
+features: [Temporal]
+---*/
+
+const dt1 = new Temporal.PlainDateTime(2000, 1, 1, 0, 0, 0, 0, 0, 0);
+
+const cal = {
+  id: 'thisisnotiso'
+};
+
+const dt2 = new Temporal.PlainDateTime(2000, 1, 1, 0, 0, 0, 0, 0, 0, cal);
+
+assert.throws(
+  RangeError,
+  () => dt1.until(dt2),
+  "cannot use until with PDTs having different calendars"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/inverse.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/inverse.js
new file mode 100644
index 0000000000..026024e310
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/inverse.js
@@ -0,0 +1,14 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: The since and until operations act as inverses
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const dt = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+const later = new Temporal.PlainDateTime(2016, 3, 3, 18);
+
+TemporalHelpers.assertDurationsEqual(dt.until(later), later.since(dt), "until and since act as inverses");
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js
new file mode 100644
index 0000000000..d064e8246a
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: Do not return Durations with unnecessary units
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const lastFeb20 = new Temporal.PlainDateTime(2020, 2, 29, 0, 0);
+const lastFeb21 = new Temporal.PlainDateTime(2021, 2, 28, 0, 0);
+
+TemporalHelpers.assertDuration(
+  lastFeb20.until(lastFeb21, { largestUnit: "months" }),
+  0, 12, 0, 0, 0, 0, 0, 0, 0, 0,
+  "does not include higher units than necessary (largest unit = months)"
+);
+
+TemporalHelpers.assertDuration(
+  lastFeb20.until(lastFeb21, { largestUnit: "years" }),
+  1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  "does not include higher units than necessary (largest unit = years)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/returns-days.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/returns-days.js
new file mode 100644
index 0000000000..b6e00ead5d
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/returns-days.js
@@ -0,0 +1,38 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: Return days by default
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const feb20 = new Temporal.PlainDateTime(2020, 2, 1, 0, 0);
+const feb21 = new Temporal.PlainDateTime(2021, 2, 1, 0, 0);
+
+TemporalHelpers.assertDuration(
+  feb20.until(feb21, { largestUnit: "auto" }),
+  0, 0, 0, 366, 0, 0, 0, 0, 0, 0,
+  "defaults to returning days (largest unit = auto)"
+);
+
+TemporalHelpers.assertDuration(
+  feb20.until(feb21, { largestUnit: "days" }),
+  0, 0, 0, 366, 0, 0, 0, 0, 0, 0,
+  "defaults to returning days (largest unit = days)"
+);
+
+TemporalHelpers.assertDuration(
+  feb20.until(new Temporal.PlainDateTime(2021, 2, 1, 0, 0, 0, 0, 0, 1)),
+  0, 0, 0, 366, 0, 0, 0, 0, 0, 1,
+  "returns nanoseconds if argument is PDT with non-zero nanoseconds"
+);
+
+const dt = new Temporal.PlainDateTime(2020, 2, 1, 0, 0, 0, 0, 0, 1);
+
+TemporalHelpers.assertDuration(
+  dt.until(feb21),
+  0, 0, 0, 365, 23, 59, 59, 999, 999, 999,
+  "one nanosecond away from one year away"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/subseconds.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/subseconds.js
new file mode 100644
index 0000000000..d731a2111f
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/subseconds.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: Largest unit is respected
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const feb20 = new Temporal.PlainDateTime(2020, 2, 1, 0, 0);
+
+const later = feb20.add({
+  days: 1,
+  milliseconds: 250,
+  microseconds: 250,
+  nanoseconds: 250
+});
+
+TemporalHelpers.assertDuration(
+  feb20.until(later, { largestUnit: "milliseconds" }),
+  0, 0, 0, 0, 0, 0, 0, 86400250, 250, 250,
+  "can return subseconds (millisecond precision)"
+);
+
+TemporalHelpers.assertDuration(
+  feb20.until(later, { largestUnit: "microseconds" }),
+  0, 0, 0, 0, 0, 0, 0, 0, 86400250250, 250,
+  "can return subseconds (microsecond precision)"
+);
+
+TemporalHelpers.assertDuration(
+  feb20.until(later, { largestUnit: "nanoseconds" }),
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 86400250250250,
+  "can return subseconds (nanosecond precision)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js
new file mode 100644
index 0000000000..f13fcb1834
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js
@@ -0,0 +1,66 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: Largest unit is respected
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const feb20 = new Temporal.PlainDateTime(2020, 2, 1, 0, 0);
+const feb21 = new Temporal.PlainDateTime(2021, 2, 1, 0, 0);
+
+TemporalHelpers.assertDuration(
+  feb20.until(feb21, { largestUnit: "years" }),
+  1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  "can return lower or higher units (years)"
+);
+
+TemporalHelpers.assertDuration(
+  feb20.until(feb21, { largestUnit: "months" }),
+  0, 12, 0, 0, 0, 0, 0, 0, 0, 0,
+  "can return lower or higher units (months)"
+);
+
+TemporalHelpers.assertDuration(
+  feb20.until(feb21, { largestUnit: "weeks" }),
+  0, 0, 52, 2, 0, 0, 0, 0, 0, 0,
+  "can return lower or higher units (weeks)"
+);
+
+TemporalHelpers.assertDuration(
+  feb20.until(feb21, { largestUnit: "hours" }),
+  0, 0, 0, 0, 8784, 0, 0,0, 0, 0,
+  "can return lower or higher units (hours)"
+);
+
+TemporalHelpers.assertDuration(
+  feb20.until(feb21, { largestUnit: "minutes" }),
+  0, 0, 0, 0, 0, 527040, 0, 0, 0, 0, 0,
+  "can return lower or higher units (minutes)"
+);
+
+TemporalHelpers.assertDuration(
+  feb20.until(feb21, { largestUnit: "seconds" }),
+  0, 0, 0, 0, 0, 0, 31622400, 0, 0, 0,
+  "can return lower or higher units (seconds)"
+);
+
+TemporalHelpers.assertDuration(
+  feb20.until(feb21, { largestUnit: "milliseconds" }),
+  0, 0, 0, 0, 0, 0, 0, 31622400000, 0, 0,
+  "can return lower or higher units (milliseconds)"
+);
+
+TemporalHelpers.assertDuration(
+  feb20.until(feb21, { largestUnit: "microseconds" }),
+  0, 0, 0, 0, 0, 0, 0, 0, 31622400000000, 0,
+  "can return lower or higher units (microseconds)"
+);
+
+TemporalHelpers.assertDuration(
+  feb20.until(feb21, { largestUnit: "nanoseconds" }),
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 31622400000000000,
+  "can return lower or higher units (nanoseconds)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/weeks-months-mutually-exclusive.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/weeks-months-mutually-exclusive.js
new file mode 100644
index 0000000000..06d8e2b706
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/weeks-months-mutually-exclusive.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: Weeks and months are mutually exclusive
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const dt = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+const laterDateTime = dt.add({ days: 42, hours: 3 });
+
+TemporalHelpers.assertDuration(
+  dt.until(laterDateTime, { largestUnit: "weeks" }),
+  0, 0, 6, 0, 3, 0, 0, 0, 0, 0,
+  "weeks and months mutually exclusive (1)"
+);
+
+TemporalHelpers.assertDuration(
+  dt.until(laterDateTime, { largestUnit: "months" }),
+  0, 1, 0, 12, 3, 0, 0, 0, 0, 0,
+  "weeks and months mutually exclusive (2)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/valueOf/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/valueOf/basic.js
new file mode 100644
index 0000000000..3da2878448
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/valueOf/basic.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.valueof
+description: Comparison operators (except !== and ===) do not work
+features: [Temporal]
+---*/
+
+const dt1 = new Temporal.PlainDateTime(1963, 2, 13, 9, 36, 29, 123, 456, 789);
+const dt1again = new Temporal.PlainDateTime(1963, 2, 13, 9, 36, 29, 123, 456, 789);
+const dt2 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+
+assert.sameValue(dt1 === dt1, true, "object equality implies ===");
+assert.sameValue(dt1 !== dt1again, true, "object non-equality, even if all data is the same, implies !==");
+assert.throws(TypeError, () => dt1 < dt1, "< throws (same objects)");
+assert.throws(TypeError, () => dt1 < dt2, "< throws (different objects)");
+assert.throws(TypeError, () => dt1 > dt1, "> throws (same objects)");
+assert.throws(TypeError, () => dt1 > dt2, "> throws (different objects)");
+assert.throws(TypeError, () => dt1 <= dt1, "<= does not throw (same objects)");
+assert.throws(TypeError, () => dt1 <= dt2, "<= throws (different objects)");
+assert.throws(TypeError, () => dt1 >= dt1, ">= throws (same objects)");
+assert.throws(TypeError, () => dt1 >= dt2, ">= throws (different objects)");
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/basic.js
new file mode 100644
index 0000000000..6273dbc54c
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/basic.js
@@ -0,0 +1,12 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-temporal.plaindatetime.prototype.weekofyear
+description: Checking week of year for a "normal" case (non-undefined, non-boundary case, etc.)
+features: [Temporal]
+---*/
+
+const calendar = Temporal.Calendar.from("iso8601");
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar);
+assert.sameValue(datetime.weekOfYear, 47, "check week of year information");
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/argument-object-insufficient-data.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/argument-object-insufficient-data.js
new file mode 100644
index 0000000000..5c4c4e2b5b
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/argument-object-insufficient-data.js
@@ -0,0 +1,42 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Unrecognized properties (incl. plurals of recognized units) are ignored
+esid: sec-temporal.plaindatetime.prototype.with
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321);
+
+assert.throws(
+  TypeError,
+  () => instance.with({}),
+  "empty object not acceptable"
+);
+
+const units = ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"];
+
+units.forEach((unit) => {
+  let plural = `${unit}s`;
+  let options = {};
+  options[plural] = 1;
+  assert.throws(
+    TypeError,
+    () => instance.with(options),
+    `plural unit ("${plural}" vs "${unit}") is not acceptable`
+  );
+});
+
+assert.throws(
+  TypeError,
+  () => instance.with({nonsense: true}),
+  "throw if no recognized properties present"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  instance.with({year: 1965, nonsense: true}),
+  1965, 5, "M05", 2, 12, 34, 56, 987, 654, 321,
+  "unrecognized properties ignored & does not throw if recognized properties present)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/basic.js
new file mode 100644
index 0000000000..d021389adc
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/basic.js
@@ -0,0 +1,77 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: A variety of "normal" (non-throwing, non-boundary case, non-null, etc.) arguments
+esid: sec-temporal.plaindatetime.prototype.with
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+
+TemporalHelpers.assertPlainDateTime(
+  datetime.with({ year: 2019 }),
+  2019, 11, "M11", 18, 15, 23, 30, 123, 456, 789,
+  "with year works"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  datetime.with({ month: 5 }),
+  1976, 5, "M05", 18, 15, 23, 30, 123, 456, 789,
+  "with month works"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  datetime.with({ monthCode: "M05" }),
+  1976, 5, "M05", 18, 15, 23, 30, 123, 456, 789,
+  "with month code works"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  datetime.with({ day: 5 }),
+  1976, 11, "M11", 5, 15, 23, 30, 123, 456, 789,
+  "with day works"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  datetime.with({ hour: 5 }),
+  1976, 11, "M11", 18, 5, 23, 30, 123, 456, 789,
+  "with hour works"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  datetime.with({ minute: 5 }),
+  1976, 11, "M11", 18, 15, 5, 30, 123, 456, 789,
+  "with minute works"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  datetime.with({ second: 5 }),
+  1976, 11, "M11", 18, 15, 23, 5, 123, 456, 789,
+  "with second works"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  datetime.with({ millisecond: 5 }),
+  1976, 11, "M11", 18, 15, 23, 30, 5, 456, 789,
+  "with millisecond works"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  datetime.with({ microsecond: 5 }),
+  1976, 11, "M11", 18, 15, 23, 30, 123, 5, 789,
+  "with microsecond works"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  datetime.with({ nanosecond: 5 }),
+  1976, 11, "M11", 18, 15, 23, 30, 123, 456, 5,
+  "with nanosecond works"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  datetime.with({ month: 5, second: 15 }),
+  1976, 5, "M05", 18, 15, 23, 15, 123, 456, 789,
+  "with month and second works"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-throws.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-throws.js
new file mode 100644
index 0000000000..165c7b57b2
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-throws.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Throws if a calendar is supplied
+esid: sec-temporal.plaindatetime.prototype.with
+features: [Temporal]
+---*/
+
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+
+assert.throws(
+  TypeError,
+  () => datetime.with({ year: 2021, calendar: "iso8601" }),
+  "throws with calendar property"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/month-and-monthcode-must-agree.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/month-and-monthcode-must-agree.js
new file mode 100644
index 0000000000..6e81bac840
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/month-and-monthcode-must-agree.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.with
+description: The month and month code should agree
+features: [Temporal]
+---*/
+
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+
+assert.throws(
+  RangeError,
+  () => datetime.with({ month: 5, monthCode: "M06" }),
+  "month and monthCode must agree"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/multiple-unrecognized-properties-ignored.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/multiple-unrecognized-properties-ignored.js
new file mode 100644
index 0000000000..5a5309f2e2
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/multiple-unrecognized-properties-ignored.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Unrecognized units are ignored
+esid: sec-temporal.plaindatetime.prototype.with
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+const units = ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"];
+
+units.forEach((unit) => {
+  let plural = `${unit}s`;
+  let arg = { month: 12 };
+  arg[plural] = 1;
+  TemporalHelpers.assertPlainDateTime(
+    datetime.with(arg),
+    1976, 12, "M12", 18, 15, 23, 30, 123, 456, 789,
+    `unrecognized property (${plural}) gets ignored`
+  );
+});
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/options-empty.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/options-empty.js
new file mode 100644
index 0000000000..3bc92e0d8e
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/options-empty.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.with
+description: Verify that undefined options are handled correctly.
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+
+TemporalHelpers.assertPlainDateTime(
+  datetime.with({ day: 40 }, {}),
+  1976, 11, "M11", 30, 15, 23, 30, 123, 456, 789,
+  "options may be empty object"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  datetime.with({ day: 40 }, () => {}),
+  1976, 11, "M11", 30, 15, 23, 30, 123, 456, 789,
+  "read empty options from function object"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/options-invalid.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/options-invalid.js
new file mode 100644
index 0000000000..8f52de349e
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/options-invalid.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.with
+description: Verify that undefined options are handled correctly.
+features: [Temporal, Symbol]
+---*/
+
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+
+const badOptions = [null, 1, 'hello', true, Symbol('foo'), 1n];
+
+badOptions.forEach((bad) => {
+  assert.throws(
+    TypeError,
+    () => datetime.with({ day: 5 }, bad),
+    `bad options (${typeof bad})`
+  );
+});
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js
index 9e3f561784..c23b9e9e97 100644
--- a/test/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js
@@ -18,4 +18,10 @@ features: [Temporal]
 ---*/
 
 const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12);
-assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: "other string" }));
+const badOverflows = ["", "CONSTRAIN", "balance", "other string"];
+badOverflows.forEach((overflow) => {
+  assert.throws(
+    RangeError,
+    () => datetime.with({ minute: 45 }, { overflow }),
+    `invalid overflow string (${overflow})`);
+});
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/string-throws.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/string-throws.js
new file mode 100644
index 0000000000..405a12fadb
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/string-throws.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Throws if a string argument is supplied
+esid: sec-temporal.plaindatetime.prototype.with
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321);
+
+const baddies = ["12:00", "1995-04-07", "2019-05-17T12:34:56.007007007", "2019-05-17T12:34:56.007007007Z", "42"];
+
+baddies.forEach((bad) => {
+  assert.throws(
+    TypeError,
+    () => instance.with(bad),
+    `bad argument (${bad})`
+  );
+});
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/timezone-throws.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/timezone-throws.js
new file mode 100644
index 0000000000..0931204b16
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/timezone-throws.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Throws if a timezone is supplied
+esid: sec-temporal.plaindatetime.prototype.with
+features: [Temporal]
+---*/
+
+const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789);
+
+assert.throws(
+  TypeError,
+  () => datetime.with({ year: 2021, timeZone: "UTC" }),
+  "throws with timezone property"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insuffcient-data.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insuffcient-data.js
new file mode 100644
index 0000000000..0ddb21932d
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insuffcient-data.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.withplaindate
+description: Unrecognized properties of plain object ignored
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30);
+
+assert.throws(
+  TypeError,
+  () => dt.withPlainDate({}),
+  "empty object not acceptable"
+);
+
+assert.throws(
+  TypeError,
+  () => dt.withPlainDate({ months: 12 }), // should be "month"
+  "no recognized properties (look like it might work)"
+);
+
+assert.throws(
+  TypeError,
+  () => dt.with({nonsense: true}),
+  "no recognized properties (clearly won't work)"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  dt.withPlainDate({ year: 2000, month: 6, day: 1, months: 123 }), // 'months' unrecognized; see above
+  2000, 6, "M06", 1, 3, 24, 30, 0, 0, 0,
+  "unrecognized properties ignored & does not throw if recognized properties present)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object.js
new file mode 100644
index 0000000000..b7e336344a
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.withplaindate
+description: Plain object may be acceptable
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30);
+
+TemporalHelpers.assertPlainDateTime(
+  dt.withPlainDate({ year: 2000, month: 6, day: 1 }),
+  2000, 6, "M06", 1, 3, 24, 30, 0, 0, 0,
+  "plain object works"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate.js
new file mode 100644
index 0000000000..14ebb69c03
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.withplaindate
+description: PlainDate object is acceptable
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30);
+const date = new Temporal.PlainDate(2020, 1, 23);
+
+TemporalHelpers.assertPlainDateTime(
+  dt.withPlainDate(date),
+  2020, 1, "M01", 23, 3, 24, 30, 0, 0, 0,
+  "PlainDate argument works"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js
new file mode 100644
index 0000000000..f3349a95df
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.withplaindate
+description: New calendar is preserved if original PDT has ISO calendar
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const cal = {
+  id: 'thisisnotiso',
+  era() { return "the era"; },
+  eraYear() { return 1909; },
+  toString() { return "this is a string"; },
+  year() { return 2008; },
+  month() { return 9; },
+  monthCode() { return "M09"; },
+  day() { return 6; }
+};
+const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30, 0, 0, 0, cal);
+const shifted = dt.withPlainDate("2010-11-12");
+
+TemporalHelpers.assertPlainDateTime(
+  shifted,
+  2008, 9, "M09", 6, 3, 24, 30, 0, 0, 0,
+  "calendar is unchanged if input has ISO calendar (1)",
+  "the era",
+  1909
+);
+
+assert.sameValue(
+  shifted.calendar,
+  cal,
+  "calendar is unchanged if input has ISO calendar (2)"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string.js
new file mode 100644
index 0000000000..902cae34dc
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.withplaindate
+description: PlainDate-like string argument is acceptable
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30);
+
+TemporalHelpers.assertPlainDateTime(
+  dt.withPlainDate("2018-09-15"),
+  2018, 9, "M09", 15, 3, 24, 30, 0, 0, 0,
+  "PlainDate-like string argument works"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/non-compatible-calendars-throw.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/non-compatible-calendars-throw.js
new file mode 100644
index 0000000000..505df4d3b5
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/non-compatible-calendars-throw.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.withplaindate
+description: If two non-ISO calendars are involved, an error is raised
+features: [Temporal]
+---*/
+
+const cal = {
+  id: 'foo',
+  toString() { return "this is a string"; },
+};
+
+const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30, 0, 0, 0, cal);
+
+const anotherCal = {
+  id: 'bar',
+  toString() { return "this is another string"; },
+};
+
+const date = new Temporal.PlainDate(2008, 9, 6, anotherCal);
+
+assert.throws(
+  RangeError,
+  () => dt.withPlainDate(date),
+  "throws if both `this` and `other` have a non-ISO calendar"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-object-insufficient-data.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-object-insufficient-data.js
new file mode 100644
index 0000000000..3143b43c5e
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-object-insufficient-data.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.withplaintime
+description: A plain object can be used as an argument
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const dt = new Temporal.PlainDateTime(2015, 12, 7, 3, 24, 30, 0, 3, 500);
+
+assert.throws(
+  TypeError,
+  () => dt.withPlainTime({}),
+  "empty object not an acceptable argument"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  dt.withPlainTime({ hour: 10 }),
+  2015, 12, "M12", 7, 10, 0, 0, 0, 0, 0,
+  "plain object (hour) works"
+);
+
+assert.throws(
+  TypeError,
+  () => dt.withPlainTime({ hours: 9 }), // should be "hour", see above
+  "plain object with a single unrecognized property fails"
+);
+
+TemporalHelpers.assertPlainDateTime(
+  dt.withPlainTime({ hour: 10, seconds: 123 }),
+  2015, 12, "M12", 7, 10, 0, 0, 0, 0, 0,
+  "unrecognized properties are ignored if at least one recognized property is present"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-without-time-designator.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-without-time-designator.js
new file mode 100644
index 0000000000..2acd0c8a3a
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-without-time-designator.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.withplaintime
+description: String argument without ISO 8601 time designator "T" allowed
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const dt = new Temporal.PlainDateTime(2015, 12, 7, 3, 24, 30, 0, 3, 500);
+
+TemporalHelpers.assertPlainDateTime(
+  dt.withPlainTime("12:34"),
+  2015, 12, "M12", 7, 12, 34, 0, 0, 0, 0,
+  "time-like string works"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-time.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-time.js
new file mode 100644
index 0000000000..885116f7d0
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-time.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.withplaintime
+description: An instance of PlainTime can be used as an argument
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const dt = new Temporal.PlainDateTime(2015, 12, 7, 3, 24, 30, 0, 3, 500);
+const hour = 11;
+const minute = 22;
+const time = new Temporal.PlainTime(hour, minute);
+
+TemporalHelpers.assertPlainDateTime(
+  dt.withPlainTime(time),
+  2015,
+  12,
+  "M12",
+  7,
+  hour,
+  minute,
+  0,
+  0,
+  0,
+  0,
+  "PlainTime argument works"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/no-argument-default-to-midnight.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/no-argument-default-to-midnight.js
new file mode 100644
index 0000000000..bcda293fb2
--- /dev/null
+++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/no-argument-default-to-midnight.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.withplaintime
+description: If no argument is given, default to midnight
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const dt = new Temporal.PlainDateTime(2015, 12, 7, 3, 24, 30, 0, 3, 500);
+
+TemporalHelpers.assertPlainDateTime(
+  dt.withPlainTime(),
+  2015, 12, "M12", 7, 0, 0, 0, 0, 0, 0,
+  "no argument defaults to midnight"
+);
diff --git a/test/built-ins/Temporal/PlainDateTime/second-undefined.js b/test/built-ins/Temporal/PlainDateTime/second-undefined.js
index 9ec2ea3ef7..4b8422d4c3 100644
--- a/test/built-ins/Temporal/PlainDateTime/second-undefined.js
+++ b/test/built-ins/Temporal/PlainDateTime/second-undefined.js
@@ -4,13 +4,20 @@
 /*---
 esid: sec-temporal.plaindatetime
 description: Second argument defaults to 0 if not given
+includes: [temporalHelpers.js]
 features: [Temporal]
 ---*/
 
 const args = [2000, 5, 2, 12, 34];
 
-const explicit = new Temporal.PlainDateTime(...args, undefined);
-assert.sameValue(explicit.second, 0, "second default argument");
+TemporalHelpers.assertPlainDateTime(
+  new Temporal.PlainDateTime(...args, undefined),
+  2000, 5, "M05", 2, 12, 34, 0, 0, 0, 0,
+  "second default argument (argument present)"
+);
 
-const implicit = new Temporal.PlainDateTime(...args);
-assert.sameValue(implicit.second, 0, "second default argument");
+TemporalHelpers.assertPlainDateTime(
+  new Temporal.PlainDateTime(...args),
+  2000, 5, "M05", 2, 12, 34, 0, 0, 0, 0,
+  "second default argument (argument missing)"
+);