Thomas Cannon

HTTPS, Subdomained System Tests in Ruby on Rails

Getting puma to use self-signed certificates in Test

Install the localhost gem, which allows Puma to use self-signed certificates in your test environment: https://github.com/puma/puma/#self-signed-ssl-certificates-via-the-localhost-gem-for-development-use

group(:test) do
  gem 'localhost'
end

It’s not documented anywhere in Capybara, but Capybara’s built-in Puma handler allows you to issue a custom bindhttps://github.com/teamcapybara/capybara/pull/2028

Capybara.run_server = true
Capybara.server = :puma, { Host: "ssl://#{Capybara.server_host}"}

I found that you do need to explicitly pass the Capybara.run_server = true argument in your system tests

You also need to have Selenium Webdriver explicitly accept insecure hosts: https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities/acceptInsecureCerts

For example:

Capybara.register_driver :chrome do |app|
  options = Selenium::WebDriver::Chrome::Options.new
  options.accept_insecure_certs = true
  Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end

With that, Capybara runs with self-signed certificates in development, and the WebDriver will accept them.

Running subdomained tests

Because of how macOS does not handle wildcard DNS resolution for localhost by default, if you need to run your tests using subdomains, you’ll need to use a loopback DNS service like nip.io
For example:

Capybara.app_host = "https://myapp.127.0.0.1.nip.io"

Depending on how your existing tests are setup, you might also need to setup a custom initializer block in config/environments/test.rb to override the tld_length

#config/environments/test.rb
Rails.application.configure do
  #...

config.hosts << “.127.0.0.1.nip.io”

if ENV[“PREP_SYSTEM_TESTS”].present? config.action_dispatch.tld_length = 5 # 127.0.0.1.nip.io = 5 top-level host details to throw out Rails.application.routes.default_url_options[:host] = “127.0.0.1.nip.io” # Necessary for routes to play nicely # … end end