我可以检测我的 rspecs 中的元素(按钮)是否为 "clickable" 吗?

Can I detect if an element (button) is "clickable" in my rspecs?

上下文:在我的rspec(使用Ruby和水豚)

  1. 我点击 link 来测试我的应用程序中的一个操作:向我的应用程序添加一个分支。
  2. 模态 window 打开 ,我在其中 select 分支,然后单击 "submit" 按钮将分支添加到我的应用程序。单击 "submit" 后,模态 window 关闭。
  3. rspecs 通过在主屏幕中单击 "Save" 继续,以保存应用程序的状态(并有效地保存添加分支)。

问题:rspec 失败,因为(表面上)它试图单击主屏幕上的 "Save" 按钮,而模态 [=用于 select 的 90=] 分支仍然存在。测试没有报错找不到"Save"按钮组件,而是报错无法点击

日志中的错误是:

[...]Save</button> is not clickable at point (692, 23). Other element would receive the click[...]

A gotcha:这个 rspec 在某些环境下正确通过,比如当它 运行 反对我的本地服务器,但是当我们的自动化服务器执行时它失败了。因此,此测试已被标记为 "flaky".

可能的解决方案:到目前为止我们已经尝试过的事情:

while 条件检查模态 window 的 "submit" 按钮是否存在。 element_visible 函数使用

find(method,element).visible?

但是 我不确定 find 是否应该已经考虑到该按钮可能存在并且可见但不可点击

由于这仍然失败,尽管我们尽一切努力确保在我们尝试单击 "save" 按钮之前模式已经消失,我想问一下:

是否有正确的方法来检测模式 window 后面的元素是 可点击 还是不使用 rspec?

find只关心"visibility",不关心"clickability"(不同的driver对"visibility"的解释可能略有不同)。您看到的不稳定的原因很可能是机器的速度 运行 影响模态动画消失时间的测试。解决这个问题的最好方法是在测试模式下禁用动画(你如何做到这一点完全取决于你为动画使用的库and/or CSS)。另一种方法是按照您的操作进行 - 在单击 'Save' 按钮之前检查模式是否消失,但是您应该只使用 Capybara 提供的方法(包括 waiting/retrying 行为)而不是为此编写自己的循环。

 expect(page).not_to have_css('css selector of the modal') # RSpec version
 assert_no_css('css selector of the modal') # minitest version

从错误中查看鼠标位置后,您可能遇到的另一个潜在问题是屏幕尺寸和滚动。如果页面需要滚动才能到达 'Save' 按钮,并且 (692, 23) 会将按钮放在固定的 header 后面(您应该能够通过在按钮之前截取屏幕截图来验证这一点click attempt) 那么可能无法使用 driver 来点击按钮。在这种情况下,您需要使用 execute_script 将页面滚动到不同的位置,这样页面上的按钮就不会被覆盖 and/or 增加 "browser" 大小,这样就不需要滚动了在测试中。

我遇到了类似的问题并通过编写自己的 click_on_with_wait 辅助函数解决了它:

def click_on_with_wait(text, wait_time: Capybara.default_max_wait_time)
  success = false

  (wait_time * 10).round.times do
    click_on text
    success = true
    break
  rescue Selenium::WebDriver::Error::WebDriverError
    sleep(0.1)
  end

  # Try clicking one last time, so that the error will get raised if it still doesn't work
  click_on text unless success
end

这将尝试点击该元素。如果它仍然被模态隐藏,该函数将等待 100 毫秒,然后重试,直到达到给定的 wait_time

使用 Rails,我把它放在 system_spec_helpers.rb 中,这样我就可以简单地将 click_on 'Submit Form' 替换为 click_on_with_wait 'Submit Form'