RubyNerd
RubyNerd

Reputation: 59

Testing that an object is owned or created by current_user

I am currently trying to make a dropbox-esque application from a tutorial and I am having trouble trying to figure out how I would test this controller.

this is the AssetsController page

    def index
       @assets = current_user.assets
    end

    def show
       @assets = current_user.assets.find(params[:id])

Also, assets belong_to :user and user has_many :assets

How would I go about putting that into an rspec test?

Upvotes: 2

Views: 172

Answers (2)

Joe Pym
Joe Pym

Reputation: 1836

Firstly, be very careful about AssetsController.

Assuming you are using Rails 3, the "assets_path" is also the path used to load your application assets, and hence, anything you write to the session in that controller will be ignored silently. Probably not what you want! I'd strongly consider renaming the controller.

I'd first create the user in a sign-in block

module ControllerMacros
  def login_user
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:user]
      @user = Factory.create(:user)
      sign_in @user
    end
  end
end

You can then load this in the spec_helper.rb file

RSpec.configure do |config|
  config.include Devise::TestHelpers, :type => :controller
  config.extend ControllerMacros, :type => :controller
end

Finally, you can use this in the test

describe MyController do
  context "#index" do
    login_user
    before(:each) do
      @assets = []
      5.times{ @assets << Factory.create(:asset, :user => @user)}
    end

    it "should test index" do
      get :index
      assigns(:assets).should eq(@assets)
    end
  end
end

Now, that should test your asset list correctly.

EDIT: Just realised, I'm using FactoryGirl/Devise here, you may or may not be!

Upvotes: 3

thorsten m&#252;ller
thorsten m&#252;ller

Reputation: 5651

What exactly is you question? How to setup basic tests for the relations or how to test the management of current_user?

The basic tests for this should be in the Model Specs, since it's the job of the model to sort out such things.

I normally test it like this:

1) define the fixtures (or alternately use something like FactoryGirl) for two users and some assets (three for this example). assets for user a are named asset_a_*, those for user b asset_b_*)

2) The test is simply like this:

   users(:users_a).assets.should have(3).records
   users(:users_a).assets.should include(assets(:asset_a_a))
   users(:users_a).assets.should include(assets(:assets_a_b))
   users(:users_a).assets.should include(assets(:assets_a_c))

You can finetune this like users(:users_a).assets.find(assets(:asset_a_a).id).should include(assets(:asset_a_a)) users(:users_a).assets.find(assets(:asset_a_a).id).should_not include(assets(:asset_b_a))

If you absolutely want, you can use similar tests for the controller part.

Though there are quite some discussions if such basic functionality needs testing at all, since it's mostly core Rails functionality to handle the associations you defined in your model.

Personally I do this kind of testing for some reasons. In many cases such permission related associations soon become more complicated and need detailed tests anyway. or somebody may change the parameters of the association and break something.

II - About the current_user part within the controller.

This depends of course on how you handle the authentication to begin with. If you use a plugin like AuthLogic (or whatever) it may have some methods that allow simulating the login in rspec. For authlogic you can do something like this:

before(:each) do
  activate_authlogic
  UserSession.create(users(:user_a))
end

This will activate authlogic and 'login' user_a. Then you run you controller

  get :index
  response.should be_success
  response.should render_template :index
  assigns(:assets).should # => more or less as above, check that there are the right aessets.

Upvotes: 1

Related Questions