diff --git a/lib/behat/form_field/behat_form_date.php b/lib/behat/form_field/behat_form_date.php index 010b5aaffc8..030d8525992 100644 --- a/lib/behat/form_field/behat_form_date.php +++ b/lib/behat/form_field/behat_form_date.php @@ -56,6 +56,14 @@ class behat_form_date extends behat_form_group { // Disable the given date selector field. $this->set_child_field_value('enabled', false); } else if (is_numeric($value)) { // The value is numeric (unix timestamp). + // First, reset the day always to an existing one (1st). Without that + // undesired modifications (JS) happens when changing of month and day if + // the interim combination doesn't exists (for example, 31 March => 01 April). + // Note that instead of always setting the day to 1, this could be a little more + // clever, for example only changing when the day > 28, or only when the + // months (current or changed) have less days that the other. But that would + // require more complex calculations than the simpler line below. + $this->set_child_field_value('day', 1); // Assign the mapped values to each form element in the date selector field. foreach ($this->get_mapped_fields($value) as $childname => $childvalue) { $this->set_child_field_value($childname, $childvalue); @@ -74,11 +82,18 @@ class behat_form_date extends behat_form_group { * @return array */ protected function get_mapped_fields(int $timestamp): array { + // Order is important, first enable, and then year -> month -> day + // (other order can lead to some transitions not working as expected, + // for example, changing from 15 June to 31 August, Behat ends with + // date being 1 August if the modification order is day, then month). + // Note that the behaviour described above is 100% reproducible + // manually, with the form (JS) auto-fixing things in the middle and + // leading to undesired final dates. return [ 'enabled' => true, - 'day' => date('j', $timestamp), - 'month' => date('n', $timestamp), 'year' => date('Y', $timestamp), + 'month' => date('n', $timestamp), + 'day' => date('j', $timestamp), ]; } diff --git a/lib/tests/behat/datetime_any.feature b/lib/tests/behat/datetime_any.feature new file mode 100644 index 00000000000..cb18187d13b --- /dev/null +++ b/lib/tests/behat/datetime_any.feature @@ -0,0 +1,33 @@ +@core @javascript @core_form +Feature: Any day / month / year combination in date form elements works ok. + In order to use date / datetime elements with Behat + as a user + Any day / month / year combination must work ok + + @javascript + Scenario Outline: Verify that setting any date / datetime is possible + Given the following "courses" exist: + | fullname | shortname | format | + | Course 1 | C1 | topics | + And the following "activity" exist: + | activity | name | intro | course | idnumber | + | assign | Assignment 01 | Assign activity to test some dates | C1 | assign01 | + Given I am on the "C1" "Course" page logged in as "admin" + And I follow "Assignment 01" + And I navigate to "Edit settings" in current page administration + And I expand all fieldsets + And I set the field "Due date" to "" + And I set the field "Due date" to "" + When I press "Save and display" + Then I should see "" in the "Due date" "table_row" + + Examples: + | initial_date | final_date | date_result | case_explanation (times Australia/Perth) | + | ##now## | ##tomorrow## | ##tomorrow##%A, %d %B %Y, %I:%M## | change of day, any day, back and forth | + | ##tomorrow## | ##now## | ##now##%A, %d %B %Y, %I:%M## | | + | 1617256800 | 1617170400 | Wednesday, 31 March 2021, 2:00 | change of month, back and forth | + | 1617170400 | 1617256800 | Thursday, 1 April 2021, 2:00 | | + | 1740808800 | 1709186400 | Thursday, 29 February 2024, 2:00 | change of month, leap year, back and forth | + | 1709186400 | 1740808800 | Saturday, 1 March 2025, 2:00 | | + | 1577858400 | 1577772000 | Tuesday, 31 December 2019, 2:00 | change of year, back and forth | + | 1577772000 | 1577858400 | Wednesday, 1 January 2020, 2:00 | |