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.
The problem manifests for the following reasons:
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:
path_only
option in url_for to tell it not to use the host part.host
option in url_for to specify the correct host.This is how those gems work. The http://example.com
is irrelevant to your app. In general, you should not have fully hard-coded paths in your app. Rails attempts to determine your local domain (for specs this is example.com
, which is configurable) and creates paths off of that.
The idea here is that you have a base URL which may change. Say, for staging I use a Heroku local app: randomname-123-staging.heroku.com
. My urls will be prefixed with that. However, in production I own a domain name. My urls there will start with mydomain.com
. It makes no sense for me to have to update all of my URLs based on the environments base domain; this should be (and is) provided by Rails.
By using a generic domain, which is supposed to be guaranteed to not resolve to a real IP, the specs help you code to this possibility.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With