Express guide to a rails 3.2+ testing custom app subdomains using cucumber capybara with a pow setup... along with devise mailer config helper example (useful if you need to test various auth situations for custom subdomains in a rails app).
If you haven't used pow, I wouldn't recommend it for local web dev... there's much better gems for local web dev like unicorn-rails or passenger nginx standalone are far better choices IMHO. I use pow for all the local name redirects to a port like explained below, with a rails dev server listening on that port running unicorn-rails.
So we're going to use it for the awesome subdomain redirect to a local customapp.dev on a specific port magic mojo.
- now go to pow.cx and install
- cd ~/.pow
- echo 3000 > theappname && echo 3030 > theappnametest
- now pow will redirect all requests to theappname.dev to port 3000
- and now pow will redirect all requests to theappnametest.dev to port 3030
- we've created two ports to be able to work in the development env and execute cukes in the test env at the same time
Capybara.server_port = 3030
Capybara.default_host = 'theappnametest.dev'
Capybara.app_host = 'http://www.theappnametest.dev'
config.action_mailer.default_url_options = { :host => 'theappnametest.dev' }
So with the above done you can switch around subdomains all you like in your cucumber features and steps by calling:
Capybara.app_host = "http://#{@user.subdomain}.theappnametest.dev"
Create a url_heleper.rb file like:
module UrlHelper
## subdomain helpers ##
def with_subdomain(subdomain)
subdomain = (subdomain || "")
subdomain += "." unless subdomain.empty?
[subdomain, request.host, request.port_string].join
end
def url_for(options = nil)
if options.kind_of?(Hash) && options.has_key?(:subdomain)
options[:host] = with_subdomain(options.delete(:subdomain))
end
super
end
## sets the subdomain in the mailer based off of the current request ##
def set_mailer_url_options
ActionMailer::Base.default_url_options[:host] = with_subdomain(request.subdomain)
end
## for building links at runtime
def build_url_or_path_for(url_or_path = '')
url_or_path = eval(url_or_path) if url_or_path =~ /_path|_url|@/
url_or_path
end
end
Next Add this to your application.rb:
config.to_prepare do
Devise::Mailer.class_eval do
helper :url
end
end
All the devise mailer links can now take the subdomain param so they build correctly:
confirmation_url(@resource, confirmation_token: @resource.confirmation_token, subdomain: @resource.account.subdomain) %>
Great Scott! That's awesome, I've been trying to test external requests to an app so this is spot on, thanks.
p.s. please excuse the Back to the Future pun, I couldn't resist.