I am a total newbie to Ruby and Rails which is why I am going through the Rails Tutorial by Michael Hartl. I am stuck on Chapter 9, Exercise #9. I have updated the def destroy code in the Users Controller to:
def destroy
user = User.find(params[:id])
if (current_user == user) && (current_user.admin?)
flash[:error] = "Can not delete own admin account!"
else
user.destroy
flash[:success] = "User destroyed."
end
redirect_to users_path
end
This seems to work when I test in the browser by adding the "delete" link to the current_user when admin is logged in. But the exercise says to write a test first - which I did but does not seem to work. Here is what I have for the test:
describe "as admin user" do
let(:user_admin) { FactoryGirl.create(:admin) }
before { sign_in user_admin }
describe "submitting a DELETE request to destroy own admin account" do
before { delete user_path(user_admin) }
it { should have_selector('div.alert.alert-error', text: 'delete own admin') }
end
end
Maybe what I am testing should not be tested. How do you test the modification of the def destroy code in the Users Controller?
I tried to get the code in the original post to work, but had no luck. Instead, I got it to work like this (got it to fail, then pass). This tests for the proper redirect as well as the correct flash message.
THE TEST : authentication_pages_spec.rb
describe "as admin user" do
let(:admin) { FactoryGirl.create(:admin) }
before { sign_in admin }
describe "can't delete self by submitting DELETE request to Users#destroy" do
before { delete user_path(admin) }
specify { response.should redirect_to(users_path),
flash[:error].should =~ /Can not delete own admin account!/i }
end
end
IMPLEMENTATION : Users#destroy
def destroy
user = User.find(params[:id])
if (current_user == user) && (current_user.admin?)
flash[:error] = "Can not delete own admin account!"
else
user.destroy
flash[:success] = "User destroyed."
end
redirect_to users_path
end
Perhaps the reason the original test wasn't working is because the way we're issuing the request? I tried adding each of the following individually to the describe block and all failed:
it { should have_selector('div.alert.alert-error', text: 'delete own admin') }
it { should have_selector('title', text: 'All users') }
it { should have_selector('h1', text: 'All users') }
So, seems like Capybara is not actually redirecting to the page to check for these selectors. I tried 'title' and 'h1', thinking maybe there was some problem with the selector 'div.alert.alert-error' ... but the 'title' and 'h1' failed with same "expected CSS to return something" ...
Anyone know more about how specify { response.should ... }
style tests work? If they don't follow redirects when they hit the controller action?
I am also new to the Rails Tutorial (and Rails in general) and had this same problem, and your question helped me figure out the answer.
I am still not certain why your code fails, exactly, but the following steps definitely worked.
First, modify the test code slightly to use the following structure (here I have left out where to put this describe block - you have the right place already):
describe "deleting herself" do
it "should not be possible" do
expect { delete user_path(admin) }.to_not change(User, :count).by(-1)
end
end
Note that I am using an expect{} block to track the number of User objects. This definitely causes the tests to go Red (which is good at this point), whereas checking for the Flash will also make the test go Red, but checking for the error flash doesn't seem to work here. I really don't know why! Maybe something to do with the double redirect that happens?
Next, write the protection code to make the tests green again. Your code works (I think), but I think my code is a bit more idiomatic in that it uses the session helpers defined earlier in Chapter 9.
def destroy
user = User.find(params[:id])
if (current_user? user) && (current_user.admin?)
flash[:error] = "You are not allowed to delete yourself as an admin."
else
user.destroy
flash[:success] = "User destroyed. ID: #{user.id}"
end
redirect_to users_path
end
This change made my test go 'green' again, which successfully completes Exercise 10.
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