rspec-rails: Default_url_options is being ignored
In my rspec_helper.rb I defined;
Rails.application.routes.default_url_options[:host] = 'lvh.me'
It works fine for non-feature specs but doesn’t work for feature specs. Host for urls are equal to “www.example.com” in feature specs.
I’ve debugged and in feature_example_group.rb file, default_url_options is always an empty hash.
found the following solution for this issue; https://github.com/beydogan/rspec-rails/commit/b590c82573b27bd8a1be967811b4835119260f09
Is this valid?
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Reactions: 18
- Comments: 36 (13 by maintainers)
Commits related to this issue
- (testing) hardcode unsubscribe to testing setting domains and protocols site wide was harder to tweak as first thought since Capybara’s feature tests do not respect the universal protocol setting of ... — committed to DFE-Digital/teaching-vacancies by tahb 5 years ago
- (testing) hardcode unsubscribe to testing setting domains and protocols site wide was harder to tweak as first thought since Capybara’s feature tests do not respect the universal protocol setting of ... — committed to DFE-Digital/teaching-vacancies by tahb 5 years ago
For future reference: I tried all sorts of variations (e.g
config.action_mailer.default_url_options = { host: 'www.example.com' }, Capybara’s host etc), nothing worked. I then addedRails.application.routes.default_url_options[:host] = 'www.example.com'after theend(end of file, outside the config block) inconfig/environments/tests.rband it worked.Regardless of the last comments. I think we can close this issue. Feel free to comment if we think we should still look at it.
I think this is just a Rails issue. There are many places to set
default_url_options, but they either work on console but not web, or the other way around:In Rails 5.1.4, I have tested the following scenarios on web and console (but not in Rspec):
For controller tests inside the
Rails.application.configureblock seemed to work for me:Any fixes for this problem ?
Ok, I dug into this a bit. It’s a little more complicated that it seems. Here’s what is going on.
The Rails test cases, the RSpec example groups are a thin shim on top of these, setup an attribute
default_url_options. If this is not set or defined, then the call chain falls back on whatever the currentroutesscope has configured. By default it has nothing configured for:hostand the value isnil.If we removed or comment out the line:
You would get the following error:
The reason your proposed solution in #1276 appears to work is simply because the example’s
default_url_optionsisniland so it falls back to therouteswhich you have customized in thespec/rails_helper.rb. For other spec types, which don’t have a:hostoption set by default, the route generation falls back to the session set by Rails’ test case. This depending on the spec type and is normally set to a default ofwww.example.comor pulled from a request, but is all handled by Rails’ test cases. This is not set for feature specs, because the session is handled by Capybara which does not set something for it.So unfortunately, your solution is basically a no-op and is the same as deleting that
ifblock. For the majority of cases, people don’t customize the host option and they would get the above exception.We could change it to:
However, this will cause other problems:
Results in a failure:
This is because Capybara uses
Capybara.default_hostto generate the “full” URL under the hood. The default host just happens to be “www.example.com”. However, it won’t actually use that web server. It just uses the value to generate the full URL while still using it’s local server. You have to configure Capybara to use an external app host.There’s another wrinkle. Capybara expects the “http://” part in the URL, if it’s not present the URL is created as: “http:///widgets”. I’m not sure this is a bug, you’d have to ask them. So while Rails is happy to have “lvh.me”, Capybara would need “http://lvh.me”.
We are tightly coupled to Capybara right now. As you can see from the feature example group file it’s essentially just all code necessary to handle Capybara’s design decisions. It also causes a lot of confusion for newer users who do not understand this tight dependency.
I really do not want to add yet another special case for Capybara. Let me think on this a bit. I have a potential solution in mind but will need to think on it for a day.
I hope this helps understand what’s happening.
If you set
config.action_controller.default_url_optionsinconfig/environments/test.rbto the correct value, you can reuse it in feature specs by settingself.default_url_options = ...in a before block as below:This fixes the issue originally described.
Same issue. Alternate resolution.
I noticed that a random feature test was failing inconsistently in both dev machine and CI environments. After reproducing with
rspec --seedand getting consistent failures tried many of the approaches here. Unfortunately, none of them quite worked for me. The route helpers would still resolve incorrectly. i.e.my_page_url = www.example.com/my_page.The interesting thing was that only the first feature test would fail. For all the subsequent feature tests in any feature testing file, the URL helpers would still resolve incorrectly, but the visit would be successful. In other words, visiting www.example.com/my_page would render my page correctly and run the necessary assertions as intended.
Simplest hack possible for me was just visiting one page before running the real tests:
Added this to the RSpec configure block in my rails helper and haven’t had any problems since.
ruby 2.3.4p301 rails 5.1.1 rspec 3.6.0 capybara 2.14.0
I’m testing subdomains and instead of _path helpers using _url in my controller. It’s only what I set.