ruby-on-railsrspeccapybaracuprite

Why is Capybara not sending the server's port to the browser on visit i.e root_path?


In ruby 2.6.1, rails 6.0 I am trying to get Capybara to start a test server and have the option to show or not the cases on chrome using capybara 3.35.3 and cuprite 0.13, by setting a headless option on or off.

My findings and issues:

Ideally Not define Capybara.server_host or Capybara.server_port and instead use Capybara.always_include_port = true which according to Capybara's documentation, is meant to always send or rather append the port to the server host address for whenever visit is used in a test case, the url in the browser would be http://127.0.0.1:xxxx/. The problem with this approach is that Capybara.always_include_port is not doing that, instead after the server is run, the browser goes to http://127.0.0.1/

If I set Capybara.server_port, the browser still ends up with no port upon bundle exec rspec, regardless to the state of Capybara.always_include_port.

for reference, the reason I use CAPYBARA_APP_HOST with host! before each case and not use a general Capybara.app_host is because Rails automatically changes the value of the latter to 127.0.0.1, so this is more of a work around acquired from evilmartians.

The commented lines of code are to showcase my points mentioned.

worth noting that the only way currently the environment would work is if I set Capybara.run_server = false , and uncomment the server_host, server_port, CAPYBARA_APP_HOST and host! lines, and start a seperate rails server using rails s then run the specs, which is less than ideal.

Any pointers? Thank you

my rails_helper.rb:

require 'spec_helper'

ENV['RAILS_ENV'] ||= 'test'

require File.expand_path('../config/environment', __dir__)

abort("The Rails environment is running in production mode!") if Rails.env.production?

require 'rspec/rails'
require 'capybara/rails'
require "capybara/cuprite"

Dir[File.join(__dir__, "system/support/**/*.rb")].sort.each { |file| require file }

Capybara.default_driver = Capybara.javascript_driver  = Capybara.current_driver = :cuprite
Capybara.default_max_wait_time = 5
Capybara.default_normalize_ws = true

Capybara.server = :puma
Capybara.always_include_port = true
# Capybara.server_host = '0.0.0.0'
# Capybara.server_port = 3030
# CAPYBARA_APP_HOST = "http://#{Capybara.server_host}:#{Capybara.server_port}".freeze

Capybara.register_driver(:cuprite) do |app|
  Capybara::Cuprite::Driver.new(
    app,
    **{
      window_size: [1200, 800],
      browser_options: {},
      process_timeout: 10,
      inspector: true,
      headless: !ENV["HEADLESS"].in?(%w[n 0 no false])
    }
  )
end

begin
  ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
  puts e.to_s.strip
  exit 1
end

RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/factories"
  config.use_transactional_fixtures = true
  config.infer_spec_type_from_file_location!
  config.filter_rails_from_backtrace!

  config.prepend_before(:each, type: :system) do
    # host! CAPYBARA_APP_HOST
    # Use JS driver always
    driven_by Capybara.javascript_driver
  end
end

Solution

  • so I decided to debug lib/capybara/session.rb and noticed that always_include_port is actually working as it should be, and the outcome is indeed to initiate a driver with a full uri; a url + port.

    The problem was a warning that I have been ignoring when running specs about having force_ssl if: :ssl_configured? within the application controller. I hashed out that line and all is working as expected.

    Lesson: do not ignore runtime warnings.