Using url_for in Rails/Capybara/Poltergeist spec sends the driver to example.com instead of the app

capybara, poltergeist, rspec, ruby, ruby-on-rails

Solution

The problem manifests for the following reasons:

- You are using Poltergeist, which uses PhantomJS, which is perfectly capable of opening any URL.

- You are using the url_for helper which needs to know the domain it should be generating a url for. When used inside a Rails view or controller, Rails supplies the domain based on what was used to make the request. When outside of a view or a controller, like in an ActionMailer or Capybara test, the domain is unknown. Capybara defaults the unknown domain to example.com.

So everything is working the way it should. Now, it happens to not be the way that you want it to work. However, if you want it to work how you would like you should do one of the following things:

- Use the `path_only` option in url_for to tell it not to use the host part.

- Use the `host` option in url_for to specify the correct host.

Problem

If I call `url_for` within a feature spec, it returns an absolute URL starting with http://www.example.com/. Capybara will happily attempt to load pages on that site, but that has nothing to do with my app. Here are minimal steps to reproduce the issue: Start with this Gemfile: ``` source 'https://rubygems.org' gem "sqlite3" gem "jquery-rails" gem "draper" gem "rails", '4.1.0' gem "therubyracer" gem "uglifier" gem "rspec-rails" gem "capybara" gem "poltergeist" gem "launchy" ``` Run the following: ``` bundle rails new myapp -O cd myapp rm Gemfile Gemfile.lock rails generate controller Test test rails generate rspec:install mkdir spec/features ``` Comment out the lines in `spec/spec_helper.rb` that say they should be removed when not using ActiveRecord, and then create `spec/features/feature_spec.rb` with the following contents: ``` require 'capybara/poltergeist' Capybara.configure do |config| config.javascript_driver = :poltergeist end require 'spec_helper' describe "nothing", js: true do specify do visit(url_for(controller: :test, action: :test)) save_and_open_page end end ``` Finally, run `rake spec` and you will see the example.com page pop up in a browser. I have verified this behavior back to Rails 3.2.17. Why is this happening, and is there a way to get URLs for the app being tested instead of example.com? Edit: some things I have found looking into this more: ActionDispatch::Routing::UrlFor.url_for is called from RSpec examples. It has `only_path` defaulting to false. ActionView::RoutingUrlFor is the version you get in, say, a view. It has `only_path` defaulting to true, which works much better. This commit to the rspec-rails gem probably caused the problem, by adding `www.example.com` as the default host. There is no explanation anywhere about why this host is an appropriate/useful choice.

Original source