将 acceptInsecureCerts 与 Headless Chrome 和 Selenium Webdriver、macOS、Rails、Capybara 结合使用

Using acceptInsecureCerts with Headless Chrome and Selenium Webdriver, macOS, Rails, Capybara

问题

headless Chrome 是否可以通过 macOS 上的 Selenium Webdriver 使用自签名证书?

信息

我正在尝试通过 SSL 进行 Rails 由无头 Chrome 驱动的系统测试。

我有一个本地自签名证书,我将其传递给 ruby Puma 应用程序服务器以终止 SSL 请求。为了让驱动程序忽略本地签名证书上的 SSL 警告,我使用 acceptInsecureCerts 标志来配置驱动程序功能。 this ticket in Chromium 让我相信这个标志应该被识别为 Chrome 64+。

我可以通过 Chrome、Firefox 和无头 Firefox 获得成功的测试。在 headless Chrome 下测试不会通过。我正在使用(在撰写本文时)我认为是 Chrome 及其变体的最新版本。

虽然 Chromium ticket 中的人们似乎成功地 运行 无头 Chrome 通过使用 Selenium webdriver 的本地签名 SSL,我还没有发现这适用于描述的设置这里。如果我的配置是正确的,那么我不确定 macOS 上的 headless Chrome、Selenium webdriver ruby gem 或其他我没有考虑过的东西是否存在限制。如果有人在 macOS 上使用 Rails 进行类似的操作,我很想了解您的设置。

来源

这里有一些代码展示了我如何配置和 运行 我的 RSpec/Capybara 测试。

测试设置

# rails_helper.rb
# ... standard rspec rails helper setup omitted ...

Capybara.register_driver(:headless_chrome) do |app|
  options = Selenium::WebDriver::Chrome::Options.new(
    args: %w[--headless --disable-gpu --no-sandbox --disable-web-security]
  )
  capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
    acceptInsecureCerts: true,
  )
  Capybara::Selenium::Driver.new(
    app,
    browser: :chrome,
    options: options,
    desired_capabilities: capabilities
  )
end

RSpec.configure do |config|
  config.before(:each, type: :system) do
    driven_by :headless_firefox
  end
end

module SystemTestHelpers
  def key_file_path
    Rails.root.join("config", "ssl", "ssl-lvh.me.key")
  end

  def cert_file_path
    Rails.root.join("config", "ssl", "ssl-lvh.me.crt")
  end

  def using_app_host(host)
    original_host = Capybara.app_host
    Capybara.app_host = host

    Capybara.server = :puma, {
      Host: "ssl://#{Capybara.server_host}?key=#{key_file_path}&cert=#{cert_file_path}"
    }
    yield
  ensure
    Capybara.app_host = original_host
  end
end

RSpec.configure do |config|
  config.include SystemTestHelpers, type: :system
end

样本测试

# spec/system/welcome_spec.rb

require 'rails_helper'

RSpec.feature "Welcome", :js, type: :system do
  scenario "Visit homepage" do
    using_app_host('https://subdomain.lvh.me') do
      visit "/"

      expect(page).to have_content('Welcome')

      expect(page).to have_content('Your domain: subdomain.lvh.me')
      expect(page).to have_content('Your protocol: https://')
    end
  end
end

页面内容:

<div>
  <h2>Welcome!</h2>

  <p>Your protocol: <%= request.protocol %></p>
  <p>Your domain: <%= request.host %></p>
</div>

如果我换掉无头 Firefox 的驱动程序,配置如下,测试将通过。

Capybara.register_driver(:headless_firefox) do |app|
  options = Selenium::WebDriver::Firefox::Options.new(args: %w[--headless])

  capabilities = Selenium::WebDriver::Remote::Capabilities.firefox(
    acceptInsecureCerts: true,
  )
  Capybara::Selenium::Driver.new(
    app,
    browser: :firefox,
    options: options,
    desired_capabilities: capabilities
  )
end

重现问题并包含上述代码的应用程序的完整源代码位于此处:https://bitbucket.org/rossta/system-test-demo

调试输出

这是 link 来自 运行 无头 Chrome 或无头 Firefox 测试的一些调试输出:https://gist.github.com/rossta/b160204baa87a520e7888c19c8b1ed98.

请注意,在输出中,会话响应不包括 Chrome 的 'acceptInsecureCerts' 功能(test-headless-chrome.log,第 15 行),而在 Firefox 中我们确实看到了会话包括标志(test-headless-firefox.log,第 22 行)。

系统

从您的日志中可以看出它正在启动 chromedriver v2.34。 acceptInsecureCerts 直到 2.35 才添加支持,你应该是 运行 最新的(目前是 2.41)。更新您的 chromedriver 版本,一切正常。

caps = Selenium::WebDriver::Remote::Capabilities.firefox

大写['acceptInsecureCerts'] = 真