This is what my spec looks like:
it "should successfullly destroy that user record" do
expect {
delete :destroy, :id => @user1.id
}.to change{User.count}.by(-1)
end
That calls this action in my UsersController
def destroy
@user = User.find(params[:id])
if @user.destroy
redirect_to root_path, notice: "You have successfully cancelled your account."
else
redirect_to :back
end
end
But when I run that spec, I get this:
RSpec::Expectations::ExpectationNotMetError: expected result to have changed by -1, but was changed by 0
How do I fix this?
Edit 1
@user1
is being initialized in a before_each
call at the top of the context
block that the it
statement lives in. That looks like this:
context "when the inviter is being deleted and invited has not accepted invitation" do
before :each do
@user1 = create(:user, gender: 0)
@user2 = create(:user)
@member = create(:member, email: @user2.email, first_name: @user2.first_name, last_name: @user2.last_name, bio: @user2.bio, gender: @user2.gender)
@membership = create(:membership, member: @member, family_tree: @user1.family_tree, inviter: @user1, relation: "sister")
@connection = create(:connection, inviter_membership: @membership)
login_user
end
Edit 2
When I swap out the test with this, it works:
it "should successfullly destroy that user record" do
delete :destroy, id: @user1
expect(response).to redirect_to(root_path)
# expect {
# delete :destroy, id: @user1
# }.to change(User,:count).by(-1)
end
That test successfully passes.
Finished in 1.2 seconds (files took 6.08 seconds to load)
19 examples, 0 failures, 15 pending
Edit 3
For what it's worth, in my UsersController
I am calling load_and_authorize_resource
at the top. When I remove that, the test does seem to pass. So the question is, how do I get this to work with CanCanCan?
This is what my ability.rb
looks like:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.has_role? :admin
can :manage, :all
end
can :manage, FamilyTree, user_id: user.id
can :manage, Comment, user_id: user.id
can :manage, Node, user_id: user.id
can :manage, Event, user_id: user.id
can :manage, User, id: user.id
can :read, Comment, user_id: user.id
can :read, Event, user_id: user.id
end
end
Edit 4
When I add a raise
to my destroy
action...nothing happens. So it does appear that my destroy
action is indeed not being executed.
Edit 5
This is what my login_user
method looks like:
module SpecAuthentication
def login_user
@request.env["devise.mapping"] = Devise.mappings[:user]
@user = FactoryGirl.create :user
sign_in @user
end
end
With the CanCanCan
gem you have to allow controller actions. You will need to add this to your ability.rb
file.
can :destroy, User
This will allow anyone with that role to destroy a user object. You can add more specifics to fit your use case.
EDIT: Just saw the :manage
documentation on the CanCanCan gem.
Your ability file currently allows users to manage themselves. Your login_user
method is creating a user on the fly while your test is trying to destroy a separate user. You can either update your CanCan ability to let all users be destroyed or try destroying current_user.id
assuming you have a current_user
method. I would strongly suggest changing your login_user
method to accept a user object so that you know which user is logged in and have access to that object.
EDIT:
As noted above, use a method to sign_in a specific user so that you can access it as an object. Replace the login_user
call with sign_in @user1
or a similar method that accepts a user object.