Created
April 1, 2011 09:13
-
-
Save c-vetter/897922 to your computer and use it in GitHub Desktop.
for use with rspec-rails controller specs; avoids duplicate actions that basically differ only in the controller action. note the required spec_helper update
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# streamlines request launching to remove duplication | |
# | |
# enables this setup: | |
# describe SomeController do | |
# describe :index do | |
# it 'works' do | |
# should do_something | |
# launch_request | |
# response.code.should eq('200') | |
# end | |
# end | |
# end | |
# | |
# accepts parameters, session data, flash data like so: | |
# launch_request :params => {}, :session => {}, :flash => {} | |
# | |
# uses POST, PUT, and DELETE for create, update, and destroy requests, respectively, GET otherwise | |
# set @method in a before(:all) block to override this, like so: | |
# before(:all){@method = :post} | |
# | |
# doesn't care where in the hierarchy the action verb is, thus enabling nested shared example groups | |
# | |
# verifies previously set expectations, thus state verification takes place _after_ behaviour verification | |
# BEWARE: this means calling launch_request twice leads to exceptions | |
# | |
# the variant launch_request_without_super makes the action call ignore super | |
# that is useful in case the application's actions inherit from a gem's actions | |
# specifying or stubbing what the gem does can be too much hassle | |
# | |
# | |
# put this in spec_helper: | |
# RSpec.configure do |config| | |
# config.include RequestLaunching, :type => :controller | |
# end | |
# | |
module RequestLaunching | |
def launch_request(options={}) | |
method, action = method_and_action | |
kick_off method, action, options | |
end | |
def launch_request_without_super(options={}, &block) | |
method, action = method_and_action | |
described_class.ancestors[1].send(:alias_method, :stubbed_out_super, action) | |
described_class.ancestors[1].send(:define_method, action, block||lambda{}) | |
kick_off method, action, options | |
described_class.ancestors[1].send(:alias_method, action, :stubbed_out_super) | |
end | |
# shortcuts | |
alias launch launch_request | |
alias launch_request_with_stubbed_super launch_request_without_super | |
alias launch_without_super launch_request_without_super | |
alias launch_with_stubbed_super launch_request_without_super | |
private | |
def kick_off(method, action, options) | |
# prepare data for the launch | |
parameters = (@params ||{}).merge(options[:params] ||{}) unless options[:params].nil? and @params.nil? | |
session = (@session ||{}).merge(options[:session] ||{}) unless options[:session].nil? and @session.nil? | |
flash = (@flash ||{}).merge(options[:flash] ||{}) unless options[:flash].nil? and @flash.nil? | |
# launch the request with the given options, merged into the related instance variables | |
if options[:xhr] || @xhr | |
xml_http_request method, | |
action, | |
parameters, | |
session, | |
flash | |
else | |
__send__ method, | |
action, | |
parameters, | |
session, | |
flash | |
end | |
# verify behaviour expectations | |
RSpec::Mocks.verify | |
end | |
def method_and_action | |
focus = self.class.instance_variable_get('@metadata') | |
# find the nearest action verb | |
while focus = focus[:example_group] do | |
action = focus[:description] and break if described_class.action_methods.include?(focus[:description]) | |
end | |
raise "you need to specify an action of #{described_class}" unless action | |
# find the method corresponding to the action | |
method = @method || { | |
'create' => :post, | |
'update' => :put, | |
'destroy' => :delete | |
}[action] || :get | |
return method, action | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment