84bbf8d fixed the flaky spec
`spec/features/projects/life_cycle/overview_page/dialog/update_spec.rb:266`.
It was flaky because it was testing if a date in the date picker is
disabled, but this date could be in the previous month and thus not
visible.
The implemented fix in 84bbf8d was to show the date before testing it
right in the `expect_xxx` methods.
The problem is that it breaks the query/command segregation principle.
Better move the calendar to the correct date before doing assertions on
the dates being visible, so the `expect_xxx` methods actually do also
check that the date is visible, which is desired in some test scenarios.
941096114c introduced `Components::Datepicker#displays_date?(date)` to
check if a date is visible in the date picker before doing some
assertions on it. Then 84bbf8d549 doubled down on it by calling it
inside each `#expect_non_working(date)`, `#expect_working(date)`,
`#expect_disabled(date)`, `#expect_not_disabled(date)` methods.
The problem is that `#displays_date?(date)` uses `has_css?` so it
returns immediately if the check is positive, but waits for 3 seconds
for the date to become visible if it's not yet. It's missing a `wait:
0`. And the css selector is wrong to: it searches for
`.flatpickr-day.flatpickr-disabled` instead of `.flatpickr-day`, so it
was returning false when the date was visible and enabled.
This commit fixes the problem by:
- Adding `wait: 0` to `has_css?`
- Changing the css selector to `.flatpickr-day`
- Add some `#expect_visible` calls to be sure the date picker is visible
before doing assertions with `wait: 0`
And same for `#has_previous_month_toggle?`: it missed a `wait: 0` for
the same reasons.
This makes for instance the 2 specs in
`spec/features/work_packages/datepicker/datepicker_follows_relation_spec.rb:84`
run in 11 seconds instead of 1 minute 27 seconds.
failing spec: ./spec/features/work_packages/details/date_editor_spec.rb:481
failing run: https://github.com/opf/openproject/actions/runs/18496811091/job/52702962599
When the working days only checkbox is toggled, the preview is triggered and updates the datepicker modal.
There was a race condition: if switching to automatic scheduling mode
before the preview finished, the preview would update the datepicker
modal and switching to automatic would be ignored (maybe it should not
be ignored). This was causing the spec to fail because the "working days
only" checkbox was not disabled.
Fix is to wait for the preview to finish before switching to automatic
scheduling mode.
Spec was ./spec/features/work_packages/scheduling/scheduling_mode_spec.rb:139
on job run https://github.com/opf/openproject/actions/runs/14519804438/job/40741624438
In `DateEditField#set_value`, the input fields of the date picker were
cleared and then the values were set. Problem is that when clearining
fields it does not wait for the preview to be applied: when the preview
comes back, it morphs the fields to set empty values but the
`#set_value` method has already started to fill the values, so the start
date field is overwritten with an empty value. Then the test fails
because the start date field is not the one expected.
The solution is to wait for the changes to be applied after clearing the
fields.
I wonder if that may be hiding a real bug where user could have their
input be reset while typing.
The setup was incorrect: the successor's dates were identical to the predecessor's dates which is not possible, and the milestone had start date different from due date which is not possible either.
Finally the second test was wrong too because when a successor milestone is
automatically scheduled, the date can't be changed and the date picker
is fully disabled.
https://community.openproject.org/wp/62362
When clicking the checkbox, it takes all form data and sends it to the
server for rerendering the form with the value updated.
Problem is: when the date form is not displayed and the "no
predecessors" message is displayed instead, there is no form data, so it
sends incomplete data to the server, and the server renders a minimalist
form.
The fix is to hide the checkbox too if the other form elements are hidden.
No checkbox, no click, no problem.
For new work packages, the generated URL was incorrect (`#show` instead
of `#new` action) and it then lead to a `ActiveRecord::RecordNotFound`
for id=`new`.
The test always works in headfull mode, but seems to be failing
sometimes in headless mode, like if capybara is not up to date with the
browser.
This is a workaround I'm not happy with.
https://community.openproject.org/wp/61894
In the backend, the date picker component assumes that the work package
is a milestone if the frontend did not send any `work_package[due_date]`
value for "Finish date" field.
Problem is, when in automatic scheduling mode, the "Finish date" field
is disabled, so it's not sent to the backend. The backend then
misleadingly thinks that it's a milestone being edited, and displays
only the "Date" field, as a milestone work package would do. The "Finish
date" and "Duration" fields disappear.
As the "Duration" field is always enabled, the fix is rely on it
(`work_package[duration]`) instead of the "Finish date" field.
Some scenarios have been described in https://community.openproject.org/wp/60670
Some of them are still not implemented. 5 of them are still failing:
- scenarios 13x
- scenario 22a
- scenario 23a
scenario 6a relies on the clear button being available, which is not the
case yet, so it's disabled.
If duration is negative or garbage, an error is displayed in the date
picker. It will not display any derivation-related errors for start and
due dates. For instance if start date is set, due date is not set, and
duration is invalid, then it won't display "can not be set to null as
start date and duration are known" error for due date.
Do not set expectations on the day being waited for. Could be disabled
or not, that's not this test purpose, that only to wait for a refresh.
And use default wait time. 20 seconds is way to much to wait.
After selecting a month, `#select_month` returns the index of the
selected month. It previously worked well only for single-month
datepickers. For a multiple months date picker, it was failing because
the selector is invalid (so it waited 5 seconds for nothing), then it
was retried, the current month was calculated, and that was the value
returned as the 2 conditions were not met. So in the end it was
returning the correct value, but it was also doing one useless retry.
This commit introduces `#current_month_index` to return the index of the
current month. This one works for both single and multi date pickers. It
is used by `#select_month` to calculate the number of months to move
forward or backward.
This should lead to some faster tests.
The `schedule_manually` column is also non-nullable now.
This includes the following changes:
- Automatically scheduled parent dates are and `ignore_non_working_days`
attributes are now always derived from children's values, even if the
children are scheduled manually.
It's more natural. Without that, adding a child to a work package
would not change the parent's dates.
As a consequence, the parent can start on a non-working day if one of
its children is manually scheduled, ignores non-working days, and
starts on a non-working day. That's why the parent's
`ignore_non_working_days` attribute is now also derived from all its
children regardless of the scheduling mode.
If the parent is manually scheduled, its dates and it's ability to
ignore non-working days will still be defined independently from its
children.
- Fix tests broken by scheduling mode being manual by default.
The tests had to be adapted to explicitly set scheduling mode to
automatic for followers and parents, and sometimes even follower's
children. Without it, work packages would not be rescheduled
automatically.
- Replace schedule helpers with table helpers.
Schedule helpers helped well, but table helpers are more flexible and
support more column types.
- Add "days counting" and "scheduling mode" columns to table helpers.
"days counting" to set `ignore_non_working_days` attribute.
- "all days" value maps to `ignore_non_working_days: true`.
- "working days" value maps to `ignore_non_working_days: false`.
"scheduling mode" to set `schedule_manually` attribute.
- "manual" value maps to `schedule_manually: true`.
- "automatic" value maps to `schedule_manually: false`.
Related to d94ea36eca. Use :enter instead of :right to trigger a
keyboard event to get the internal state of flatpickr updated. It seems
to work better.
The test wants to change a date using the datepicker from year 2025 to
year 2024. Using `fill_in` or `set` on the year input of the date picker
does not trigger any event which would update the internal state of the
flatpickr (it can be seen because the calendar dates is not redrawn). So
when the month is changed, the year switches back to 2025 (the internal
state), the wrong date is picked and the test fails.
This is fixed by sending a right arrow key to the year input to trigger
a keyboard event which then updates the internal state of the flatpickr.
This is a flickering test as the issue only occurs when the year needs
to be changed.
It was stupid to make an assertion on the selected day for the
datepicker in `#select_day` as the date picker is dismissed half of the
time, so the selected element is not there anymore to make assertions on
it.
Replaced with a direct assertion where it matters and reverted the
"safeguard".
The modal behavior being more reliable now, the `retry_block` is not
needed anymore. Also the `#select_day` method was similar in the parent
class. Better keep only the one from the parent class.