From 5b70edf43ff68536e0eb50507c1606179faaf4ca Mon Sep 17 00:00:00 2001 From: Christophe Bliard Date: Fri, 17 Jan 2025 10:32:05 +0100 Subject: [PATCH] Fix flaky test The test is opening a dialog and setting text in an autocompleter. That triggers the dropdown of the autocompleter options. But as the dialog is still in its opening animation, the dropdown is not displayed at the right place: it is over the input. When the test then tries to click on that input, it fails because the dropdown is overlapping the input. That's the flakiness This commit adds a helper `wait_for_size_animation_completion(selector)` to wait for the animation of an element to finish. It's used to wait for the dialog animation to complete. Once the animation is finished, it is safe to set the text in the input. It triggers the display of the dropdown as before, but it is now displayed at the right place and the test can continue without failing. --- spec/support/capybara/wait_helpers.rb | 53 +++++++++++++++++++++++++++ spec/support/pages/page.rb | 2 + spec/support/pages/projects/show.rb | 2 +- 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 spec/support/capybara/wait_helpers.rb diff --git a/spec/support/capybara/wait_helpers.rb b/spec/support/capybara/wait_helpers.rb new file mode 100644 index 000000000000..1caa208911ba --- /dev/null +++ b/spec/support/capybara/wait_helpers.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +module WaitHelpers + # Wait for an element to stop being resized on the page + # + # Useful to wait for a primer dialog to finish opening, as they have an + # opening animation. + # + # @param selector [String] CSS selector for the element to wait for + # @param wait [Integer] Optional maximum time to wait in seconds, defaults to + # Capybara's default wait time + def wait_for_size_animation_completion(selector, wait: Capybara.default_max_wait_time) + element = page.find(selector, wait:) + page.document.synchronize do + initial_position = page.evaluate_script("arguments[0].getBoundingClientRect()", element) + sleep 0.1 # Small delay to allow for animation + final_position = page.evaluate_script("arguments[0].getBoundingClientRect()", element) + raise Capybara::ExpectationNotMet, "Animation not finished" unless initial_position == final_position + end + end +end + +RSpec.configure do |config| + config.include WaitHelpers, type: :feature +end diff --git a/spec/support/pages/page.rb b/spec/support/pages/page.rb index 433c15be55aa..36bc07829fc5 100644 --- a/spec/support/pages/page.rb +++ b/spec/support/pages/page.rb @@ -28,6 +28,7 @@ require_relative "../toasts/expectations" require_relative "../flash/expectations" +require_relative "../capybara/wait_helpers" module Pages class Page @@ -38,6 +39,7 @@ class Page include OpenProject::StaticRouting::UrlHelpers include Toasts::Expectations include Flash::Expectations + include WaitHelpers def current_page? URI.parse(current_url).path == path diff --git a/spec/support/pages/projects/show.rb b/spec/support/pages/projects/show.rb index 4877c69ab00e..b2d5a518b98e 100644 --- a/spec/support/pages/projects/show.rb +++ b/spec/support/pages/projects/show.rb @@ -82,7 +82,7 @@ def open_edit_dialog_for_section(section) end end - expect(page).to have_css("[data-test-selector='async-dialog-content']", wait: 5) + wait_for_size_animation_completion("[data-test-selector='async-dialog-content']") end def open_edit_dialog_for_life_cycles