Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Express guide to a rails 3.2+ testing custom subdomains using cucumber capybara with pow setup... along with devise mailer config helper (only useful when needing to test custom subdomains in your rails app).

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.

First install pow.cx

  • 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

Now go to your cucumber's env.rb file add the following:

Capybara.server_port = 3030
Capybara.default_host = 'theappnametest.dev'
Capybara.app_host = 'http://www.theappnametest.dev'

Next modify the rails environment test.rb file by adding the following:

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"

Need it to work with devise mailers?

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) %>
@jacobsimeon

This comment has been minimized.

Copy link

@jacobsimeon jacobsimeon commented Mar 4, 2013

Nice work man. I didn't realize Pow could forward to different ports.

@thelucid

This comment has been minimized.

Copy link

@thelucid thelucid commented May 11, 2013

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.

@thelucid

This comment has been minimized.

Copy link

@thelucid thelucid commented May 11, 2013

Should Capybara be running a server? I had to manually start the Rails server using the test environment i.e. rails s -e test -p 3030 for this to work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment