Revert the removal of should_be_restful.
This reverts commits10303b28f3
,f018d08444
and66eaccf98c
, which collectively removed should_be_restful. We need to deprecate should_be_restful for a good while before we actually remove it from the codebase. This also reverts the gem version back to 2.0.0. We'll see if github has a problem with that.
This commit is contained in:
parent
66eaccf98c
commit
9a43008886
13
README.rdoc
13
README.rdoc
|
@ -90,6 +90,19 @@ Macros to test the most common controller patterns...
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Test entire controllers in a few lines...
|
||||||
|
|
||||||
|
class PostsControllerTest < Test::Unit::TestCase
|
||||||
|
should_be_restful do |resource|
|
||||||
|
resource.parent = :user
|
||||||
|
|
||||||
|
resource.create.params = { :title => "first post", :body => 'blah blah blah'}
|
||||||
|
resource.update.params = { :title => "changed" }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
should_be_restful generates 40 tests on the fly, for both html and xml requests.
|
||||||
|
|
||||||
=== Helpful Assertions (ThoughtBot::Shoulda::Assertions)
|
=== Helpful Assertions (ThoughtBot::Shoulda::Assertions)
|
||||||
|
|
||||||
More to come here, but have fun with what's there.
|
More to come here, but have fun with what's there.
|
||||||
|
|
|
@ -22,7 +22,53 @@ module ThoughtBot # :nodoc:
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# Would produce 5 tests for the +show+ action
|
# Would produce 5 tests for the +show+ action
|
||||||
|
#
|
||||||
|
# Furthermore, the should_be_restful helper will create an entire set of tests which will verify that your
|
||||||
|
# controller responds restfully to a variety of requested formats.
|
||||||
module Macros
|
module Macros
|
||||||
|
# :section: should_be_restful
|
||||||
|
# Generates a full suite of tests for a restful controller.
|
||||||
|
#
|
||||||
|
# The following definition will generate tests for the +index+, +show+, +new+,
|
||||||
|
# +edit+, +create+, +update+ and +destroy+ actions, in both +html+ and +xml+ formats:
|
||||||
|
#
|
||||||
|
# should_be_restful do |resource|
|
||||||
|
# resource.parent = :user
|
||||||
|
#
|
||||||
|
# resource.create.params = { :title => "first post", :body => 'blah blah blah'}
|
||||||
|
# resource.update.params = { :title => "changed" }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# This generates about 40 tests, all of the format:
|
||||||
|
# "on GET to :show should assign @user."
|
||||||
|
# "on GET to :show should not set the flash."
|
||||||
|
# "on GET to :show should render 'show' template."
|
||||||
|
# "on GET to :show should respond with success."
|
||||||
|
# "on GET to :show as xml should assign @user."
|
||||||
|
# "on GET to :show as xml should have ContentType set to 'application/xml'."
|
||||||
|
# "on GET to :show as xml should respond with success."
|
||||||
|
# "on GET to :show as xml should return <user/> as the root element."
|
||||||
|
# The +resource+ parameter passed into the block is a ResourceOptions object, and
|
||||||
|
# is used to configure the tests for the details of your resources.
|
||||||
|
#
|
||||||
|
def should_be_restful(&blk) # :yields: resource
|
||||||
|
resource = ResourceOptions.new
|
||||||
|
blk.call(resource)
|
||||||
|
resource.normalize!(self)
|
||||||
|
|
||||||
|
resource.formats.each do |format|
|
||||||
|
resource.actions.each do |action|
|
||||||
|
if self.respond_to? :"make_#{action}_#{format}_tests"
|
||||||
|
self.send(:"make_#{action}_#{format}_tests", resource)
|
||||||
|
else
|
||||||
|
should "test #{action} #{format}" do
|
||||||
|
flunk "Test for #{action} as #{format} not implemented"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# :section: Test macros
|
# :section: Test macros
|
||||||
# Macro that creates a test asserting that the flash contains the given value.
|
# Macro that creates a test asserting that the flash contains the given value.
|
||||||
# val can be a String, a Regex, or nil (indicating that the flash should not be set)
|
# val can be a String, a Regex, or nil (indicating that the flash should not be set)
|
||||||
|
|
|
@ -1,10 +1,234 @@
|
||||||
module ThoughtBot # :nodoc:
|
module ThoughtBot # :nodoc:
|
||||||
module Shoulda # :nodoc:
|
module Shoulda # :nodoc:
|
||||||
module Controller
|
module Controller
|
||||||
|
# Formats tested by #should_be_restful. Defaults to [:html, :xml]
|
||||||
VALID_FORMATS = Dir.glob(File.join(File.dirname(__FILE__), 'formats', '*.rb')).map { |f| File.basename(f, '.rb') }.map(&:to_sym) # :doc:
|
VALID_FORMATS = Dir.glob(File.join(File.dirname(__FILE__), 'formats', '*.rb')).map { |f| File.basename(f, '.rb') }.map(&:to_sym) # :doc:
|
||||||
VALID_FORMATS.each {|f| require "shoulda/controller/formats/#{f}"}
|
VALID_FORMATS.each {|f| require "shoulda/controller/formats/#{f}"}
|
||||||
|
|
||||||
|
# Actions tested by #should_be_restful
|
||||||
VALID_ACTIONS = [:index, :show, :new, :edit, :create, :update, :destroy] # :doc:
|
VALID_ACTIONS = [:index, :show, :new, :edit, :create, :update, :destroy] # :doc:
|
||||||
|
|
||||||
|
# A ResourceOptions object is passed into should_be_restful in order to configure the tests for your controller.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# class UsersControllerTest < Test::Unit::TestCase
|
||||||
|
# fixtures :all
|
||||||
|
#
|
||||||
|
# def setup
|
||||||
|
# ...normal setup code...
|
||||||
|
# @user = User.find(:first)
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# should_be_restful do |resource|
|
||||||
|
# resource.identifier = :id
|
||||||
|
# resource.klass = User
|
||||||
|
# resource.object = :user
|
||||||
|
# resource.parent = []
|
||||||
|
# resource.actions = [:index, :show, :new, :edit, :update, :create, :destroy]
|
||||||
|
# resource.formats = [:html, :xml]
|
||||||
|
#
|
||||||
|
# resource.create.params = { :name => "bob", :email => 'bob@bob.com', :age => 13}
|
||||||
|
# resource.update.params = { :name => "sue" }
|
||||||
|
#
|
||||||
|
# resource.create.redirect = "user_url(@user)"
|
||||||
|
# resource.update.redirect = "user_url(@user)"
|
||||||
|
# resource.destroy.redirect = "users_url"
|
||||||
|
#
|
||||||
|
# resource.create.flash = /created/i
|
||||||
|
# resource.update.flash = /updated/i
|
||||||
|
# resource.destroy.flash = /removed/i
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# Whenever possible, the resource attributes will be set to sensible defaults.
|
||||||
|
#
|
||||||
|
class ResourceOptions
|
||||||
|
# Configuration options for the create, update, destroy actions under should_be_restful
|
||||||
|
class ActionOptions
|
||||||
|
# String evaled to get the target of the redirection.
|
||||||
|
# All of the instance variables set by the controller will be available to the
|
||||||
|
# evaled code.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# resource.create.redirect = "user_url(@user.company, @user)"
|
||||||
|
#
|
||||||
|
# Defaults to a generated url based on the name of the controller, the action, and the resource.parents list.
|
||||||
|
attr_accessor :redirect
|
||||||
|
|
||||||
|
# String or Regexp describing a value expected in the flash. Will match against any flash key.
|
||||||
|
#
|
||||||
|
# Defaults:
|
||||||
|
# destroy:: /removed/
|
||||||
|
# create:: /created/
|
||||||
|
# update:: /updated/
|
||||||
|
attr_accessor :flash
|
||||||
|
|
||||||
|
# Hash describing the params that should be sent in with this action.
|
||||||
|
attr_accessor :params
|
||||||
|
end
|
||||||
|
|
||||||
|
# Configuration options for the denied actions under should_be_restful
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# context "The public" do
|
||||||
|
# setup do
|
||||||
|
# @request.session[:logged_in] = false
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# should_be_restful do |resource|
|
||||||
|
# resource.parent = :user
|
||||||
|
#
|
||||||
|
# resource.denied.actions = [:index, :show, :edit, :new, :create, :update, :destroy]
|
||||||
|
# resource.denied.flash = /get outta here/i
|
||||||
|
# resource.denied.redirect = 'new_session_url'
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
class DeniedOptions
|
||||||
|
# String evaled to get the target of the redirection.
|
||||||
|
# All of the instance variables set by the controller will be available to the
|
||||||
|
# evaled code.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# resource.create.redirect = "user_url(@user.company, @user)"
|
||||||
|
attr_accessor :redirect
|
||||||
|
|
||||||
|
# String or Regexp describing a value expected in the flash. Will match against any flash key.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# resource.create.flash = /created/
|
||||||
|
attr_accessor :flash
|
||||||
|
|
||||||
|
# Actions that should be denied (only used by resource.denied). <i>Note that these actions will
|
||||||
|
# only be tested if they are also listed in +resource.actions+</i>
|
||||||
|
# The special value of :all will deny all of the REST actions.
|
||||||
|
attr_accessor :actions
|
||||||
|
end
|
||||||
|
|
||||||
|
# Name of key in params that references the primary key.
|
||||||
|
# Will almost always be :id (default), unless you are using a plugin or have patched rails.
|
||||||
|
attr_accessor :identifier
|
||||||
|
|
||||||
|
# Name of the ActiveRecord class this resource is responsible for. Automatically determined from
|
||||||
|
# test class if not explicitly set. UserTest => "User"
|
||||||
|
attr_accessor :klass
|
||||||
|
|
||||||
|
# Name of the instantiated ActiveRecord object that should be used by some of the tests.
|
||||||
|
# Defaults to the underscored name of the AR class. CompanyManager => :company_manager
|
||||||
|
attr_accessor :object
|
||||||
|
|
||||||
|
# Name of the parent AR objects. Can be set as parent= or parents=, and can take either
|
||||||
|
# the name of the parent resource (if there's only one), or an array of names (if there's
|
||||||
|
# more than one).
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# # in the routes...
|
||||||
|
# map.resources :companies do
|
||||||
|
# map.resources :people do
|
||||||
|
# map.resources :limbs
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # in the tests...
|
||||||
|
# class PeopleControllerTest < Test::Unit::TestCase
|
||||||
|
# should_be_restful do |resource|
|
||||||
|
# resource.parent = :companies
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# class LimbsControllerTest < Test::Unit::TestCase
|
||||||
|
# should_be_restful do |resource|
|
||||||
|
# resource.parents = [:companies, :people]
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
attr_accessor :parent
|
||||||
|
alias parents parent
|
||||||
|
alias parents= parent=
|
||||||
|
|
||||||
|
# Actions that should be tested. Must be a subset of VALID_ACTIONS (default).
|
||||||
|
# Tests for each actionw will only be generated if the action is listed here.
|
||||||
|
# The special value of :all will test all of the REST actions.
|
||||||
|
#
|
||||||
|
# Example (for a read-only controller):
|
||||||
|
# resource.actions = [:show, :index]
|
||||||
|
attr_accessor :actions
|
||||||
|
|
||||||
|
# Formats that should be tested. Must be a subset of VALID_FORMATS (default).
|
||||||
|
# Each action will be tested against the formats listed here. The special value
|
||||||
|
# of :all will test all of the supported formats.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# resource.actions = [:html, :xml]
|
||||||
|
attr_accessor :formats
|
||||||
|
|
||||||
|
# ActionOptions object specifying options for the create action.
|
||||||
|
attr_accessor :create
|
||||||
|
|
||||||
|
# ActionOptions object specifying options for the update action.
|
||||||
|
attr_accessor :update
|
||||||
|
|
||||||
|
# ActionOptions object specifying options for the desrtoy action.
|
||||||
|
attr_accessor :destroy
|
||||||
|
|
||||||
|
# DeniedOptions object specifying which actions should return deny a request, and what should happen in that case.
|
||||||
|
attr_accessor :denied
|
||||||
|
|
||||||
|
def initialize # :nodoc:
|
||||||
|
@create = ActionOptions.new
|
||||||
|
@update = ActionOptions.new
|
||||||
|
@destroy = ActionOptions.new
|
||||||
|
@denied = DeniedOptions.new
|
||||||
|
|
||||||
|
@create.flash ||= /created/i
|
||||||
|
@update.flash ||= /updated/i
|
||||||
|
@destroy.flash ||= /removed/i
|
||||||
|
@denied.flash ||= /denied/i
|
||||||
|
|
||||||
|
@create.params ||= {}
|
||||||
|
@update.params ||= {}
|
||||||
|
|
||||||
|
@actions = VALID_ACTIONS
|
||||||
|
@formats = VALID_FORMATS
|
||||||
|
@denied.actions = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize!(target) # :nodoc:
|
||||||
|
@denied.actions = VALID_ACTIONS if @denied.actions == :all
|
||||||
|
@actions = VALID_ACTIONS if @actions == :all
|
||||||
|
@formats = VALID_FORMATS if @formats == :all
|
||||||
|
|
||||||
|
@denied.actions = @denied.actions.map(&:to_sym)
|
||||||
|
@actions = @actions.map(&:to_sym)
|
||||||
|
@formats = @formats.map(&:to_sym)
|
||||||
|
|
||||||
|
ensure_valid_members(@actions, VALID_ACTIONS, 'actions')
|
||||||
|
ensure_valid_members(@denied.actions, VALID_ACTIONS, 'denied.actions')
|
||||||
|
ensure_valid_members(@formats, VALID_FORMATS, 'formats')
|
||||||
|
|
||||||
|
@identifier ||= :id
|
||||||
|
@klass ||= target.name.gsub(/ControllerTest$/, '').singularize.constantize
|
||||||
|
@object ||= @klass.name.tableize.singularize
|
||||||
|
@parent ||= []
|
||||||
|
@parent = [@parent] unless @parent.is_a? Array
|
||||||
|
|
||||||
|
collection_helper = [@parent, @object.to_s.pluralize, 'url'].flatten.join('_')
|
||||||
|
collection_args = @parent.map {|n| "@#{object}.#{n}"}.join(', ')
|
||||||
|
@destroy.redirect ||= "#{collection_helper}(#{collection_args})"
|
||||||
|
|
||||||
|
member_helper = [@parent, @object, 'url'].flatten.join('_')
|
||||||
|
member_args = [@parent.map {|n| "@#{object}.#{n}"}, "@#{object}"].flatten.join(', ')
|
||||||
|
@create.redirect ||= "#{member_helper}(#{member_args})"
|
||||||
|
@update.redirect ||= "#{member_helper}(#{member_args})"
|
||||||
|
@denied.redirect ||= "new_session_url"
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def ensure_valid_members(ary, valid_members, name) # :nodoc:
|
||||||
|
invalid = ary - valid_members
|
||||||
|
raise ArgumentError, "Unsupported #{name}: #{invalid.inspect}" unless invalid.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
Gem::Specification.new do |s|
|
Gem::Specification.new do |s|
|
||||||
s.name = %q{shoulda}
|
s.name = %q{shoulda}
|
||||||
s.version = "2.0.1"
|
s.version = "2.0.0"
|
||||||
|
|
||||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||||
s.authors = ["Tammer Saleh"]
|
s.authors = ["Tammer Saleh"]
|
||||||
s.date = %q{2008-09-20}
|
s.date = %q{2008-09-14}
|
||||||
s.default_executable = %q{convert_to_should_syntax}
|
s.default_executable = %q{convert_to_should_syntax}
|
||||||
s.email = %q{tsaleh@thoughtbot.com}
|
s.email = %q{tsaleh@thoughtbot.com}
|
||||||
s.executables = ["convert_to_should_syntax"]
|
s.executables = ["convert_to_should_syntax"]
|
||||||
|
|
|
@ -33,11 +33,32 @@ class PostsControllerTest < Test::Unit::TestCase
|
||||||
should_route :get, '/users/5/posts/new', :action => :new, :user_id => 5
|
should_route :get, '/users/5/posts/new', :action => :new, :user_id => 5
|
||||||
should_route :put, '/users/5/posts/1', :action => :update, :id => 1, :user_id => 5
|
should_route :put, '/users/5/posts/1', :action => :update, :id => 1, :user_id => 5
|
||||||
|
|
||||||
|
context "The public" do
|
||||||
|
setup do
|
||||||
|
@request.session[:logged_in] = false
|
||||||
|
end
|
||||||
|
|
||||||
|
should_be_restful do |resource|
|
||||||
|
resource.parent = :user
|
||||||
|
|
||||||
|
resource.denied.actions = [:index, :show, :edit, :new, :create, :update, :destroy]
|
||||||
|
resource.denied.flash = /what/i
|
||||||
|
resource.denied.redirect = '"/"'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "Logged in" do
|
context "Logged in" do
|
||||||
setup do
|
setup do
|
||||||
@request.session[:logged_in] = true
|
@request.session[:logged_in] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
should_be_restful do |resource|
|
||||||
|
resource.parent = :user
|
||||||
|
|
||||||
|
resource.create.params = { :title => "first post", :body => 'blah blah blah'}
|
||||||
|
resource.update.params = { :title => "changed" }
|
||||||
|
end
|
||||||
|
|
||||||
context "viewing posts for a user" do
|
context "viewing posts for a user" do
|
||||||
setup do
|
setup do
|
||||||
get :index, :user_id => users(:first)
|
get :index, :user_id => users(:first)
|
||||||
|
|
|
@ -14,30 +14,23 @@ class UsersControllerTest < Test::Unit::TestCase
|
||||||
@user = User.find(:first)
|
@user = User.find(:first)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "on GET to #index" do
|
should_be_restful do |resource|
|
||||||
setup { get :index }
|
resource.identifier = :id
|
||||||
|
resource.klass = User
|
||||||
|
resource.object = :user
|
||||||
|
resource.parent = []
|
||||||
|
resource.actions = [:index, :show, :new, :edit, :update, :create, :destroy]
|
||||||
|
resource.formats = [:html, :xml]
|
||||||
|
|
||||||
should_respond_with :success
|
resource.create.params = { :name => "bob", :email => 'bob@bob.com', :age => 13, :ssn => "123456789"}
|
||||||
should_render_with_layout 'users'
|
resource.update.params = { :name => "sue" }
|
||||||
should_render_template :index
|
|
||||||
should_assign_to :users
|
resource.create.redirect = "user_url(@user)"
|
||||||
|
resource.update.redirect = "user_url(@user)"
|
||||||
|
resource.destroy.redirect = "users_url"
|
||||||
|
|
||||||
|
resource.create.flash = /created/i
|
||||||
|
resource.update.flash = /updated/i
|
||||||
|
resource.destroy.flash = /removed/i
|
||||||
end
|
end
|
||||||
|
|
||||||
context "on GET to #index.xml" do
|
|
||||||
setup { get :index, :format => 'xml' }
|
|
||||||
|
|
||||||
should_respond_with :success
|
|
||||||
should_respond_with_xml_for
|
|
||||||
should_assign_to :users
|
|
||||||
end
|
|
||||||
|
|
||||||
context "on GET to #show" do
|
|
||||||
setup { get :show, :id => @user }
|
|
||||||
|
|
||||||
should_respond_with :success
|
|
||||||
should_render_with_layout 'users'
|
|
||||||
should_render_template :show
|
|
||||||
should_assign_to :user
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue