Cyril Duchon-Doris
Cyril Duchon-Doris

Reputation: 13949

Rails correctly configure host/port with Cucumber/Capybara on CircleCI

I have problems figuring out the good way to set up the host/port for test on CircleCI

EDIT 2 - Requirements :

Previously my test suite was running fine with localhost:3042 but then I realized I had problems with tests that used session : the rails app itself started on localhost but then emails were sent to the 127.0.0.1 address which caused session-based tests to fail

I changed the following config

# feature/env.rb
Capybara.server_port = ENV['TEST_PORT'] || 3042
Rails.application.routes.default_url_options[:port] = Capybara.server_port
if ENV['CIRCLECI']
  Capybara.default_host = 'http://www.example.com/'
end

# configuration/test.rb
config.action_mailer.default_url_options = {
    host: (ENV['CIRCLECI'].present? ? 'www.example.com' : '127.0.0.1'),
    port: ENV['TEST_PORT'] || 3042
  }

# circle.yml    
machine:
  hosts:
    www.example.com: 127.0.0.1

But now I'm getting weird email urls being generated like http://www.example.com/:3042/xxx

Did someone manage a working configuration on circleCI using custom host name ?

EDIT

Capybara 2.13 Rails 5.0 Cucumber 2.4 CircleCI 1.x

Upvotes: 1

Views: 2084

Answers (2)

Cyril Duchon-Doris
Cyril Duchon-Doris

Reputation: 13949

My new config which seems to work for session-based tests but fails for remote websites (it tries to reach the remote server with the same TEST_PORT I have defined (eg click on email with http://www.example-remote.com/some_path --> Capybara connects to http://www.example-remote.com:TEST_PORT/some_path)

# features/env.rb
# If test port specified, use it
if ENV['TEST_PORT'].present?
  Capybara.server_port = ENV['TEST_PORT']
elsif ActionMailer::Base.default_url_options[:port].try do |port|
  Capybara.server_port = port
end
else
  Rails.logger.warn 'Capybara server port could not be inferred'
end

# Note that Capybara needs either an IP or a URL with http://
# Most TEST_HOST env variable will only include domain name
def set_capybara_host
  host = [
    ENV['TEST_HOST'],
    ActionMailer::Base.default_url_options[:host]
  ].detect(&:present?)
  if host.present?
    # If the host is an IP, Capybara.app_host = IP will crash so do nothing
    return if host =~ /^[\d\.]+/ 
    # If hostname starts with http(s)
    if host =~ %r(^(?:https?\:\/\/)|(?:\d+))
      # OK
    elsif Capybara.server_port == 443
      host = 'https://' + host
    else
      host = 'http://' + host
    end
    puts "Attempting to set Capybara host to #{host}"
    Capybara.app_host = host
  else
    Rails.logger.warn 'Capybara server host could not be inferred'
  end
end
set_capybara_host

# config/environments/test.rb
Capybara.always_include_port = true

config.action_mailer.default_url_options = {
    host: (ENV['TEST_HOST'].present? ? ENV['TEST_HOST'] : '127.0.0.1'),
    port: (ENV['TEST_PORT'].present? ? ENV['TEST_PORT'] : 3042)
  }

Upvotes: 0

Thomas Walpole
Thomas Walpole

Reputation: 49880

Capybara.default_host only affects tests using the rack_test driver (and only if Capybara.app_host isn't set). It shouldn't have the trailing '/' on it, and it already defaults to 'http://www.example.com' so your setting of it should be unnecessary.

If what you're trying to do is make all your tests (JS and non-JS) go to 'http://www.example.com' by default then you should be able to do either

Capybara.server_host = 'www.example.com'

or

Capybara.app_host = 'http://www.example.com'
Capybara.always_include_port = true

Upvotes: 3

Related Questions