Testing subdomains with RSpec and Capybara

There's a lot of ugly solutions out there regarding this problem and rightfully so, it's a pain in the ass. I've gone through a good number of options and found the following to be the most simple. Warning: It only works on Mac OS X.

Configure Capybara

Capybara allows you to set the server port to run the test server on. This may or may not be necessary depending on your environment. It was necessary for me because Pow hijacks my default port.

spec_helper.rb

Capybara.server_port = 6543

Use the Subdomain

Mac OS X comes with a handy *.127localhost.com domain configured for you. So you can do contact.127localhost.com, test.127localhost.com, etc and it will all point to 127.0.0.1.

When you need to use your subdomain, simply use a url helper:

login_spec.rb

describe 'as a guest user on the mobile login page' do
  before do
    visit login_url(:subdomain => 'contact', :host => '127localhost.com', :port => 6543)
  end

  it 'shows me the login form' do
    page.should have_content('Login')
  end
end

Note: The :subdomain option isn't available by default. I stole it from Ryan Bate's Railscast and gisted it.

Other Options

Fenangling the /etc/hosts feels dirty and pollutes domain resolution.

Ultimately, it would be awesome to boot a Pow server for testing and use something like http://contact.myapp.test where the development app lives at http://contact.myapp.dev. It's possible to get Pow to boot at http://myapp.test by using the POW_DOMAINS environment variable. The issue here is the Pow server still runs in development. You can start the Pow server in an environment other than development by using .powenv. The issue here is managing the .powenv file so that it only exists during testing. Also, there would be additional boot time by restarting the Pow server.

I hope that in future versions of Pow, it's possible to configure the environment based on the top-level domain such as dev or test. That way, you can modify /etc/resolver/test to point to the port for which your test app lives during runtime. The resolver files are pretty simple and could be modified to look like the following:

/etc/resolver/test

# Lovingly generated by Pow
nameserver 127.0.0.1
port 6543

Until Pow provides the ability to run different environments, I'll stick to *.127localhost.com.

Happy testing!

Posted by Mike Pack on 09/16/2011 at 11:01AM

Tags: subdomains, capybara, testing, rspec, pow


"Incorrect" Timezone on Heroku

This is just a friendly reminder that Time.now on Heroku will give you server time, ie: PDT/PST, and not the local time for your app.

Since usually you want time calculations to be done with the correct zone for your app, just make sure to include 'zone' in your call for Time.now, like so:

Time.zone.now

I have the following in my config:

config/application.rb

config.time_zone = 'Mountain Time (US & Canada)'

Here's the difference for me in Heroku's console:

Time.now #=> 2011-08-20 18:53:06 -0700
Time.zone.now #=> Sat, 20 Aug 2011 19:53:08 MDT -06:00

So, remember, always use Time.zone.now instead of Time.now.

Happy time travel!

Posted by Mike Pack on 08/20/2011 at 07:56PM

Tags: heroku, time


Parsing Excel files on Heroku with roo

When it comes to processing Excel files in Ruby, your options are slim. A quick Google or Github search might reveal roo. roo is an interesting beast. It appears that the RubyGems.org gem file has been taken over and there's some large inconsistencies between the official gem and the Github codebase. The official gem is at version 1.9.5 as of this writing and the Github repo is still stuck at 1.3.11. Don't you hate when that happens?

This guide doesn't involve using the actual roo API, see the Github page or rubyforge page for that.

Getting roo to work on Heroku

Without tweaking, roo doesn't work on Heroku. It makes the (bad) assumption that the file system is writable. Check out this line of library to see where the temporary directory gets set. This line assigns a directory within the current working directory as the temporary file store.

On Heroku, that won't be possible. While the roo gem is packed in the dyno, it's directory is read only.

Directly after the linked line is another line that refers to the environment variable ROO_TMP. In version 1.2.0, ROO_TMP was added to alleviate issues where the current directory is inadequate to store temporary files.

To get roo to work on Heroku, create an initializer and set the environment variable to the Rails tmp directory (the only writable directory on Heroku):

config/initializers/roo.rb

ENV['ROO_TMP'] = "#{RAILS_ROOT}/tmp/"

Now, when your app is run either on Heroku or locally, roo will use the Rails tmp directory to store it's files.

Happy rooing!

Posted by Mike Pack on 08/02/2011 at 08:21PM

Tags: heroku, roo, excel