将 JS 文件注入水豚 chrome headless

Inject JS file into capybara chrome headless

我的测试中有 RSpec 水豚和 Chrome 无头。对于某些页面,我加载了其他 javascript 所依赖的外部 JS 文件。

我想让我的测试独立于外部 JS 调用,例如当我离线时,它们将无法工作并抛出 JS 错误。更改生产代码(例如测试环境然后加载或不加载文件或执行脚本)感觉非常难看,所以这不是一个选项。

因此,我考虑在每次访问页面时将某种模拟脚本注入浏览器。问题是,page.evaluate_scriptpage.execute_script 之类的方法仅在加载页面时 运行 脚本。而此时,生产 JS 代码已经抛出错误。

我四处寻找解决方案,但没有找到 chrome 无头加载文件或在每次页面加载时执行脚本的选项。

我的设置目前是这样的

Capybara.register_driver :chrome_headless do |app|
  options = Selenium::WebDriver::Chrome::Options.new
  options.add_argument("no-sandbox")
  options.add_argument("headless")
  options.add_argument("disable-gpu")
  options.add_argument("window-size=1400,1400")

  capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
    acceptInsecureCerts: true
  )

  Capybara::Selenium::Driver.new(
    app, browser: :chrome, options: options, desired_capabilities: capabilities
  )
end
Capybara.javascript_driver = :chrome_headless

我还尝试构建一个扩展并将其与

一起使用
options.add_extension("spec/support/chrome_extension_test_helper/chrome_extension_test_helper.crx")

但似乎没有加载扩展(我在扩展中添加了一个 console.error("foobar") 但没有显示任何内容。所以可能不允许自签名扩展?此外,我想构建这样的扩展每次更改内容时都无需通过 chrome 打包。

那么,有没有办法将模拟 JS 文件加载到 chrome headless with capybara?=

Capybara 和 selenium 都不直接支持此功能,但是 Chrome 通过其 DevTools 协议 Page.addScriptToEvaluateOnNewDocument 命令支持。如果您是 运行 最新的 selenium-webdriver 和 chromedriver,则可以使用它,但不能保证永远有效,因为它涉及调用 selenium 驱动程序 bridge 上的私有方法

params = {
  cmd: 'Page.addScriptToEvaluateOnNewDocument',
  params: {
    source: '<The JS you want run before scripts on every page load>'
  }
}
page.driver.browser.send(:bridge).send_command(params)

我可以建议使用 webmock 之类的东西来存根对外部 js 的调用,而不是通过网络驱动程序注入模拟 js 脚本,return 以这种方式进行合理的模拟。这避免了需要使用Chrome的私有方法,以后可能会改变,也可以用来存根其他种类的外部资源。