Fix flaky specs: create_spec.rb[1:12:3:2:1] and switch_types_spec.rb[1:1:2]#23784
create_spec.rb[1:12:3:2:1] and switch_types_spec.rb[1:1:2]#23784Conversation
…step synchronisation
- switch_types_spec.rb[1:1:2]: Remove redundant type_field.openSelectField between
activate! and set_value. The set_value path (via select_autocomplete/search_autocomplete)
already opens the dropdown if closed, making openSelectField superfluous. The extra
click introduced a race condition while Angular was concurrently closing the required
CF and opening the type field.
- create_spec.rb[1:12:3:2:1]: Add explicit have_text('2 of') / have_text('3 of') waits
after each click_on 'Continue' in the before block. The Turbo Drive 422 re-renders fire
turbo:render (not turbo:load), so the previous implicit fill_in wait only guaranteed
the target field was visible but not that the entire step (including pre-populated
default values) had fully settled.
create_spec.rb[1:12:3:2:1] and switch_types_spec.rb[1:1:2]
|
cc @mrmir - not too bad 😏 |
| # Step 2: Fill in project details; wait to ensure Turbo has fully rendered step 2 | ||
| expect(page).to have_text("2 of") # rubocop:disable RSpec/ExpectInHook |
There was a problem hiding this comment.
This is definitely the right strategy for dealing with timing issues.. my only issue is the actual expectation. Can we not scope the text to a particular element or region..
| # Step 2: Fill in project details; wait to ensure Turbo has fully rendered step 2 | |
| expect(page).to have_text("2 of") # rubocop:disable RSpec/ExpectInHook | |
| expect(page).to have_role(:progressbar, text: "2 of") # rubocop:disable RSpec/ExpectInHook |
or (if using a <progress> element itself):
| # Step 2: Fill in project details; wait to ensure Turbo has fully rendered step 2 | |
| expect(page).to have_text("2 of") # rubocop:disable RSpec/ExpectInHook | |
| expect(page).to have_element(:progress, value: "2") # rubocop:disable RSpec/ExpectInHook | |
|
|
||
| # Now switch back to a type without the required CF | ||
| type_field.activate! | ||
| type_field.openSelectField |
There was a problem hiding this comment.
This will not fix the issue. The problem is a race condition in the production code where the schema is expected to be there, but sometimes isn't, on the required custom field.
There is an attempted fix in the form of a PR but I wanted to dig deeper if time permits to find out if the schema access can be safeguarded instead of attempting to address the issue on accessing the schema. But my proposal might already be good enough for now.
There was a problem hiding this comment.
Pull request overview
This PR reduces CI flakiness in two feature specs by removing a race-prone extra interaction in an Angular edit field flow and by adding explicit synchronization points between Turbo wizard steps in the project creation flow.
Changes:
- Remove a redundant
openSelectFieldcall when switching the work package type in the table spec to avoid competing async UI transitions. - Add explicit step-progress assertions after each “Continue” click in the project creation wizard to ensure the next Turbo-rendered step is fully committed before interacting with fields.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| spec/features/work_packages/table/switch_types_spec.rb | Removes a redundant select-opening call to avoid an Angular timing race during type switching. |
| spec/features/projects/create_spec.rb | Adds explicit wizard-step synchronization after Turbo transitions to stabilize subsequent field interactions. |
|
|
||
| # Step 2: Fill in project details | ||
| # Step 2: Fill in project details; wait to ensure Turbo has fully rendered step 2 | ||
| expect(page).to have_text("2 of") # rubocop:disable RSpec/ExpectInHook |
|
|
||
| # Step 3: Fill in required custom field | ||
| # Step 3: Fill in required custom field; wait to ensure Turbo has fully rendered step 3 | ||
| expect(page).to have_text("3 of") # rubocop:disable RSpec/ExpectInHook |
|
I've not be able to follow up on this, I'll close it. |
Ticket
What are you trying to accomplish?
Fix two flaky CI feature specs first seen on PR #23755. Both failures are timing/race conditions rooted in missing synchronisation after async UI transitions.
What approach did you choose and why?
switch_types_spec.rb[1:1:2]— remove redundantopenSelectFieldAfter
req_text_field.expect_active!, the required CF is in Angular edit mode.type_field.activate!fires one click that concurrently triggers Angular's click-outside close on the required CF and opens the type field's editor. The immediately-followingopenSelectFieldclicked.ng-input inputand calledwait_for_network_idlewhile Angular was still settling both transitions — landing the dropdown in an indeterminate state forset_value.Fix: remove
type_field.openSelectField.set_value→select_autocomplete→search_autocompletealready callsng_click_autocompleteronly when the dropdown is closed, so the extra call was both redundant and the source of the race.create_spec.rb[1:12:3:2:1]— add explicit Turbo step synchronisationThe
beforeblock navigates a 3-step Turbo Drive wizard. Eachclick_on "Continue"triggers a form POST the server answers with a 422 re-render; Turbo firesturbo:render, notturbo:load. The only previous synchronisation was the implicit Capybara element-level wait infill_in— enough to find the target field, but not enough to guarantee the full step (including thedefault_value: "Default value"pre-populated oncustom_field_with_default_value) had settled in the DOM. When "Complete" was submitted before the default was stable, creation failed validation andwait_for_turbotimed out.Fix: add
expect(page).to have_text("2 of")/have_text("3 of")waits after eachclick_on "Continue". The step-progress indicator is rendered by the wizard footer only after Turbo has fully committed the new step's HTML, making it a reliable full-step synchronisation point — the same pattern already used in the sibling test at lines 365–370.Merge checklist