From 54351e1b8a9b070bfce6a478e9912a76f1545a54 Mon Sep 17 00:00:00 2001 From: Martin Brennan Date: Thu, 9 Mar 2023 01:49:20 +1000 Subject: [PATCH] DEV: Introduces a wait_for_animation system spec helper (#20573) This is used when calling click_message_action_mobile to wait for the message actions menu to finish animating up before attempting to click on it using capybara. Without this, in the time between capybara getting the x,y position of a menu item to click on and the click being fired, the animating menu can move that item out of the way. With the new helper, we constantly compare x,y client rect positions for the animating element and wait for them to stabilise. Once they do, it means the animation is done, and it is safe to click on anything within the element. Re-enables mobile system specs for chat that were ignored because of this. --- .../system/page_objects/chat/chat_channel.rb | 7 ++--- .../chat/spec/system/single_thread_spec.rb | 4 +-- plugins/chat/spec/system/transcript_spec.rb | 4 +-- spec/support/system_helpers.rb | 31 +++++++++++++++++++ 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/plugins/chat/spec/system/page_objects/chat/chat_channel.rb b/plugins/chat/spec/system/page_objects/chat/chat_channel.rb index 1f4ffbaed53..b0729fe3c3c 100644 --- a/plugins/chat/spec/system/page_objects/chat/chat_channel.rb +++ b/plugins/chat/spec/system/page_objects/chat/chat_channel.rb @@ -39,11 +39,8 @@ module PageObjects end def click_message_action_mobile(message, message_action) - i = 0.5 - try_until_success(timeout: 20) do - expand_message_actions_mobile(message, delay: i) - first(".chat-message-action-item[data-id=\"#{message_action}\"]") - end + expand_message_actions_mobile(message, delay: 0.5) + wait_for_animation(find(".chat-message-actions"), timeout: 5) find(".chat-message-action-item[data-id=\"#{message_action}\"] button").click end diff --git a/plugins/chat/spec/system/single_thread_spec.rb b/plugins/chat/spec/system/single_thread_spec.rb index 1408e32ed4e..52f1b2e5d39 100644 --- a/plugins/chat/spec/system/single_thread_spec.rb +++ b/plugins/chat/spec/system/single_thread_spec.rb @@ -69,8 +69,8 @@ describe "Single thread in side panel", type: :system, js: true do end context "when using mobile" do - xit "opens the side panel for a single thread from the mobile message actions menu", - mobile: true do + it "opens the side panel for a single thread from the mobile message actions menu", + mobile: true do chat_page.visit_channel(channel) channel_page.click_message_action_mobile(thread.chat_messages.last, "openThread") expect(side_panel).to have_open_thread(thread) diff --git a/plugins/chat/spec/system/transcript_spec.rb b/plugins/chat/spec/system/transcript_spec.rb index a89e35e2e16..4f6297b181d 100644 --- a/plugins/chat/spec/system/transcript_spec.rb +++ b/plugins/chat/spec/system/transcript_spec.rb @@ -205,8 +205,8 @@ RSpec.describe "Quoting chat message transcripts", type: :system, js: true do end context "when on mobile" do - xit "first navigates to the channel's category before opening the topic composer with the quote prefilled", - mobile: true do + it "first navigates to the channel's category before opening the topic composer with the quote prefilled", + mobile: true do chat_page.visit_channel(chat_channel_1) chat_channel_page.click_message_action_mobile(message_1, "selectMessage") diff --git a/spec/support/system_helpers.rb b/spec/support/system_helpers.rb index a9d472a729b..668c4d8d002 100644 --- a/spec/support/system_helpers.rb +++ b/spec/support/system_helpers.rb @@ -53,6 +53,37 @@ module SystemHelpers end end + # Waits for an element to stop animating up to timeout seconds, + # then raises a Capybara error if it does not stop. + # + # This is based on getBoundingClientRect, where Y is the distance + # from the top of the element to the top of the viewport, and X + # is the distance from the leftmost edge of the element to the + # left of the viewport. The viewpoint origin (0, 0) is at the + # top left of the page. + # + # Once X and Y stop changing based on the current vs previous position, + # then we know the animation has stopped and the element is stabilised, + # at which point we can click on it without fear of Capybara mis-clicking. + # + # c.f. https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect + def wait_for_animation(element, timeout: Capybara.default_max_wait_time) + old_element_x = nil + old_element_y = nil + + try_until_success(timeout: timeout) do + current_element_x = element.rect.x + current_element_y = element.rect.y + + stopped_moving = current_element_x == old_element_x && current_element_y == old_element_y + + old_element_x = current_element_x + old_element_y = current_element_y + + raise Capybara::ExpectationNotMet if !stopped_moving + end + end + def resize_window(width: nil, height: nil) original_size = page.driver.browser.manage.window.size page.driver.browser.manage.window.resize_to(