Rather than test all of this in a functional test, I would use functional tests and Cucumber features in combination. You're wanting to test that when the user logs in, that they then can access various parts of the application. This is the Cucumber feature. Then you're wanting to test that when the user isn't logged in that they can't access these parts. That's the functional test.
I would write the Cucumber feature like this:
Feature: Viewing accounts
In order to update my account information
As a user
I want to access my profile page
Background:
Given a user exists:
| login | password |
| Radar | superpassword |
And I am logged in as them
Scenario: My profile page
When I follow "Account"
Then I should see "Profile Information"
I assume a couple of things here. Firstly your users login using a login and a password. You may have this as an email and password, but I'm sure you understand the gist.
The "I am logged in as them" step doesn't actually set up the session but rather actually goes through the process of logging in the user. I would write these two Background steps like this*:
Given /^a user exists:$/ do |table|
table.hashes.each do |user|
@user = User.create!(user)
end
end
Given /^I am logged in as them$/ do
steps(%Q{
Given I am on the homepage
And I follow "Login"
And I fill in "Login" with "#{@user.login}"
And I fill in "Password" with "#{@user.password}"
And I press "Login"
Then I should see "Login successful."
})
end
With these steps defined then the Scenario will run. I assume here that you have a link somewhere on the page where the login action redirects to that says "Account". When this link's clicked, I also assume that it goes to a page that says "Profile Information".
* It's a slightly contrived example. The "a user exists" step can take multiple rows.
Now for the functional test. I'm an RSpec sort of guy, so I'd write it as this.
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe AccountsController do
context "not logged in users" do
it "cannot access the profile action" do
get :profile
flash[:alert].should eql("You must be logged in to access that action.")
response.should redirect_to(login_path)
end
end
end
The before_filter
that checks that the user is logged in will be tested by this functional test. Because it's a private
method (it's a private
method, right?) it should not be tested directly. Here again I make a couple of assumptions like that when this before_filter
"fails" it sets a flash[:alert]
to some particular message and redirects to the login_path
.
So in summary: Test all the things the user can do by clicking around and filling in forms on the site using Cucumber, but for things such as going to protected actions or missing resources use a functional test / controller spec.