Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically generating shared examples in RSpec 2?

I'm trying to keep my specs DRY by creating a shared example group that performs the boilerplate checks for all admin controllers (all controllers under the Admin namespace of my project). I'm struggling to figure out how to do it, since the shared example needs providing with the information about what actions and parameters to use. It should ideally present meaningful errors if a test fails (i.e. include the details of the action it was testing).

require 'spec_helper'

shared_examples "an admin controller" do

  before(:each) do
    @non_admin = User.make
    @admin = User.make(:admin)
  end

  context "as an admin user" do
    @actions.each do |action, params|

      specify "I should be able to access ##{action.last} via #{action.first}" do
        self.active_user = @admin
        send(action.first, action.last, params)

        response.status.should be_ok
      end

    end   
  end

  context "as a regular user" do
    @actions.each do |action, params|

      specify "I should be denied access to ##{action.last}" do
        self.active_user = @non_admin
        send(action.first, action.last, params)

        response.status.should be 403
      end

    end   
  end

end

describe Admin::UserNotesController do

  @user = User.make
  @actions = { [:get, :index]   => { :user_id => @user.id },
               [:get, :new]     => { :user_id => @user.id },
               [:post, :create] => { :user_id => @user.id } }

  it_behaves_like "an admin controller"

end

This errors for the obvious reason that @actions is not visible to the shared example group. If I use let, this is only available in the context of an example, not in the context of the describe block. Any ideas?

like image 669
d11wtq Avatar asked May 27 '11 12:05

d11wtq


1 Answers

Here's a much cleaner way that should work:

require 'spec_helper'

shared_examples "an admin controller" do |actions|
  context "as an admin user" do
    actions.each_pair do |action, verb|
      specify "I should be able to access ##{action} via #{verb}" do
        send(verb, action, :user_id => User.make(:admin).id)
        response.status.should be_ok
      end
    end   
  end

  context "as a regular user" do
    actions.each_pair do |action, verb|
      specify "I should be denied access to ##{action}" do
        send(verb, action, :user_id => User.make.id)
        response.status.should be 403
      end
    end   
  end
end

describe Admin::UserNotesController do
  it_behaves_like "an admin controller", { 
    :index  => :get,
    :new    => :get,
    :create => :post
  }
end

See http://relishapp.com/rspec/rspec-core/v/2-6/dir/example-groups/shared-examples for more information

like image 120
David Chelimsky Avatar answered Nov 07 '22 05:11

David Chelimsky