Integration Testing with rspec and devise
So we are building a Rails app and we wanted to use rspec to do some integration testing (do some testing on the requests). We created our tests in the spec/requests/ folder like this:
# encoding: UTF-8
require 'spec_helper'
describe "Links:" do
it "should have the title 'Links'" do
visit "/links/"
page.should have_selector('h1', text: 'Links')
end
end
It worked great!
$> bundle exec rspec spec/requests/links_spec.rb --order random
...
Finished in 0.2016 seconds
1 example, 0 failures
Then we added devise and it stopped working. The website now requires you to log in in order to visit that page. The rspec tests aren't doing that, so it's redirecting to the log in page where it won't find the H1 title we expect.
We looked around the internet and found two blog posts ([1] and [2]) that set us on the right track, but didn't completely solved our problem, so we had to mix them! This is how we did it:
First, let's set up FactoryGirl to mock a user. We created a factory in spec/factories/user.rb:
ruby
FactoryGirl.define do
factory :user do
email "test@test2.com"
password "testtest"
password_confirmation "testtest"
end
end
Now we have to add helper to actually sign the user in. Following [2], we did this in spec/support/devisesupport.rb, but the `postvia_redirect` method for logging in didn't work for us, we had to use the method described in [1]:
# Module for authenticating users for request specs.
module ValidUserRequestHelper
# Signs in a valid user uwing the page.drive.post method
def sign_in_as_valid_user_driver
@user ||= FactoryGirl.create :user
page.driver.post user_session_path, :user => {:email => @user.email, :password => @user.password}
end
end
We have to configure spec/spec_helper.rb to use this helper.
RSpec.configure do |config|
[...]
config.include ValidUserRequestHelper, :type => :request
end
Now we can use the method sign_in_as_valid_user_driver
in our specs:
# encoding: UTF-8
require 'spec_helper'
describe "Links:" do
it "should have the title 'Links'" do
sign_in_as_valid_user_driver
visit "/links/"
page.should have_selector('h1', text: 'Links')
end
end
Of course there will be several tests, so we shouldn't be repeating the call in each one:
# encoding: UTF-8
require 'spec_helper'
describe "Links:" do
before do
sign_in_as_valid_user_driver
end
it "should have the title 'Links'" do
visit "/links/"
page.should have_selector('h1', text: 'Links')
end
end