我正在尝试在 Rails 6.1 应用程序的几个页面上引入 Turbo Drive。
将一些旧版 JQuery 插件初始化从$(document).ready()
调用移至
document.addEventListener('turbo:load', ..)
调用后,Ḯ已按预期获得了结果。
但是,当我运行 Capybara 功能规范时,我可以从失败规范的屏幕截图中看到,例如 JQuery 插件尚未按应有的方式初始化。失败测试的一个典型示例:
scenario 'element is visible', :js do
visit(my_page_path)
expect(page.find(#some-jquery-plugin-created-element).text).to \
eq 'some expected text from the plugin element'
end
任何人都可以帮助我理解为什么这在功能规范中不起作用?在我看来,
turbo:load
事件根本没有被触发。
我在驱动程序中启用登录:
Selenium::WebDriver::Remote::Capabilities.chrome( "goog:loggingPrefs": { browser: 'ALL' } ).
.. 但在失败的
page.driver.browser.manage.logs.get(:browser)
调用之前调用 expect
只会返回一个空数组。
也许我做错了?
Capybara.default_max_wait_time = 10
写下您的期望,例如
expect(page.find(#some-jquery-plugin-created-element).text).to \
eq 'some expected text from the plugin element'
您正在击败 Capybaras 重试功能,这将导致动态页面中的大量测试失败。您不应该“永远”将基本的 RSpec 匹配器(eq 等)与 Capybara 相关对象一起使用。
在您的情况下,
find
调用正在等待匹配元素存在,然后获取其文本并检查它。这将会失败,因为当元素首次添加到页面时,它可能还没有完整的文本内容。相反,您应该使用 Capybara 提供的匹配器,它将使用 Capybara 等待行为来匹配事物
expect(page.find(#some-jquery-plugin-created-element)).to have_text('some expected text from the plugin element')
根据我的经验:水豚在页面加载后从
visit()
返回,但不一定是在所有脚本运行后。在触发/处理“turbo:load”事件之前,您的测试将立即继续。您可以通过将 sleep()
放入测试中来验证是否是这种情况 - 这将以粗略的方式解决您的问题:
scenario 'element is visible', :js do
visit(my_page_path)
sleep 10
expect(page.find(#some-jquery-plugin-created-element).text).to \
eq 'some expected text from the plugin element'
end
我的理解是,这就是浏览器的实际工作方式:在显示内容之后、在加载时执行所有脚本之前有一个间隙。对于用户体验而言,这不是问题,因为间隙很短,用户不太可能在短时间内与页面进行交互。测试时情况有所不同,因为它们比人类快得多。
为了使测试工作没有不必要的延迟,您需要确保仅在执行所需的脚本后才继续测试。一种方法是:
举个例子,我确实隐藏了整个 HTML 元素:
<html style="visibility: hidden;">
然后只有在 Turbo 加载后才显示:
function showPage(event) {
document.documentElement.style.visibility="visible";
}
document.addEventListener('turbo:load', showPage);
并且在每次页面加载后,使用具有等待能力的方法,以确保只有在页面完全加载后测试才会继续。