Merge pull request #22617 from opf/more-flaky

Apply more flaky fixes
This commit is contained in:
Klaus Zanders
2026-04-01 11:27:09 +02:00
committed by GitHub
4 changed files with 58 additions and 31 deletions
@@ -1,3 +1,5 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
@@ -119,16 +121,18 @@ RSpec.describe "Arbitrary WorkPackage query table widget on my page",
columns.assume_opened
columns.remove "Subject"
expect(filter_area.area)
.to have_css(".id", text: type_work_package.id)
retry_block do
expect(filter_area.area)
.to have_css(".id", text: type_work_package.id)
# as the Subject column is disabled
expect(filter_area.area)
.to have_no_css(".subject", text: type_work_package.subject)
# as the Subject column is disabled
expect(filter_area.area)
.to have_no_css(".subject", text: type_work_package.subject)
# As other_type is filtered out
expect(filter_area.area)
.to have_no_css(".id", text: other_type_work_package.id)
# As other_type is filtered out
expect(filter_area.area)
.to have_no_css(".id", text: other_type_work_package.id)
end
# Wait for the column save PATCH to complete after the DOM has confirmed the
# Angular state update. Without this ordering, wait_for_network_idle can fire
@@ -142,7 +146,9 @@ RSpec.describe "Arbitrary WorkPackage query table widget on my page",
input.native.send_keys(:return)
end
my_page.expect_and_dismiss_toaster message: I18n.t("js.notice_successful_update")
retry_block do
my_page.expect_and_dismiss_toaster message: I18n.t("js.notice_successful_update")
end
wait_for_network_idle
@@ -155,25 +161,27 @@ RSpec.describe "Arbitrary WorkPackage query table widget on my page",
filter_area = Components::Grids::GridArea.new(".grid--area.-widgeted:nth-of-type(3)")
# Wait for the widget to load from its persisted state before asserting.
# The title comes from the grid API; once visible, the widget is initialized.
# A second wait_for_network_idle then catches the subsequent query + results fetches.
within filter_area.area do
expect(page).to have_field("editable-toolbar-title", with: "My WP Filter", wait: 10)
retry_block do
# Wait for the widget to load from its persisted state before asserting.
# The title comes from the grid API; once visible, the widget is initialized.
# A second wait_for_network_idle then catches the subsequent query + results fetches.
within filter_area.area do
expect(page).to have_field("editable-toolbar-title", with: "My WP Filter", wait: 10)
end
wait_for_network_idle
expect(filter_area.area)
.to have_css(".id", text: type_work_package.id)
# as the Subject column is disabled
expect(filter_area.area)
.to have_no_css(".subject", text: type_work_package.subject)
# As other_type is filtered out
expect(filter_area.area)
.to have_no_css(".id", text: other_type_work_package.id)
end
wait_for_network_idle
expect(filter_area.area)
.to have_css(".id", text: type_work_package.id)
# as the Subject column is disabled
expect(filter_area.area)
.to have_no_css(".subject", text: type_work_package.subject)
# As other_type is filtered out
expect(filter_area.area)
.to have_no_css(".id", text: other_type_work_package.id)
end
end
@@ -79,6 +79,7 @@ RSpec.describe "Project description widget", :js do
# Activate the field for editing
wait_for_turbo_stream { description_field.open_field }
wait_for_ckeditor
# Set a new description
new_description = "This is a **test** project description with markdown formatting."
+4 -4
View File
@@ -939,7 +939,7 @@ RSpec.describe "Projects list filters", :js, with_settings: { login_required?: f
projects_page.expect_projects_not_listed(development_project, project)
projects_page.expect_projects_in_order(public_project)
projects_page.remove_filter("project_finish_gate_#{gate.definition_id}")
wait_for_turbo_stream { projects_page.remove_filter("project_finish_gate_#{gate.definition_id}") }
projects_page.expect_projects_in_order(development_project, project, public_project)
@@ -950,7 +950,7 @@ RSpec.describe "Projects list filters", :js, with_settings: { login_required?: f
projects_page.expect_projects_not_listed(development_project, project)
projects_page.expect_projects_in_order(public_project)
projects_page.remove_filter("project_finish_gate_#{gate.definition_id}")
wait_for_turbo_stream { projects_page.remove_filter("project_finish_gate_#{gate.definition_id}") }
projects_page.expect_projects_in_order(development_project, project, public_project)
@@ -962,7 +962,7 @@ RSpec.describe "Projects list filters", :js, with_settings: { login_required?: f
projects_page.expect_projects_not_listed(development_project, project)
projects_page.expect_projects_in_order(public_project)
projects_page.remove_filter("project_finish_gate_#{gate.definition_id}")
wait_for_turbo_stream { projects_page.remove_filter("project_finish_gate_#{gate.definition_id}") }
projects_page.expect_projects_in_order(development_project, project, public_project)
@@ -973,7 +973,7 @@ RSpec.describe "Projects list filters", :js, with_settings: { login_required?: f
projects_page.expect_projects_not_listed(development_project, project)
projects_page.expect_projects_in_order(public_project)
projects_page.remove_filter("project_finish_gate_#{gate.definition_id}")
wait_for_turbo_stream { projects_page.remove_filter("project_finish_gate_#{gate.definition_id}") }
projects_page.expect_projects_in_order(development_project, project, public_project)
+18
View File
@@ -191,6 +191,24 @@ def wait_for_turbo_frame(timeout: 10, &block)
raise result["error"] if result.is_a?(Hash) && !result["success"]
end
# Waits for CKEditor to be fully initialized.
#
# CKEditor is an Angular component (`opce-ckeditor-augmented-textarea`)
# that initializes asynchronously after its container is inserted into the DOM
# (e.g. via a Turbo Stream). The `.ck-content` element only appears once the
# editor instance is fully created, so waiting for it is a reliable readiness signal.
#
# Uses a generous timeout because Angular bootstrap + CKEditor init can be slow on CI.
#
# @example
# wait_for_turbo_stream { description_field.open_field }
# wait_for_ckeditor
# wait_for_turbo_stream { description_field.fill_and_submit_value(...) }
#
def wait_for_ckeditor(timeout: 20)
expect(page).to have_css(".ck-content", wait: timeout)
end
def using_cuprite?
Capybara.javascript_driver == :better_cuprite_en
end