Testing a subdomain in Capybara
Pre requites:
- Rails 3.2
- Capybara.javascript_driver :webkit
- Rspec
Some basics about a Capybara request
Capybara by default uses the rack-test driver, which shows up in the request as "www.example.com" (port 80). When using a different driver, such as capybara-webkit, Capybara first spins up the rails server via "rails s -e test -p <capybara assigned port>", and then tests through http://127.0.0.1<capybara assigned port>. It is worth noting based on my experience that blank values come through for request.domain and request.subdomain on a capybara-webkit request.
Hitting a subdomain
Spec'ing a subdomain using the rack-test driver is straight-forward as you simply insert in the subdomain instead of the "www" e.g. http://billstools.example.com. When using the capybara-webkit driver it is not as simple as you can't add a subdomain to 127.0.0.1 and you don't know the capybara generated port number.
Modify the default_host or app_host?
With both drivers, rack-test and webkit, you are going to have to monkey with the request url. For the rack-test driver you can directly alter the Capybara.default_host option. For other drivers you need to modify the Capybara.app_host setting. However, let's stop here and say that this is not the "correct" approach. The main reason is that changing the default_host or app_host option will change this value globally for each spec that follows. The author of Capybara, Jonas Nicklas, states "Never change Capybara.default_host, just don't." and recommends that subdomains are visited explicitly.
Navigate through explicit urls
So the correct approach is to navigate using explicit urls for subdomain specs. That's easy for a rack-test spec as you create a prefix to the relative path, e.g. http://billstools.example.com/inventory/blue-hammer, but how about a capybara-webkit/js-driver spec? Since you cannot add a subdomain to 127.0.0.1 you either need to edit your /etc/hosts file adding a mapping for 127.0.0.1 such as *.local.me or use free services such as lvh.me or smackaho.st which provide wildcard matching back to your localhost. I prefer the latter as with the former all of the other developers are also going to have to make those edits to their /etc/hosts file.
Code example: Helper method for testing subdomains in Capybara
# spec/support/misc.helpers.rb def hosted_domain(options = {}) path = options[:path] || "/" # use root path by default subdomain = options[:subdomain] || 'billstools' if example.metadata[:js] # figures out which port Capybara spun up on the "rails s -e test" command # ** note: on Capybara 2.x you can use Capybara.always_use_port in the spec_helper port = Capybara.current_session.driver.server_port url = "http://#{subdomain}.lvh.me:#{port}#{path}" else url = "http://#{subdomain}.example.com" + path end end
require 'spec_helper' describe "Contact us form" do let (:account) { Factory.create(:account, :subdomain => 'billstools') } let!(:inventory) { Factory.create(:inventory, :account => account) } before do visit hosted_domain path: hosted_inventory_path(inventory) end it "shows the page" do page.should have_content('Contact Us') end it "shows the page", :js => true do page.should have_content('Contact Us') end end
- Pushed on 08/16/2012 by Christian