Controller Testing - YaleSTC/reservations GitHub Wiki

During its usual run, the Reservations app has a number of barriers, without the setup of which it will lock you out of much functionality (i.e. redirect you to go and set up the app).

Authorization and happy paths: best practice

CanCan Authorization maintains permissions; these manifest in access to controller actions. At worst, this means you might have up to eight separate behaviors with different authorization level.

In such a case, best practice is to write the happy/unhappy paths for the controller code itself into a shared_examples block, then follow up with separate context blocks for every authorization level/situation in which you will include the appropriate shared example groups (via include_examples or it_behaves_like).

AppConfig and current_user

Every controller checks that AppConfig exists and current_user has (whatever) privileges. Therefore, preface your controller tests with

before(:all) do
  @app_config = FactoryGirl.create(:app_config)
end
before(:each) do
  @controller.stub(:first_time_user).and_return(FactoryGirl.create(:user))
  @controller.stub(:current_user).and_return(FactoryGirl.create(:admin)) # Or whatever other role
end

This is because unless Reservations detects a valid AppConfig and a user with proper authorization, it will redirect to a set-up page (or bad-authentication page). That is, however, not immediately clear from the tests failing.

It is worth noting, too, that FactoryGirl cleans up after itself; consequently, it is not necessary to add an after(:all) { @app_config.destroy } hook. In fact, it breaks the database state (for some reason), so don't do it.

Cart

The Cart object lives in session[:cart]. In order to set it, it needs to be passed as a third argument to the HTTP request verb, e.g.

get :new, nil, { cart: FactoryGirl.build(:cart_with_items, reserver_id: @user.id) }