2
\$\begingroup\$

I'm just starting with rails and testing, and not sure what's good way to dry code like this.

require 'rails_helper'
describe EventsController, type: :controller do
 let(:admin) { create(:user_admin) }
 let(:mod) { create(:user_moderator) }
 let(:user) { create(:user) }
 let(:link) { create(:link) }
 let(:event) { create(:event) }
 describe 'GET #new' do
 it 'allows admin user to perform action' do
 sign_in admin
 get :new, link: link.id
 expect(flash[:alert]).to_not match(/^You are not authorized to perform this action./)
 end
 it 'allows mod user to perform action' do
 sign_in mod
 get :new, link: link.id
 expect(flash[:alert]).to_not match(/^You are not authorized to perform this action./)
 end
 it 'does not allow regular user to perform action' do
 sign_in user
 get :new, link: link.id
 expect(flash[:alert]).to match(/^You are not authorized to perform this action./)
 end
 it 'does not allow guest to perform action' do
 get :new, link: link.id
 expect(flash[:alert]).to match(/^You are not authorized to perform this action./)
 end
 end
 describe 'POST #create' do
 it 'allows admin user to perform action' do
 sign_in admin
 post :create, event: attributes_for_event(event, link)
 expect(flash[:alert]).to_not match(/^You are not authorized to perform this action./)
 end
 it 'allows mod user to perform action' do
 sign_in mod
 post :create, event: attributes_for_event(event, link)
 expect(flash[:alert]).to_not match(/^You are not authorized to perform this action./)
 end
 it 'does not allow regular user to perform action' do
 sign_in user
 post :create, event: attributes_for_event(event, link)
 expect(flash[:alert]).to match(/^You are not authorized to perform this action./)
 end
 it 'does not allow guest to perform action' do
 post :create, event: attributes_for_event(event, link)
 expect(flash[:alert]).to match(/^You are not authorized to perform this action./)
 end
 end
end
asked Mar 24, 2015 at 11:42
\$\endgroup\$
1
  • \$\begingroup\$ Please state only the code's purpose in the title. \$\endgroup\$ Commented Mar 24, 2015 at 13:09

3 Answers 3

1
\$\begingroup\$

You could DRY the specs in the following way:

  1. perform the authentication of the user in a before block
  2. when testing a controller the subject could be the request itself
  3. use context blocks for better structure
  4. use functions for making the assertions when it comes to flash messages

So, keeping these in mind, you could write your specs like this:

require 'rails_helper'
describe EventsController, type: :controller do
 let(:link) { create(:link) }
 let(:event) { create(:event) }
 let(:admin) { create(:user_admin) }
 let(:moderator) { create(:user_moderator) }
 let(:user) { create(:user) }
 AUTHORIZATION_ERROR = /^You are not authorized to perform this action/
 describe 'GET #new' do
 subject { get :new, link: link.id }
 before(:each) do
 sign_in(authorized_resource) if authorized_resource.present?
 end
 context 'for user with admin role' do
 let(:authorized_resource) { admin }
 it 'does not display an alert' do
 subject
 expect(flash[:alert]).to_not match(AUTHORIZATION_ERROR)
 end
 end
 context 'for user with moderator role' do
 let(:authorized_resource) { moderator }
 it 'does not display an alert' do
 subject
 expect(flash[:alert]).to_not match(AUTHORIZATION_ERROR)
 end
 end
 context 'for user with no role' do
 let(:authorized_resource) { user }
 it 'displays an alert' do
 subject
 expect(flash[:alert]).to match(AUTHORIZATION_ERROR)
 end
 end
 context 'for guest user' do
 it 'displays an alert' do
 subject
 expect(flash[:alert]).to match(AUTHORIZATION_ERROR)
 end
 end
 end
end

It might make sense to check for response codes as well (e.g. 401 Unauthorized, 403 Forbidden, etc) since a flash message on its own does say much about what's going on with the controller.

answered Mar 24, 2015 at 20:53
\$\endgroup\$
0
\$\begingroup\$

I don't think this spec needs DRY-ing. You've reduced things down to realistic usage scenarios, which is exactly what you want to do. The steps in each spec are not 100% the same, so there really isn't any code repetition.

While it may feel like you've got repeated code, your tests are explicit and easy to follow. I wouldn't change anything.

answered Mar 24, 2015 at 12:47
\$\endgroup\$
0
\$\begingroup\$

I would just factor out the flash error into a constant. Also, I believe the trailing period in your regex should be escaped, as you don't want to match any character.

require 'rails_helper'
FLASH_ERROR = /^You are not authorized to perform this action\./
describe EventsController, type: :controller do
 let(:admin) { create(:user_admin) }
 let(:mod) { create(:user_moderator) }
 let(:user) { create(:user) }
 let(:link) { create(:link) }
 let(:event) { create(:event) }
 describe 'GET #new' do
 it 'allows admin user to perform action' do
 sign_in admin
 get :new, link: link.id
 expect(flash[:alert]).to_not match FLASH_ERROR
 end
 it 'allows mod user to perform action' do
 sign_in mod
 get :new, link: link.id
 expect(flash[:alert]).to_not match FLASH_ERROR
 end
 it 'does not allow regular user to perform action' do
 sign_in user
 get :new, link: link.id
 expect(flash[:alert]).to match FLASH_ERROR
 end
 it 'does not allow guest to perform action' do
 get :new, link: link.id
 expect(flash[:alert]).to match FLASH_ERROR
 end
 end
 describe 'POST #create' do
 it 'allows admin user to perform action' do
 sign_in admin
 post :create, event: attributes_for_event(event, link)
 expect(flash[:alert]).to_not match FLASH_ERROR
 end
 it 'allows mod user to perform action' do
 sign_in mod
 post :create, event: attributes_for_event(event, link)
 expect(flash[:alert]).to_not match FLASH_ERROR
 end
 it 'does not allow regular user to perform action' do
 sign_in user
 post :create, event: attributes_for_event(event, link)
 expect(flash[:alert]).to match FLASH_ERROR
 end
 it 'does not allow guest to perform action' do
 post :create, event: attributes_for_event(event, link)
 expect(flash[:alert]).to match FLASH_ERROR
 end
 end
end
answered Mar 24, 2015 at 13:05
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.