← Back to Upcase

Testing not marking other users tasks complete


(Aaron Renner) #1

At 38 minutes in the “unit testing” video, you mentioned we could write a test that ensures a user cannot mark another user’s task as complete. I put together the following scenario, but think it needs some work.

scenario 'not mark other users tasks as complete' do
  other_user_todo = create(:todo, description: 'Buy some eggs', owner_email: 'not_me@example.com')
  sign_in_as 'me@example.com'

  #Posting code from here: http://stackoverflow.com/a/5616072/614775
  page.driver.post("/todos/#{other_user_todo.id}/completion")
  expect(page.driver.status_code).to eq 404
end

Moreover, when I run the test it doesn’t pass. I get the following failure:

ActiveRecord::RecordNotFound:
Couldn't find Todo with id=1 [WHERE "todos"."owner_email" = 'me@example.com']

How would you handle this type of testing, and more generally security testing so users can’t mess with other users stuff? I am thinking in this scenario a controller test might be the way to go, but would be interested in your ideas.

Thanks,
Aaron


(Josh Clayton) #2

@aaronrenner a controller spec is what you want here - while there are ways to simulate posts from the driver (which you did with page.driver.post), a controller spec is definitely more suited for that type of test. We don’t cover controller specs in the online workshop so I’d dig through the RSpec docs for a couple examples of how to test it this way. You’re definitely on the right path though!


(Aaron Renner) #3

@joshclayton Thanks for the reply. For future reference here’s the controller spec I put together.

require 'spec_helper'

describe CompletionsController do
  describe "POST 'create'" do
    it "prevents completion of a todo that doesn't belong to the current user" do
      sign_in_as "me@example.com"
      other_user_todo = create :todo, owner_email: "not-me@example.com"

      expect {
        post :create, todo_id: other_user_todo.id
      }.to raise_error(ActiveRecord::RecordNotFound)
    end

  end

  def sign_in_as(user)
    controller.sign_in_as(user)
  end
end

Let me know if you would refactor it or take a different approach.


(Josh Clayton) #4

@aaronrenner is it possible to assert it returns a status code 404 or a 401 (to denote the user is not authorized to do anything to that certain todo)? Only other thing that I’d probably do is structure the spec like this:

describe CompletionsController, 'POST "create"' do
  it '...' do
  end

  def sign_in_as(user)
  end
end

This way, it’s one fewer level of nesting and easier to parse visually. Looks good though - and it’s a lot more obvious what’s happening here!