我可以检测我的 rspecs 中的元素(按钮)是否为 "clickable" 吗?
Can I detect if an element (button) is "clickable" in my rspecs?
上下文:在我的rspec(使用Ruby和水豚)
- 我点击 link 来测试我的应用程序中的一个操作:向我的应用程序添加一个分支。
- 模态 window 打开 ,我在其中 select 分支,然后单击 "submit" 按钮将分支添加到我的应用程序。单击 "submit" 后,模态 window 关闭。
- 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".
可能的解决方案:到目前为止我们已经尝试过的事情:
玩转我们的 "clicks configuration",确保我们在 "ready state" 上并且模态 window 消失了。我们失败了,因为我们一直遇到同样的错误。
执行一个"wait"。当模态 window 似乎存在时,我们添加了一个循环休眠
XYZ.add_new_branch_name(@branch_name)
while Utilities.element_visible?(:xpath, myElement)
sleep(0.5)
end
XYZ.save
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'
。
上下文:在我的rspec(使用Ruby和水豚)
- 我点击 link 来测试我的应用程序中的一个操作:向我的应用程序添加一个分支。
- 模态 window 打开 ,我在其中 select 分支,然后单击 "submit" 按钮将分支添加到我的应用程序。单击 "submit" 后,模态 window 关闭。
- 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".
可能的解决方案:到目前为止我们已经尝试过的事情:
玩转我们的 "clicks configuration",确保我们在 "ready state" 上并且模态 window 消失了。我们失败了,因为我们一直遇到同样的错误。
执行一个"wait"。当模态 window 似乎存在时,我们添加了一个循环休眠
XYZ.add_new_branch_name(@branch_name) while Utilities.element_visible?(:xpath, myElement) sleep(0.5) end XYZ.save
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'
。