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
\$\endgroup\$
  • \$\begingroup\$ Please state only the code's purpose in the title. \$\endgroup\$ – Jamal Mar 24 '15 at 13:09
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.

| improve this answer | |
\$\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.

| improve this answer | |
\$\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
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.