From 74730a2d63dafdeb89bfa15258066e09754c1289 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Sat, 3 Apr 2021 01:22:15 +0200 Subject: [PATCH 1/2] MDL-71264 behat: New feature covering all day/month/year date changes Because of the order that dates and datetimes are filled by behat sometimes there are some intermediate results that are impossible and then the form (javascript) automatically reacts and fixes the date, ultimate leading to a different date that the one we wanted to set with Behat. This is noticeable when switching between months (with some day being the last day of the month) and the 2 months have a different number of days. For example April date => March date (or the opposite). This test covers all the critical changes (day, month and year), back and forth. All times are Perth/Australia. --- lib/tests/behat/datetime_any.feature | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 lib/tests/behat/datetime_any.feature 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 | | From b240173b665ae21403eb99d02ed342ebb72835e2 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Sat, 3 Apr 2021 10:33:57 +0200 Subject: [PATCH 2/2] MDL-71264 behat: Change date(time) element update order This includes 2 change to the order date(time) elements are filled, each one addressing one type of problem, where current order is problematic and can lead to unexpected dates. 1) Changing date, when current month only has X days and target month has more than X days. Example, being 1 April, change the date to 31 May. This is solved by changing the order of introduction from current D => M => Y to Y => M => D. 2) Changing date, when target month only has X days and current month has more that X days. Example, being 31 March, change the date to 28 Feb. This is solved by always setting the D to 1, before the Y => M => D sequence commented @ 1) begins. --- lib/behat/form_field/behat_form_date.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) 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), ]; }