2
votes

Been chugging along learning Rspec, Capybara, and FactoryGirl as per Ryan Bates' "How I Test" railscast and hit a snag. My app uses Devise for authentication and CanCan for authorization. I'd like to test to make sure that an user can delete their own posts, but not the posts of other users, but I can't seem to make the deletion happen. I've read about how I should use "controller tests" for this, but googling hasn't shed much light on what the difference is between that and my integration tests and how I might go that route.

Here's my code and, below it, the result:

Factories:

  2 FactoryGirl.define do
  3   factory :role do
  4     factory :admin_role do
  5      name 'admin'
  6     end
  7 
  8     factory :author_role do
  9       name 'author'
 10     end
...
 17   sequence(:name) { |n| "Joe User #{n}"}
 18   sequence(:email) { |n| "joeuser+user#{n}@example.com"}
 19 
 20   factory :user do
 21     name
 22     email
 23     password 'secret'
 24 
 25     factory :admin, :class => User do
 26       name
 27       email
 28       after_create { |user| user.roles << FactoryGirl.create(:admin_role) }
 29     end
 30 
 31     factory :author , :class => User do
 32       name
 33       email
 34       after_create { |user| user.roles << FactoryGirl.create(:author_role) }
 35     end
 36   end
 37 
 38   sequence(:title) { |n| "Post Title #{n}"}
 39   sequence(:body) { |n| "The inner post body #{n}"}
 40 
 41   factory :post do
 42     title
 43     body
 44   end
 45 
 46 end

posts_spec.rb:

  1 require 'spec_helper'                                                                                                                                                                                   
  2 
  3 def login(user)
  4   visit new_user_session_path
  5   fill_in "Email", :with => user.email
  6   fill_in "Password", :with => user.password
  7   click_button "Sign in"
  8   page.should have_content("Signed in successfully")
  9 end
 10 
 11 describe "Posts" do
 12   let(:author) {FactoryGirl.create(:author)}
 13   let(:author2) {FactoryGirl.create(:author)}
 14   let(:user) {FactoryGirl.create(:user)}
 15   let(:admin) {FactoryGirl.create(:admin)}
 16   let(:post) { FactoryGirl.create(:post, user: author) }
...
 99   describe "destroy /post/:id" do
100     it "should allow the author to destroy post" do
101       login(author)
102 
103       visit post_path(post, :method => :delete)
104       lambda {
105         visit post_path(post)                                                                                                                                                                           
106       }.should raise_exception(ActiveRecord::RecordNotFound)
107     end
108   end
109 end

Results from guard:

Running: spec/requests/posts_spec.rb
........F

Failures:

  1) Posts destroy /post/:id should allow the author to destroy post
     Failure/Error: lambda {
       expected ActiveRecord::RecordNotFound but nothing was raised
     # ./spec/requests/posts_spec.rb:104:in `block (3 levels) in <top (required)>'

When I actually save_and_open_page (using launchy) I see that the post hasn't been deleted. Any thoughts on how I should best do this? Thanks much!

1
Are you really want to test abilities via Capybara? There is a solution about testing CanCan: github.com/ryanb/cancan/wiki/Testing-Abilitiesrailscard
This is beautiful, thank you. Exactly what I was looking for. I didn't need to test via Capybara, it was just the only way I really knew how. Thanks again.John Hutch

1 Answers

0
votes

Thank you, railscard, for the solution:

Are you really want to test abilities via Capybara? There is a solution about testing CanCan: github.com/ryanb/cancan/wiki/Testing-Abilities