Using url_for in Rails / Capybara / Poltergeist specification sends example.com driver instead of application

If I call url_for in the spec specification, it returns an absolute URL starting with http://www.example.com/ . Capybara will happily try to load pages on this site, but this has nothing to do with my application. The following are the minimum steps to reproduce the problem:

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" 

Do 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 deleted if you are 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 that the example.com page appears in the browser. I tested this behavior on Rails 3.2.17.

Why is this happening, and is there a way to get the URLs for the application under test instead of example.com?

Edit: some things I found in this in more detail:

ActionDispatch :: Routing :: UrlFor.url_for is called from RSpec examples. It has only_path default value is false.

ActionView :: RoutingUrlFor is the version that you enter, say, in the view. It has only_path default value is true, which works much better.

This commit in gspec-rails probably caused the problem by adding www.example.com as the default host. There is no explanation why this host is a suitable / useful choice.

+6
source share
2 answers

The problem appears for the following reasons:

  • You are using the 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 for which it should generate the URL. When used inside a Rails view or controller, Rails transfers the domain based on what was used to execute the request. When outside the view or controller, as in the ActionMailer or Capybara test, the domain is unknown. Capybara defaults to the unknown domain example.com.

So, everything works as it should. Now that’s not how you want it to work. However, if you want it to work as you would like, you need to do one of the following:

  • Use the path_only parameter in url_for to tell it not to use the host part.
  • Use the host parameter in url_for to specify the correct host.
+3
source

Here's how these gems work. http://example.com not related to your application. In general, you should not have completely hardcoded paths in your application. Rails tries to determine your local domain (for specifications, this is example.com , which is configured) and creates paths from this.

The idea here is that you have a base url that can change. Let's say for the production I use the local Heroku application: randomname-123-staging.heroku.com . My urls will be prefixed. However, in production I have a domain name. My URLs will start at mydomain.com . It makes no sense for me to update all my URLs based on the base domain of the environment; it should be (and accessible) Rails.

Using a common domain, which should ensure that it will not be allowed for real IP , the specifications will help you use this feature.

+1
source

All Articles