Where should I test authorization with RSpec?
When you create a Rails application with RSpec, there are three folders that seems to be adequate:
In which one should I test if the user is logged in? Should I test in more than one spec type?
There is a subtle distinction to your question. Authorization
usually referrers to permissions that users have within the app. Authentication
referrers to users signing up and logging in users.
As far as Authentication
goes, I usually prefer to use integration/requests
specs or acceptance/feature specs
. Feature specs are preferred lately because the Capybara DSL (page
and visit
) are only available in feature specs. They used to be allowed in request specs until the 2.x upgrade.
I will test things like signing up, signing in and signing out. For example,
# signing_up_spec.rb
feature 'Signing up' do
scenario 'Successful sign up' do
visit '/'
within 'nav' do
click_link 'Sign up'
end
fill_in "Email", :with => "[email protected]"
fill_in "Password", :with => "password"
fill_in "Password confirmation", :with => "password"
click_button "Sign up"
page.should have_content("Please open the link to activate your account.")
end
end
This allows you to test the higher level aspect and lets you see the different components (controllers, views, etc...) within your app working together. This is by definition an integration/acceptance test. I would do the same as above for signing_in_spec.rb
and signing_out_spec.rb
Now for Authorization
, I would choose to use controller specs. This allows you to test the individual actions a user has permission to access. These controller specs are more granular in nature and are by definition unit/function tests. For example, say you had a ticket resource and you want to test that only certain users can access some particular functionality
# tickets_controller_spec.rb
describe TicketsController do
let(:user) { FactoryGirl.create(:confirmed_user) }
let(:project) { FactoryGirl.create(:project) }
let(:ticket) { FactoryGirl.create(:ticket, :project => project,
:user => user) }
context "standard users" do
it "cannot access a ticket for a project" do
sign_in(:user, user)
get :show, :id => ticket.id, :project_id => project.id
response.should redirect_to(root_path)
flash[:alert].should eql("The project you were looking for could not be found.")
end
context "with permission to view the project" do
before do
sign_in(:user, user)
define_permission!(user, "view", project)
end
def cannot_create_tickets!
response.should redirect_to(project)
flash[:alert].should eql("You cannot create tickets on this project.")
end
def cannot_update_tickets!
response.should redirect_to(project)
flash[:alert].should eql("You cannot edit tickets on this project.")
end
it "cannot begin to create a ticket" do
get :new, :project_id => project.id
cannot_create_tickets!
end
it "cannot create a ticket without permission" do
post :create, :project_id => project.id
cannot_create_tickets!
end
it "cannot edit a ticket without permission" do
get :edit, { :project_id => project.id, :id => ticket.id }
cannot_update_tickets!
end
it "cannot update a ticket without permission" do
put :update, { :project_id => project.id,
:id => ticket.id,
:ticket => {}
}
cannot_update_tickets!
end
it "cannot delete a ticket without permission" do
delete :destroy, { :project_id => project.id, :id => ticket.id }
response.should redirect_to(project)
flash[:alert].should eql("You cannot delete tickets from this project.")
end
it "can create tickets, but not tag them" do
Permission.create(:user => user, :thing => project, :action => "create tickets")
post :create, :ticket => { :title => "New ticket!",
:description => "Brand spankin' new",
:tag_names => "these are tags"
},
:project_id => project.id
Ticket.last.tags.should be_empty
end
end
end
end
I have found that the combination of rspec-rails
, capybara
and factory_girl_rails
have served well in both types of testing within rails apps.
The examples above were taken from the Rails3Book repo on github. Take a look at the repo for more examples. It is a great way to see the possibilities you have when testing a rails app.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With