mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-26 03:58:49 +01:00
Upgrade skinny_spec to deal with newer version of RSpec due to unfreezing.
This commit is contained in:
parent
bbf3e95b21
commit
feeca283b4
17 changed files with 703 additions and 203 deletions
39
vendor/plugins/skinny_spec/README.rdoc
vendored
39
vendor/plugins/skinny_spec/README.rdoc
vendored
|
|
@ -39,12 +39,6 @@ specs) to see what's new and different with Skinny Spec.
|
|||
Let's look at the controller specs.
|
||||
|
||||
describe UsersController do
|
||||
def valid_attributes(args = {})
|
||||
{
|
||||
# Add valid attributes for the your params[:user] here!
|
||||
}.merge(args)
|
||||
end
|
||||
|
||||
describe "GET :index" do
|
||||
before(:each) do
|
||||
@users = stub_index(User)
|
||||
|
|
@ -68,12 +62,7 @@ Let's look at the controller specs.
|
|||
|
||||
# ...
|
||||
|
||||
First thing you should see is a method definition for
|
||||
<tt>valid_attributes</tt>. This will be used later by the <tt>create</tt> and <tt>update</tt>
|
||||
specs to more accurately represent how the controller works in actual practice by supplying
|
||||
somewhat real data for the <tt>params</tt> coming from the HTML forms.
|
||||
|
||||
Next we find an example group for <tt>GET :index</tt>. That <tt>stub_index</tt> method there
|
||||
First thing you should see is an example group for <tt>GET :index</tt>. That <tt>stub_index</tt> method there
|
||||
does a lot of work behind the curtain. I'll leave it up to you to check the documentation for it
|
||||
(and its brothers and sister methods like <tt>stub_new</tt>) but I will point out that the
|
||||
methods named <tt>stub_<i>controller_method</i></tt> should only be used for stubbing and
|
||||
|
|
@ -82,8 +71,16 @@ use <tt>stub_find_all</tt>, <tt>stub_find_one</tt>, and <tt>stub_initialize</tt>
|
|||
for this is because the former methods actually save us a step by defining an implicit
|
||||
controller method request. If you add a new method to your resource routing, you'll want to
|
||||
use the helper method <tt>define_request</tt> in those example groups to define an explicit
|
||||
request. You can also define a method called <tt>shared_request</tt> to "share a
|
||||
<tt>define_request</tt>" across shared describe blocks, like so:
|
||||
request, like so:
|
||||
|
||||
describe "PUT :demote" do
|
||||
define_request { put :demote }
|
||||
|
||||
# ...
|
||||
end
|
||||
|
||||
You can also define a method called <tt>shared_request</tt> to "share" a
|
||||
<tt>define_request</tt> across nested describe blocks, like so:
|
||||
|
||||
describe "POST :create" do
|
||||
def shared_request
|
||||
|
|
@ -100,16 +97,22 @@ request. You can also define a method called <tt>shared_request</tt> to "share a
|
|||
end
|
||||
|
||||
Note: When you're adding longer, more complicated controller specs you can still leverage
|
||||
implicit and shared requests by calling <tt>do_request</tt> in your spec as in the following
|
||||
implicit and explicit requests by calling <tt>do_request</tt> in your spec as in the following
|
||||
example:
|
||||
|
||||
# Let's assume this controller is _not_ CategoriesController
|
||||
# Note this controller is UsersController and _not_ CategoriesController
|
||||
# and that loading the categories isn't part of the default actions
|
||||
describe "GET :index" do
|
||||
# and cannot use the <tt>stub_<i>controller_method</i></tt> helpers
|
||||
# [which create implicit requests based on the controller method in the name]
|
||||
# but uses <tt>stub_find_all</tt> instead
|
||||
describe "GET :new" do
|
||||
before(:each) do
|
||||
@user = stub_new(User)
|
||||
@categories = stub_find_all(Category)
|
||||
end
|
||||
|
||||
# ...
|
||||
|
||||
it "should preload categories" do
|
||||
Category.should_receive(:find).with(:all)
|
||||
do_request
|
||||
|
|
@ -264,4 +267,4 @@ rspec_on_rails_on_crack[http://github.com/technoweenie/rspec_on_rails_on_crack/t
|
|||
Also thanks and props to Hampton Catlin and Nathan Weizenbaum for the lovely and imminently useable
|
||||
Haml and make_resourceful. Also also praises and glory to David Chelimsky and the Rspec crew.
|
||||
|
||||
Also thanks to Don Petersen for his suggestions and fixes.
|
||||
Also thanks to Don Petersen, Nicolas Mérouze, Mikkel Malmberg, and Brandan Lennox for their suggestions and fixes.
|
||||
|
|
@ -33,7 +33,7 @@ def button_to(name, options = {}, html_options = {})
|
|||
|
||||
html_options.merge!("type" => "submit", "value" => name)
|
||||
|
||||
"<form method=\"#{form_method}\" action=\"#{escape_once url}\" class=\"button_to\"><div>" +
|
||||
"<form method=\"#{form_method}\" action=\"#{escape_once url}\" class=\"button-to\"><div>" +
|
||||
method_tag + content_tag("button", name, html_options) + request_token_tag + "</div></form>"
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ class SkinnyScaffoldGenerator < Rails::Generator::NamedBase
|
|||
alias_method :controller_singular_name, :controller_file_name
|
||||
alias_method :controller_table_name, :controller_plural_name
|
||||
|
||||
default_options :skip_migration => false
|
||||
|
||||
def initialize(runtime_args, runtime_options = {})
|
||||
super
|
||||
|
||||
|
|
@ -86,6 +88,13 @@ protected
|
|||
def banner
|
||||
"Usage: #{$0} skinny_scaffold ModelName [field:type, field:type]"
|
||||
end
|
||||
|
||||
def add_options!(opt)
|
||||
opt.separator ''
|
||||
opt.separator 'Options:'
|
||||
opt.on("--skip-migration",
|
||||
"Don't generate a migration file for this model") { |v| options[:skip_migration] = v }
|
||||
end
|
||||
|
||||
def model_name
|
||||
class_name.demodulize
|
||||
|
|
|
|||
|
|
@ -1,29 +1,6 @@
|
|||
require File.dirname(__FILE__) + '/../spec_helper'
|
||||
|
||||
describe <%= controller_class_name %>Controller do
|
||||
def valid_attributes(args = {})
|
||||
{
|
||||
<% if attributes.empty? -%>
|
||||
# Add valid attributes for the your params[:<%= singular_name %>] here!
|
||||
<% else -%>
|
||||
<%- attributes.each_with_index do |attribute, index| -%>
|
||||
<%- case attribute.type -%>
|
||||
<%- when :string, :text -%>
|
||||
"<%= attribute.name %>" => "foo"<%= index < attributes.size - 1 ? "," : "" %>
|
||||
<%- when :integer, :float, :decimal -%>
|
||||
"<%= attribute.name %>" => 815<%= index < attributes.size - 1 ? "," : "" %>
|
||||
<%- when :boolean -%>
|
||||
"<%= attribute.name %>" => false<%= index < attributes.size - 1 ? "," : "" %>
|
||||
<%- when :date, :datetime, :time, :timestamp -%>
|
||||
"<%= attribute.name %>" => 1.week.ago<%= index < attributes.size - 1 ? "," : "" %>
|
||||
<%- else -%>
|
||||
"<%= attribute.name %>" => nil<%= index < attributes.size - 1 ? "," : "" %> # Could not determine valid attribute
|
||||
<%- end -%>
|
||||
<%- end -%>
|
||||
<% end -%>
|
||||
}.merge(args)
|
||||
end
|
||||
|
||||
describe "GET :index" do
|
||||
before(:each) do
|
||||
@<%= plural_name %> = stub_index(<%= class_name %>)
|
||||
|
|
|
|||
|
|
@ -5,11 +5,10 @@ describe "<%= File.join(controller_class_path, controller_singular_name) %>/form
|
|||
@<%= singular_name %> = mock_and_assign(<%= model_name %>, :stub => {
|
||||
<% if attributes.blank? -%>
|
||||
# Add your stub attributes and return values here like:
|
||||
# :name => "Foo", :created_at => 1.week.ago, :updated_at => nil
|
||||
# :name => "Foo", :address => "815 Oceanic Drive"
|
||||
<% else -%>
|
||||
<%- attributes.each_with_index do |attribute, index| -%>
|
||||
<%- case attribute.type -%>
|
||||
<%- when :string, :text -%>
|
||||
<%- case attribute.type when :string, :text -%>
|
||||
:<%= attribute.name %> => "foo"<%= index < attributes.size - 1 ? "," : "" %>
|
||||
<%- when :integer, :float, :decimal -%>
|
||||
:<%= attribute.name %> => 815<%= index < attributes.size - 1 ? "," : "" %>
|
||||
|
|
@ -21,7 +20,7 @@ describe "<%= File.join(controller_class_path, controller_singular_name) %>/form
|
|||
:<%= attribute.name %> => nil<%= index < attributes.size - 1 ? "," : "" %> # Could not determine valid attribute
|
||||
<%- end -%>
|
||||
<%- end -%>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
})
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ require File.dirname(__FILE__) + '<%= '/..' * controller_class_nesting_depth %>/
|
|||
describe "<%= File.join(controller_class_path, controller_singular_name) %>/index.html.<%= template_language %>" do
|
||||
before(:each) do
|
||||
@<%= plural_name %> = mock_and_assign_collection(<%= model_name %>)
|
||||
template.stub_render :partial => @<%= plural_name %>
|
||||
template.stub! :render
|
||||
end
|
||||
|
||||
it "should render :partial => @<%= plural_name %>" do
|
||||
template.expect_render :partial => @<%= plural_name %>
|
||||
template.should_receive(:render).with(:partial => @<%= plural_name %>)
|
||||
do_render
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ describe "<%= File.join(controller_class_path, controller_singular_name) %>/_<%=
|
|||
# :name => "Foo", :created_at => 1.week.ago, :updated_at => nil
|
||||
<% else -%>
|
||||
<%- attributes.each_with_index do |attribute, index| -%>
|
||||
<%- case attribute.type -%>
|
||||
<%- when :string, :text -%>
|
||||
<%- case attribute.type when :string, :text -%>
|
||||
:<%= attribute.name %> => "foo"<%= index < attributes.size - 1 ? "," : "" %>
|
||||
<%- when :integer, :float, :decimal -%>
|
||||
:<%= attribute.name %> => 815<%= index < attributes.size - 1 ? "," : "" %>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ describe <%= class_name %> do
|
|||
end
|
||||
|
||||
after(:each) do
|
||||
@<%= singular_name %>.destroy unless @<%= singular_name %>.new_record?
|
||||
@<%= singular_name %>.destroy
|
||||
end
|
||||
|
||||
# Add your model specs here, please!
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ describe "<%= File.join(controller_class_path, controller_singular_name) %>/show
|
|||
<% else -%>
|
||||
@<%= singular_name %> = mock_and_assign(<%= model_name %>, :stub => {
|
||||
<%- attributes.each_with_index do |attribute, index| -%>
|
||||
<%- case attribute.type -%>
|
||||
<%- when :string, :text -%>
|
||||
<%- case attribute.type when :string, :text -%>
|
||||
:<%= attribute.name %> => "foo"<%= index < attributes.size - 1 ? "," : "" %>
|
||||
<%- when :integer, :float, :decimal -%>
|
||||
:<%= attribute.name %> => 815<%= index < attributes.size - 1 ? "," : "" %>
|
||||
|
|
|
|||
|
|
@ -2,13 +2,24 @@ module LuckySneaks
|
|||
# These methods are mostly just called internally by various other spec helper
|
||||
# methods but you're welcome to use them as needed in your own specs.
|
||||
module CommonSpecHelpers
|
||||
# Stubs out Time.now and returns value to use when comparing it. Example:
|
||||
#
|
||||
# time_now = stub_time_now
|
||||
# @foo.some_method_that_resets_updated_at
|
||||
# @foo.updated_at.should == time_now
|
||||
def stub_time_now
|
||||
returning Time.now do |now|
|
||||
Time.stub!(:now).and_return(now)
|
||||
end
|
||||
end
|
||||
|
||||
# Returns class for the specified name. Example:
|
||||
#
|
||||
# class_for("foo") # => Foo
|
||||
def class_for(name)
|
||||
name.to_s.constantize
|
||||
rescue NameError
|
||||
name.to_s.classify.constantize
|
||||
name.to_s.pluralize.classify.constantize
|
||||
# Let any other error rise!
|
||||
end
|
||||
|
||||
|
|
@ -42,5 +53,31 @@ module LuckySneaks
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Returns class description text
|
||||
def class_description_text
|
||||
if self.class.respond_to?(:description_text)
|
||||
# Old school
|
||||
self.class.description_text
|
||||
else
|
||||
# New school
|
||||
self.class.description
|
||||
end
|
||||
end
|
||||
|
||||
# Returns description text
|
||||
def self_description_text
|
||||
if respond_to?(:description_text)
|
||||
# Old school
|
||||
description_text
|
||||
else
|
||||
# New school
|
||||
description
|
||||
end
|
||||
end
|
||||
|
||||
def described_type
|
||||
self.class.described_type
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ module LuckySneaks
|
|||
alias do_request eval_request
|
||||
|
||||
def try_shared_request_definition
|
||||
shared_request
|
||||
rescue NameError
|
||||
if @implicit_request
|
||||
if defined?(shared_request) == "method"
|
||||
shared_request
|
||||
elsif @implicit_request
|
||||
try_implicit_request
|
||||
else
|
||||
error_message = "Could not determine request definition for 'describe' context. "
|
||||
|
|
@ -64,4 +64,4 @@ module LuckySneaks
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -41,28 +41,23 @@ module LuckySneaks
|
|||
private
|
||||
def create_ar_class_expectation(name, method, argument = nil, options = {})
|
||||
args = []
|
||||
if [:create, :update].include?(@controller_method)
|
||||
args << (argument.nil? ? valid_attributes : argument)
|
||||
else
|
||||
unless options.delete(:only_method)
|
||||
args << argument unless argument.nil?
|
||||
args << hash_including(options) unless options.empty?
|
||||
end
|
||||
args << options unless options.empty?
|
||||
method = options.delete(:find_method) if options[:find_method]
|
||||
if args.empty?
|
||||
return_value = class_for(name).send(method)
|
||||
class_for(name).should_receive(method).and_return(return_value)
|
||||
class_for(name).should_receive(method).and_return(instance_for(name))
|
||||
else
|
||||
return_value = class_for(name).send(method, *args)
|
||||
class_for(name).should_receive(method).with(*args).and_return(return_value)
|
||||
class_for(name).should_receive(method).with(*args).and_return(instance_for(name))
|
||||
end
|
||||
end
|
||||
|
||||
def create_positive_ar_instance_expectation(name, method, *args)
|
||||
instance = instance_for(name)
|
||||
if args.empty?
|
||||
return_value = instance.send(method)
|
||||
instance.should_receive(method).and_return(true)
|
||||
else
|
||||
return_value = instance.send(method, *args)
|
||||
instance.should_receive(method).with(*args).and_return(true)
|
||||
end
|
||||
end
|
||||
|
|
@ -73,12 +68,14 @@ module LuckySneaks
|
|||
# Creates an expectation that the controller method calls <tt>ActiveRecord::Base.find</tt>.
|
||||
# Examples:
|
||||
#
|
||||
# it_should_find :foos # => Foo.should_receive(:find).with(:all)
|
||||
# it_should_find :foos, :all # An explicit version of the above
|
||||
# it_should_find :foos, :conditions => {:foo => "bar"} # => Foo.should_receive(:find).with(:all, :conditions => {"foo" => "bar"}
|
||||
# it_should_find :foo # => Foo.should_recieve(:find).with(@foo.id.to_s)
|
||||
# it_should_find :foo, :params => "id" # => Foo.should_receive(:find).with(params[:id].to_s)
|
||||
# it_should_find :foo, 2 # => Foo.should_receive(:find).with("2")
|
||||
# it_should_find :foos # => Foo.should_receive(:find).with(:all)
|
||||
# it_should_find :foos, :all # An explicit version of the above
|
||||
# it_should_find :foos, :conditions => {:foo => "bar"} # => Foo.should_receive(:find).with(:all, :conditions => {"foo" => "bar"}
|
||||
# it_should_find :foos, "joe", :method => :find_all_by_name # Foo.should_receive(:find_all_by_name).with("joe")
|
||||
# it_should_find :foo # => Foo.should_recieve(:find).with(@foo.id.to_s)
|
||||
# it_should_find :foo, :params => "id" # => Foo.should_receive(:find).with(params[:id].to_s)
|
||||
# it_should_find :foo, 2 # => Foo.should_receive(:find).with("2")
|
||||
# it_should_find :foo, "joe", :method => :find_by_name # => Foo.should_recieve(:find_by_name).with("joe")
|
||||
#
|
||||
# <b>Note:</b> All params (key and value) will be strings if they come from a form element and are handled
|
||||
# internally with this expectation.
|
||||
|
|
@ -103,7 +100,27 @@ module LuckySneaks
|
|||
:all
|
||||
end
|
||||
end
|
||||
create_ar_class_expectation name, :find, argument, options
|
||||
find_method = options.delete(:method) || :find
|
||||
create_ar_class_expectation name, find_method, argument, options
|
||||
eval_request
|
||||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_find</tt>. This creates an expectation that
|
||||
# the class never receives <tt>find</tt> at all.
|
||||
def it_should_not_find(name)
|
||||
name_string = name.to_s
|
||||
name_message = if name_string == name_string.singularize
|
||||
"a #{name}"
|
||||
else
|
||||
name
|
||||
end
|
||||
it "should not find #{name_message}" do
|
||||
if name_string == name_string.singularize
|
||||
class_for(name).should_not_receive(:find)
|
||||
else
|
||||
class_for(name).should_not_receive(:find).with(:all)
|
||||
end
|
||||
eval_request
|
||||
end
|
||||
end
|
||||
|
|
@ -121,6 +138,15 @@ module LuckySneaks
|
|||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_initialize</tt>. This creates an expectation
|
||||
# that the class never recieves <tt>new</tt> at all.
|
||||
def it_should_not_initialize(name)
|
||||
it "should initialize a #{name}" do
|
||||
class_for(name).should_not_receive(:new)
|
||||
eval_request
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that the controller method calls <tt>ActiveRecord::Base#save</tt> on the
|
||||
# named instance. Example:
|
||||
#
|
||||
|
|
@ -136,6 +162,15 @@ module LuckySneaks
|
|||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_update</tt>. This creates an expectation
|
||||
# that the instance never receives <tt>save</tt> at all.
|
||||
def it_should_not_save(name)
|
||||
it "should not save the #{name}" do
|
||||
instance_for(name).should_not_receive(:save)
|
||||
eval_request
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that the controller method calls <tt>ActiveRecord::Base#update_attributes</tt>
|
||||
# on the named instance. Takes optional argument for <tt>params</tt> to specify in the
|
||||
# expectation. Examples:
|
||||
|
|
@ -148,7 +183,16 @@ module LuckySneaks
|
|||
# for the inevitable re-rendering of the form template.
|
||||
def it_should_update(name, options = {})
|
||||
it "should update the #{name}" do
|
||||
create_positive_ar_instance_expectation name, :update_attributes, params[options[:params]]
|
||||
create_positive_ar_instance_expectation name, :update_attributes, params[name]
|
||||
eval_request
|
||||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_update</tt>. This creates an expectation
|
||||
# that the instance never receives <tt>update_attributes</tt> at all.
|
||||
def it_should_not_update(name)
|
||||
it "should not update the #{name}" do
|
||||
instance_for(name).should_not_receive(:update_attributes)
|
||||
eval_request
|
||||
end
|
||||
end
|
||||
|
|
@ -168,6 +212,15 @@ module LuckySneaks
|
|||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_destroy</tt>. This creates an expectation
|
||||
# that the instance never receives <tt>destroy</tt> at all.
|
||||
def it_should_not_destroy(name)
|
||||
it "should not destroy the #{name}" do
|
||||
instance_for(name).should_not_receive(:destroy)
|
||||
eval_request
|
||||
end
|
||||
end
|
||||
|
||||
# Creates expectation[s] that the controller method should assign the specified
|
||||
# instance variables along with any specified values. Examples:
|
||||
#
|
||||
|
|
@ -192,16 +245,36 @@ module LuckySneaks
|
|||
end
|
||||
end
|
||||
|
||||
# Essentially shorthand for <tt>it_should_assign name => :nil</tt>. This method can take multiple
|
||||
# instance variable names, creating this shorthand for each name. See the docs for
|
||||
# <tt>it_should_assign</tt> for more information.
|
||||
def it_should_not_assign(*names)
|
||||
names.each do |name|
|
||||
# Assuming name is a symbol
|
||||
it_should_assign name => :nil
|
||||
end
|
||||
end
|
||||
|
||||
# Wraps the separate expectations <tt>it_should_find</tt> and <tt>it_should_assign</tt>
|
||||
# for simple cases. If you need more control over the parameters of the find, this
|
||||
# isn't the right helper method and you should write out the two expectations separately.
|
||||
def it_should_find_and_assign(*names)
|
||||
names.each do |name|
|
||||
it_should_find name
|
||||
it_should_find name, :only_method => true
|
||||
it_should_assign name
|
||||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_find_and_assign</tt>. This creates an
|
||||
# expectation that the class never receives <tt>find</tt> at all and that
|
||||
# no matching instance variable is ever created.
|
||||
def it_should_not_find_and_assign(*names)
|
||||
names.each do |name|
|
||||
it_should_not_find name
|
||||
it_should_assign name => :nil
|
||||
end
|
||||
end
|
||||
|
||||
# Wraps the separate expectations <tt>it_should_initialize</tt> and <tt>it_should_assign</tt>
|
||||
# for simple cases. If you need more control over the parameters of the initialization, this
|
||||
# isn't the right helper method and you should write out the two expectations separately.
|
||||
|
|
@ -212,11 +285,21 @@ module LuckySneaks
|
|||
# please use <tt>it_should_initialize_and_save</tt>.
|
||||
def it_should_initialize_and_assign(*names)
|
||||
names.each do |name|
|
||||
it_should_initialize name
|
||||
it_should_initialize name, :only_method => true
|
||||
it_should_assign name
|
||||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_initialize_and_assign</tt>. This creates an
|
||||
# expectation that the class never receives <tt>new</tt> at all and that
|
||||
# no matching instance variable is ever created.
|
||||
def it_should_not_initialize_and_assign(*names)
|
||||
names.each do |name|
|
||||
it_should_not_initialize name
|
||||
it_should_assign name => :nil
|
||||
end
|
||||
end
|
||||
|
||||
# Wraps the separate expectations <tt>it_should_initialize</tt> and <tt>it_should_save</tt>
|
||||
# for simple cases. If you need more control over the parameters of the initialization, this
|
||||
# isn't the right helper method and you should write out the two expectations separately.
|
||||
|
|
@ -226,7 +309,7 @@ module LuckySneaks
|
|||
# but not saved, just use <tt>it_should_initialize_and_assign</tt>.
|
||||
def it_should_initialize_and_save(*names)
|
||||
names.each do |name|
|
||||
it_should_initialize name
|
||||
it_should_initialize name, :only_method => true
|
||||
it_should_save name
|
||||
end
|
||||
end
|
||||
|
|
@ -240,7 +323,7 @@ module LuckySneaks
|
|||
# instance is found but not saved, just use <tt>it_should_find_and_assign</tt>.
|
||||
def it_should_find_and_update(*names)
|
||||
names.each do |name|
|
||||
it_should_find name
|
||||
it_should_find name, :only_method => true
|
||||
it_should_update name
|
||||
end
|
||||
end
|
||||
|
|
@ -250,16 +333,16 @@ module LuckySneaks
|
|||
# isn't the right helper method and you should write out the two expectations separately.
|
||||
def it_should_find_and_destroy(*names)
|
||||
names.each do |name|
|
||||
it_should_find name
|
||||
it_should_find name, :only_method => true
|
||||
it_should_destroy name
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that the specified collection (<tt>flash</tt> or <tt>session</tt>)
|
||||
# contains the specified key and value. To specify that the collection should be set
|
||||
# to <tt>nil</tt>, specify the value as :nil instead.
|
||||
# Creates an expectation that the specified collection (<tt>flash</tt>, <tt>session</tt>,
|
||||
# <tt>params</tt>, <tt>cookies</tt>) contains the specified key and value. To specify that
|
||||
# the collection should be set to <tt>nil</tt>, specify the value as :nil instead.
|
||||
def it_should_set(collection, key, value = nil, &block)
|
||||
it "should set #{collection}[:#{key}]" do
|
||||
it "should set #{collection}[:#{key}]#{' with ' + value.inspect if value}" do
|
||||
# Allow flash.now[:foo] to remain in the flash
|
||||
flash.stub!(:sweep) if collection == :flash
|
||||
eval_request
|
||||
|
|
@ -270,7 +353,7 @@ module LuckySneaks
|
|||
self.send(collection)[key].should == value
|
||||
end
|
||||
elsif block_given?
|
||||
self.send(collection)[key].should == block.call
|
||||
self.send(collection)[key].should == instance_eval(&block)
|
||||
else
|
||||
self.send(collection)[key].should_not be_nil
|
||||
end
|
||||
|
|
@ -282,6 +365,11 @@ module LuckySneaks
|
|||
def it_should_set_flash(name, value = nil, &block)
|
||||
it_should_set :flash, name, value, &block
|
||||
end
|
||||
|
||||
# Wraps <tt>it_should_set :flash, :nil</tt>.
|
||||
def it_should_not_set_flash(name)
|
||||
it_should_set :flash, name, :nil
|
||||
end
|
||||
|
||||
# Wraps <tt>it_should_set :session</tt>. To specify that the collection should be set
|
||||
# to <tt>nil</tt>, specify the value as :nil instead.
|
||||
|
|
@ -289,6 +377,33 @@ module LuckySneaks
|
|||
it_should_set :session, name, value, &block
|
||||
end
|
||||
|
||||
# Wraps <tt>it_should_set :session, :nil</tt>.
|
||||
def it_should_not_set_session(name)
|
||||
it_should_set :session, name, :nil
|
||||
end
|
||||
|
||||
# Wraps <tt>it_should_set :params</tt>. To specify that the collection should be set
|
||||
# to <tt>nil</tt>, specify the value as :nil instead.
|
||||
def it_should_set_params(name, value = nil, &block)
|
||||
it_should_set :params, name, value, &block
|
||||
end
|
||||
|
||||
# Wraps <tt>it_should_set :params, :nil</tt>.
|
||||
def it_should_not_set_params(name)
|
||||
it_should_set :params, name, :nil
|
||||
end
|
||||
|
||||
# Wraps <tt>it_should_set :cookies</tt>. To specify that the collection should be set
|
||||
# to <tt>nil</tt>, specify the value as :nil instead.
|
||||
def it_should_set_cookies(name, value = nil, &block)
|
||||
it_should_set :cookies, name, value, &block
|
||||
end
|
||||
|
||||
# Wraps <tt>it_should_set :cookies, :nil</tt>.
|
||||
def it_should_not_set_cookies(name)
|
||||
it_should_set :cookies, name, :nil
|
||||
end
|
||||
|
||||
# Wraps the various <tt>it_should_render_<i>foo</i></tt> methods:
|
||||
# <tt>it_should_render_template</tt>, <tt>it_should_render_partial</tt>,
|
||||
# <tt>it_should_render_xml</tt>, <tt>it_should_render_json</tt>,
|
||||
|
|
@ -407,6 +522,27 @@ module LuckySneaks
|
|||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_redirect_to</tt>.
|
||||
def it_should_not_redirect_to(hint = nil, &route)
|
||||
if hint.nil? && route.respond_to?(:to_ruby)
|
||||
hint = route.to_ruby.gsub(/(^proc \{)|(\}$)/, '').strip
|
||||
end
|
||||
it "should not redirect to #{(hint || route)}" do
|
||||
eval_request
|
||||
response.should_not redirect_to(instance_eval(&route))
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that the controller method redirects back to the previous page
|
||||
def it_should_redirect_to_referer
|
||||
it "should redirect to the referring page" do
|
||||
request.env["HTTP_REFERER"] = "http://test.host/referer"
|
||||
eval_request
|
||||
response.should redirect_to("http://test.host/referer")
|
||||
end
|
||||
end
|
||||
alias it_should_redirect_to_referrer it_should_redirect_to_referer
|
||||
|
||||
private
|
||||
def it_should_assign_instance_variable(name, value)
|
||||
expectation_proc = case value
|
||||
|
|
|
|||
|
|
@ -6,26 +6,13 @@ module LuckySneaks # :nodoc:
|
|||
# file even more. You are encouraged to use these methods to setup the basic calls for your
|
||||
# resources and only resort to the other methods when mocking and stubbing secondary objects
|
||||
# and calls.
|
||||
#
|
||||
# Both <tt>stub_create</tt> and <tt>stub_update</tt> benefit from having a <tt>valid_attributes</tt>
|
||||
# method defined at the top level of your example groups, ie the top-most "describe" block
|
||||
# of the spec file. If you did not generate your specs with <tt>skinny_scaffold</tt> or
|
||||
# <tt>skinny_resourceful</tt> generators, you can simply write a method like the following
|
||||
# for yourself:
|
||||
#
|
||||
# def valid_attributes
|
||||
# {
|
||||
# "foo" => "bar",
|
||||
# "baz" => "quux"
|
||||
# }
|
||||
# end
|
||||
#
|
||||
# Note this method employs strings as both the key and values to best replicate the way
|
||||
# they are used in actual controllers where the params will come from a form.
|
||||
module ControllerStubHelpers
|
||||
# Stubs out <tt>find :all</tt> and returns a collection of <tt>mock_model</tt>
|
||||
# instances of that class. Accepts the following options:
|
||||
#
|
||||
# <b>:find_method</b>:: Method to use as finder call. Default is <tt>:find</tt>.
|
||||
# <b>Note:</b> When specifying the method, the call is stubbed
|
||||
# to accept any arguments. Caveat programmer.
|
||||
# <b>:format</b>:: Format of the request. Used to only add <tt>to_xml</tt> and
|
||||
# <tt>to_json</tt> when actually needed.
|
||||
# <b>:size</b>:: Number of instances to return in the result. Default is 3.
|
||||
|
|
@ -40,10 +27,13 @@ module LuckySneaks # :nodoc:
|
|||
stub_formatted collection, format
|
||||
params[:format] = format
|
||||
end
|
||||
if options.empty?
|
||||
klass.stub!(:find).with(:all).and_return(collection)
|
||||
if find_method = options[:find_method]
|
||||
# Not stubbing specific arguments here
|
||||
# If you need more specificity, write a custom example
|
||||
klass.stub!(find_method).and_return(collection)
|
||||
else
|
||||
klass.stub!(:find).with(:all, options).and_return(collection)
|
||||
klass.stub!(:find).with(:all).and_return(collection)
|
||||
klass.stub!(:find).with(:all, hash_including(options)).and_return(collection)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -71,9 +61,11 @@ module LuckySneaks # :nodoc:
|
|||
params[:format] = format
|
||||
end
|
||||
klass.stub!(:new).and_return(member)
|
||||
if options[:params]
|
||||
klass.stub!(:new).with(hash_including(options[:params])).and_return(member)
|
||||
end
|
||||
if options[:stub_save]
|
||||
stub_ar_method member, :save, options[:return]
|
||||
klass.stub!(:new).with(params[options[:params]]).and_return(member)
|
||||
else
|
||||
member.stub!(:new_record?).and_return(true)
|
||||
member.stub!(:id).and_return(nil)
|
||||
|
|
@ -89,32 +81,25 @@ module LuckySneaks # :nodoc:
|
|||
|
||||
# Alias for <tt>stub_initialize</tt> which additionally defines an implicit request <tt>post :create</tt>.
|
||||
#
|
||||
# <b>Note:</b> If <tt>stub_create<tt> is provided an optional <tt>:params</tt> hash
|
||||
# or the method <tt>valid_attributes</tt> is defined within its scope,
|
||||
# those params will be added to the example's <tt>params</tt> object. If <i>neither</i>
|
||||
# are provided an <tt>ArgumentError</tt> will be raised.
|
||||
# <b>Note:</b> If <tt>stub_create<tt> is provided an optional <tt>:params</tt> hash,
|
||||
# those params will be added to the example's <tt>params</tt> object.
|
||||
def stub_create(klass, options = {})
|
||||
define_implicit_request :create
|
||||
if options[:params].nil?
|
||||
if self.respond_to?(:valid_attributes)
|
||||
params[klass.name.underscore.to_sym] = valid_attributes
|
||||
options[:params] = valid_attributes
|
||||
else
|
||||
error_message = "Params for creating #{klass} could not be determined. "
|
||||
error_message << "Please define valid_attributes method in the base 'describe' block "
|
||||
error_message << "or manually set params in the before block."
|
||||
raise ArgumentError, error_message
|
||||
end
|
||||
end
|
||||
class_name = klass.name.underscore
|
||||
options[:params] ||= params[class_name]
|
||||
stub_initialize klass, options.merge(:stub_save => true)
|
||||
end
|
||||
|
||||
# Stubs out <tt>find</tt> and returns a single <tt>mock_model</tt>
|
||||
# instances of that class. Accepts the following options:
|
||||
#
|
||||
# <b>:format</b>:: Format of the request. Used to only add <tt>to_xml</tt> and
|
||||
# <tt>to_json</tt> when actually needed.
|
||||
# <b>:stub</b>:: Additional methods to stub on the instances
|
||||
# <b>:find_method</b>:: Method to use as finder call. Default is <tt>:find</tt>.
|
||||
# <b>:format</b>:: Format of the request. Used to only add <tt>to_xml</tt> and
|
||||
# <tt>to_json</tt> when actually needed.
|
||||
# <b>:stub</b>:: Additional methods to stub on the instances
|
||||
# <b>:current_object</b>:: If set to true, <tt>find</tt> will set <tt>params[:id]</tt>
|
||||
# using the <tt>id</tt> of the <tt>mock_model</tt> instance
|
||||
# and use that value as an argument when stubbing <tt>find</tt>
|
||||
#
|
||||
# Any additional options will be passed as arguments to <tt>find</tt>.You will want
|
||||
# to make sure to pass those arguments to the <tt>it_should_find</tt> spec as well.
|
||||
|
|
@ -125,17 +110,55 @@ module LuckySneaks # :nodoc:
|
|||
def stub_find_one(klass, options = {})
|
||||
returning mock_model(klass) do |member|
|
||||
stub_out member, options.delete(:stub)
|
||||
if options[:format]
|
||||
stub_formatted member, options[:format]
|
||||
params[:format] = options[:format]
|
||||
if format = options.delete(:format)
|
||||
stub_formatted member, format
|
||||
params[:format] = format
|
||||
end
|
||||
if options[:current_object]
|
||||
if options.delete(:current_object)
|
||||
params[:id] = member.id
|
||||
if options[:stub_ar]
|
||||
stub_ar_method member, options[:stub_ar], options[:return]
|
||||
if ar_stub = options.delete(:stub_ar)
|
||||
stub_ar_method member, ar_stub, options.delete(:return), options.delete(:update_params)
|
||||
end
|
||||
end
|
||||
klass.stub!(:find).with(member.id.to_s).and_return(member)
|
||||
if find_method = options.delete(:find_method)
|
||||
klass.stub!(find_method).and_return(member)
|
||||
else
|
||||
# Stubbing string and non-string just to be safe
|
||||
klass.stub!(:find).with(member.id).and_return(member)
|
||||
klass.stub!(:find).with(member.id.to_s).and_return(member)
|
||||
unless options.empty?
|
||||
klass.stub!(:find).with(member.id, hash_including(options)).and_return(member)
|
||||
klass.stub!(:find).with(member.id.to_s, hash_including(options)).and_return(member)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# <b>Note:</b> Use of this method with :child options (to mock
|
||||
# association) is deprecated. Please use <tt>stub_association</tt>.
|
||||
#
|
||||
# Same as <tt>stub_find_one</tt> but setups the instance as the parent
|
||||
# of the specified association. Example:
|
||||
#
|
||||
# stub_parent(Document, :child => :comments)
|
||||
#
|
||||
# This stubs <tt>Document.find</tt>, <tt>@document.comments</tt> (which
|
||||
# will return <tt>Comment</tt> class), as well as <tt>params[:document_id]</tt>.
|
||||
# This method is meant to be used in the controller for the specified child
|
||||
# (<tt>CommentsController</tt> in this instance) in situations like:
|
||||
#
|
||||
# def index
|
||||
# @document = Document.find(params[:document_id])
|
||||
# @comments = @document.comments.find(:all)
|
||||
# end
|
||||
def stub_parent(klass, options = {})
|
||||
returning stub_find_one(klass, options) do |member|
|
||||
params[klass.name.foreign_key] = member.id
|
||||
if offspring = options.delete(:child)
|
||||
puts "stub_parent with :child option has been marked for deprecation"
|
||||
puts "please use stub_association to create the mock instead"
|
||||
member.stub!(offspring).and_return(class_for(offspring))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -154,10 +177,8 @@ module LuckySneaks # :nodoc:
|
|||
# Alias for <tt>stub_find_one</tt> which additionally defines an implicit request <tt>put :update</tt>
|
||||
# and stubs out the <tt>update_attribute</tt> method on the instance as well.
|
||||
#
|
||||
# <b>Note:</b> If <tt>stub_update<tt> is provided an optional <tt>:params</tt> hash
|
||||
# or the method <tt>valid_attributes</tt> is defined within its scope,
|
||||
# those params will be added to the example's <tt>params</tt> object. If <i>neither</i>
|
||||
# are provided an <tt>ArgumentError</tt> will be raised.
|
||||
# <b>Note:</b> If <tt>stub_update<tt> is provided an optional <tt>:params</tt> hash,
|
||||
# those params will be added to the example's <tt>params</tt> object.
|
||||
def stub_update(klass, options = {})
|
||||
define_implicit_request :update
|
||||
stub_find_one klass, options.merge(:current_object => true, :stub_ar => :update_attributes)
|
||||
|
|
@ -176,6 +197,20 @@ module LuckySneaks # :nodoc:
|
|||
object.stub!("to_#{format}").and_return("#{object.class} formatted as #{format}")
|
||||
end
|
||||
|
||||
# Creates a mock object representing an association proxy, stubs the appropriate
|
||||
# method on the parent object and returns that association proxy.
|
||||
# Accepts the following option:
|
||||
#
|
||||
# <b>:stub</b>:: Additional methods to stub on the mock proxy object
|
||||
def stub_association(object, association, options = {})
|
||||
# I know options isn't implemented anywhere
|
||||
object_name = instance_variables.select{|name| instance_variable_get(name) == object}
|
||||
returning mock("Association proxy for #{object_name}.#{association}") do |proxy|
|
||||
stub_out proxy, options[:stub] if options[:stub]
|
||||
object.stub!(association).and_return(proxy)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
# Stubs out multiple methods. You shouldn't be calling this yourself and if you do
|
||||
# you should be able to understand the code yourself, right?
|
||||
|
|
@ -192,8 +227,12 @@ module LuckySneaks # :nodoc:
|
|||
|
||||
# Stubs out ActiveRecord::Base methods like #save, #update_attributes, etc
|
||||
# that may be called on a found or instantiated mock_model instance.
|
||||
def stub_ar_method(object, method, return_value)
|
||||
object.stub!(method).and_return(return_value ? false : true)
|
||||
def stub_ar_method(object, method, return_value, params = {})
|
||||
if params.blank?
|
||||
object.stub!(method).and_return(return_value ? false : true)
|
||||
else
|
||||
object.stub!(method).with(hash_including(params)).and_return(return_value ? false : true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,25 +6,51 @@ module LuckySneaks
|
|||
# to make your model specs a little more DRY. You might also be interested
|
||||
# in checking out the example block [read: "describe"] level versions in of these
|
||||
# methods which can DRY things up even more:
|
||||
# LuckySneaks::ModelSpecHelpers::ExampleGroupLevelMethods
|
||||
# LuckySneaks::ModelSpecHelpers::ExampleGroupLevelMethods.
|
||||
#
|
||||
# <b>Note:</b> The validation matchers are only meant to be used for simple validation checking
|
||||
# not as a one-size-fits-all solution.
|
||||
# Also check out the methods in LuckySneaks::ModelSpecHelpers::AssociationMatcher
|
||||
# for some helpful matcher helper methods to use with these methods if you want to spec
|
||||
# options on your association setups.
|
||||
module ModelSpecHelpers
|
||||
include LuckySneaks::CommonSpecHelpers
|
||||
|
||||
def self.included(base) # :nodoc:
|
||||
base.extend ExampleGroupLevelMethods
|
||||
end
|
||||
|
||||
class AssociationMatcher # :nodoc:
|
||||
def initialize(associated, macro)
|
||||
|
||||
# These methods cannot be used alone but are used in compliment with the association
|
||||
# matchers in LuckySneaks::ModelSpecHelpers like <tt>have_many</tt>. Example:
|
||||
#
|
||||
# describe User do
|
||||
# it "should have many memberships" do
|
||||
# User.should have_many(:memberships)
|
||||
# end
|
||||
#
|
||||
# it "should have many sites through memberships" do
|
||||
# User.should have_many(:sites).through(:memberships)
|
||||
# end
|
||||
#
|
||||
# it "should belong to a manager" do
|
||||
# User.should belong_to(:manager).with_counter_cache
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# <b>Note:</b> To spec these sorts of options using the example block helpers like
|
||||
# <tt>it_should_have_many</tt>, just add them as options directly. This will use
|
||||
# <tt>with_options</tt> rather than any specific matcher helpers but will have the same
|
||||
# effects. Example:
|
||||
#
|
||||
# describe User do
|
||||
# it_should_have_many :sites, :through => :memberships
|
||||
# end
|
||||
class AssociationMatcher
|
||||
def initialize(associated, macro) # :nodoc:
|
||||
@associated = associated
|
||||
@macro = macro
|
||||
@options = {}
|
||||
end
|
||||
|
||||
def matches?(main_model)
|
||||
def matches?(main_model) # :nodoc:
|
||||
unless main_model.respond_to?(:reflect_on_association)
|
||||
if main_model.class.respond_to?(:reflect_on_association)
|
||||
main_model = main_model.class
|
||||
|
|
@ -39,7 +65,7 @@ module LuckySneaks
|
|||
end
|
||||
end
|
||||
|
||||
def failure_message
|
||||
def failure_message # :nodoc:
|
||||
if @not_model
|
||||
" expected: #{@not_model} to be a subclass of ActiveRecord::Base class, but was not"
|
||||
elsif @association
|
||||
|
|
@ -49,7 +75,7 @@ module LuckySneaks
|
|||
end
|
||||
end
|
||||
|
||||
def negative_failure_message
|
||||
def negative_failure_message # :nodoc:
|
||||
if @association
|
||||
" expected: #{association_with(@options)}\n got: #{association_with(@association.options)}"
|
||||
else
|
||||
|
|
@ -77,7 +103,7 @@ module LuckySneaks
|
|||
self
|
||||
end
|
||||
|
||||
def with_counter_cache(counter_cache = false)
|
||||
def with_counter_cache(counter_cache = true)
|
||||
if counter_cache
|
||||
@options[:counter_cache] = counter_cache
|
||||
end
|
||||
|
|
@ -169,86 +195,208 @@ module LuckySneaks
|
|||
|
||||
private
|
||||
def class_or_instance
|
||||
@model_spec_class_or_instance ||= class_for(self.class.description_text) || instance
|
||||
@model_spec_class_or_instance ||= class_for(described_type) || instance
|
||||
end
|
||||
|
||||
def instance
|
||||
@model_spec_instance ||= instance_for(self.class.description_text)
|
||||
@model_spec_instance ||= instance_for(described_type)
|
||||
end
|
||||
|
||||
# These methods are designed to be used at the example group [read: "describe"] level
|
||||
# to simplify and DRY up common expectations. Most of these methods are wrappers for
|
||||
# to simplify and DRY up common expectations. Some of these methods are wrappers for
|
||||
# matchers which can also be used on the example level [read: within an "it" block]. See
|
||||
# LuckySneaks::ModelSpecHelpers for more information.
|
||||
#
|
||||
# <b>Note:</b> The validation matchers are only meant to be used for simple validation checking
|
||||
# not as a one-size-fits-all solution.
|
||||
module ExampleGroupLevelMethods
|
||||
# Creates an expectation that the current model being spec'd has a <tt>belongs_to</tt>
|
||||
# association with the specified model.
|
||||
# Creates an expectation that the current model being spec'd has a <tt>belong_to</tt>
|
||||
# association with the specified model. Accepts optional arguments which are appended to
|
||||
# the <tt>belong_to</tt> spec like this:
|
||||
#
|
||||
# it_should_belong_to :document, :counter_cache => true
|
||||
#
|
||||
# which is the same as writing out:
|
||||
#
|
||||
# it "should belong to document" do
|
||||
# Comment.should belong_to(:document).with_options(:counter_cache => true)
|
||||
# end
|
||||
#
|
||||
# If you want a more detailed spec description text, feel free to write this out in the long
|
||||
# form and use <tt>belong_to</tt> and its related matcher helpers.
|
||||
#
|
||||
# <b>Note:</b> The argument should be a symbol as in the model's association definition
|
||||
# and not the model's class name.
|
||||
def it_should_belong_to(model)
|
||||
def it_should_belong_to(model, options = {})
|
||||
it "should belong to a #{model}" do
|
||||
class_or_instance.should belong_to(model)
|
||||
if options.empty?
|
||||
class_or_instance.should belong_to(model)
|
||||
else
|
||||
class_or_instance.should belong_to(model).with_options(options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that the current model being spec'd has a <tt>have_one</tt>
|
||||
# association with the specified model.
|
||||
# association with the specified model. Accepts optional arguments which are appended to
|
||||
# the <tt>have_one</tt> spec like this:
|
||||
#
|
||||
# it_should_have_one :last_comment, :class_name => "Comment", :order => "created_at DESC"
|
||||
#
|
||||
# which is the same as writing out:
|
||||
#
|
||||
# it "should have one document" do
|
||||
# Document.should have_one(:last_comment).with_options(:class_name => "Comment", :order => "created_at DESC")
|
||||
# end
|
||||
#
|
||||
# If you want a more detailed spec description text, feel free to write this out in the long
|
||||
# form and use <tt>have_one</tt> and its related matcher helpers.
|
||||
#
|
||||
# <b>Note:</b> The argument should be a symbol as in the model's association definition
|
||||
# and not the model's class name.
|
||||
def it_should_have_one(model)
|
||||
def it_should_have_one(model, options = {})
|
||||
it "should have one #{model}" do
|
||||
class_or_instance.should have_one(model)
|
||||
if options.empty?
|
||||
class_or_instance.should have_one(model)
|
||||
else
|
||||
class_or_instance.should have_one(model).with_options(options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that the current model being spec'd has a <tt>have_many</tt>
|
||||
# association with the specified model.
|
||||
# association with the specified model. Accepts optional arguments which are appended to
|
||||
# the <tt>have_many</tt> spec like this:
|
||||
#
|
||||
# it_should_have_many :memberships, :through => :sites
|
||||
#
|
||||
# which is the same as writing out:
|
||||
#
|
||||
# it "should have many memberships" do
|
||||
# User.should have_many(:memberships).with_options(:through => :sites)
|
||||
# end
|
||||
#
|
||||
# If you want a more detailed spec description text, feel free to write this out in the long
|
||||
# form and use <tt>have_many</tt> and its related matcher helpers.
|
||||
#
|
||||
# <b>Note:</b> The argument should be a symbol as in the model's association definition
|
||||
# and not the model's class name.
|
||||
def it_should_have_many(models)
|
||||
def it_should_have_many(models, options = {})
|
||||
it "should have many #{models}" do
|
||||
class_or_instance.should have_many(models)
|
||||
if options.empty?
|
||||
class_or_instance.should have_many(models)
|
||||
else
|
||||
class_or_instance.should have_many(models).with_options(options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that the current model being spec'd has a <tt>have_and_belong_to_many</tt>
|
||||
# association with the specified model.
|
||||
# association with the specified model. Accepts optional arguments which are appended to
|
||||
# the <tt>have_and_belong_to_many</tt> spec like this:
|
||||
#
|
||||
# it_should_have_and_belong_to_many :documents, :include => :attachments
|
||||
#
|
||||
# which is the same as writing out:
|
||||
#
|
||||
# it "should belong to document" do
|
||||
# User.should have_and_belong_to_many(:documents).with_options(:include => :attachments)
|
||||
# end
|
||||
#
|
||||
# If you want a more detailed spec description text, feel free to write this out in the long
|
||||
# form and use <tt>have_and_belong_to_many</tt> and its related matcher helpers.
|
||||
#
|
||||
# <b>Note:</b> The argument should be a symbol as in the model's association definition
|
||||
# and not the model's class name.
|
||||
def it_should_have_and_belong_to_many(models)
|
||||
def it_should_have_and_belong_to_many(models, options = {})
|
||||
it "should have and belong to many #{models}" do
|
||||
class_or_instance.should have_and_belong_to_many(models)
|
||||
if options.empty?
|
||||
class_or_instance.should have_and_belong_to_many(models)
|
||||
else
|
||||
class_or_instance.should have_and_belong_to_many(models).with_options(options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that new instances of the model being spec'd
|
||||
# should initialise the specified attributes with a default value.
|
||||
#
|
||||
# it_should_default_attributes :status => 'new'
|
||||
#
|
||||
def it_should_default_attributes(hash_attribute_values)
|
||||
hash_attribute_values.each_pair do |a,v|
|
||||
it "should default #{a} attribute to #{v}" do
|
||||
class_or_instance.new.send(a).should == v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that the current model being spec'd <tt>validates_presence_of</tt>
|
||||
# the specified attribute. Takes an optional custom message to match the one in the model's
|
||||
# validation.
|
||||
def it_should_validate_presence_of(attribute, message = I18n.translate('activerecord.errors.messages')[:blank])
|
||||
def it_should_validate_presence_of(attribute, message = default_error_message(:blank))
|
||||
it "should not be valid if #{attribute} is blank" do
|
||||
instance.send "#{attribute}=", nil
|
||||
instance.errors_on(attribute).should include(message)
|
||||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_validate_presence_of</tt>. See that method for more
|
||||
# details. You'd probably only be using this in a nested example block to compare that
|
||||
# one scenario validates presence and another does not (because of conditions in
|
||||
# <tt>:if/:unless</tt>).
|
||||
def it_should_not_validate_presence_of(attribute, message = default_error_message(:blank))
|
||||
it "should be valid if #{attribute} is blank" do
|
||||
instance.send "#{attribute}=", nil
|
||||
instance.errors_on(attribute).should_not include(message)
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that the current model being spec'd <tt>validates_inclusion_of</tt>
|
||||
# the specified attribute. Takes an optional custom message to match the one in the model's
|
||||
# validation.
|
||||
def it_should_validate_inclusion_of(attribute, options = {}, message = default_error_message(:inclusion))
|
||||
it "should validate #{attribute} is in #{options[:in].to_s}" do
|
||||
# We specifically do not try to go below the range on String and character ranges because that problem set is unpredictable.
|
||||
lower = options[:in].first.respond_to?(:-) ? options[:in].first - 0.0001 : nil
|
||||
higher = options[:in].last.succ
|
||||
|
||||
instance.send "#{attribute}=", lower
|
||||
instance.errors_on(attribute).should include(message)
|
||||
|
||||
instance.send "#{attribute}=", higher
|
||||
instance.errors_on(attribute).should include(message)
|
||||
|
||||
instance.send "#{attribute}=", (lower+higher)/2
|
||||
instance.errors_on(attribute).should_not include(message)
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that the current model being spec'd <tt>validates_numericality_of</tt>
|
||||
# the specified attribute. Takes an optional custom message to match the one in the model's
|
||||
# validation.
|
||||
def it_should_validate_numericality_of(attribute, message = I18n.translate('activerecord.errors.messages')[:not_a_number])
|
||||
def it_should_validate_numericality_of(attribute, message = default_error_message(:not_a_number))
|
||||
it "should validate #{attribute} is a numeric" do
|
||||
instance.send "#{attribute}=", "NaN"
|
||||
instance.errors_on(attribute).should include(message)
|
||||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_validate_numericality_of</tt>. See that method for more
|
||||
# details. You'd probably only be using this in a nested example block to compare that
|
||||
# one scenario validates presence and another does not (because of conditions in
|
||||
# <tt>:if/:unless</tt>).
|
||||
def it_should_not_validate_numericality_of(attribute, message = default_error_message(:not_a_number))
|
||||
it "should not validate #{attribute} is a numeric" do
|
||||
instance.send "#{attribute}=", "NaN"
|
||||
instance.errors_on(attribute).should_not include(message)
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that the current model being spec'd <tt>validates_confirmation_of</tt>
|
||||
# the specified attribute. Takes an optional custom message to match the one in the model's
|
||||
# validation.
|
||||
def it_should_validate_confirmation_of(attribute, message = I18n.translate('activerecord.errors.messages')[:confirmation])
|
||||
def it_should_validate_confirmation_of(attribute, message = default_error_message(:confirmation))
|
||||
it "should validate confirmation of #{attribute}" do
|
||||
dummy_value = dummy_value_for(instance, attribute) || "try a string"
|
||||
instance.send "#{attribute}=", dummy_value
|
||||
|
|
@ -263,20 +411,33 @@ module LuckySneaks
|
|||
#
|
||||
# <b>Note:</b> This method will fail completely if <tt>valid_attributes</tt>
|
||||
# does not provide all the attributes needed to create a valid record.
|
||||
def it_should_validate_uniqueness_of(attribute, message = I18n.translate('activerecord.errors.messages')[:taken])
|
||||
it "should validate #{attribute} confirmation" do
|
||||
previous_instance = class_for(self.class.description_text).create!(valid_attributes)
|
||||
def it_should_validate_uniqueness_of(attribute, message = default_error_message(:taken))
|
||||
it "should validate uniqueness of #{attribute}" do
|
||||
previous_instance = instance.class.create!(valid_attributes)
|
||||
instance.attributes = valid_attributes
|
||||
instance.errors_on(attribute).should include(message)
|
||||
previous_instance.destroy
|
||||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_validate_uniqueness_of</tt>. See that method for more
|
||||
# details. You'd probably only be using this in a nested example block to compare that
|
||||
# one scenario validates presence and another does not (because of conditions in
|
||||
# <tt>:if/:unless</tt>).
|
||||
def it_should_not_validate_uniqueness_of(attribute, message = default_error_message(:taken))
|
||||
it "should not validate uniqueness of #{attribute}" do
|
||||
previous_instance = instance.class.create!(valid_attributes)
|
||||
instance.attributes = valid_attributes
|
||||
instance.errors_on(attribute).should_not include(message)
|
||||
previous_instance.destroy
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that the current model being spec'd accepts the specified values as
|
||||
# valid for the specified attribute. This is most likely used with <tt>validates_format_of</tt>
|
||||
# but there's nothing saying it couldn't be another validation.
|
||||
def it_should_accept_as_valid(attribute, *values)
|
||||
values.each do |value|
|
||||
values.flatten.each do |value|
|
||||
value_inspect = case value
|
||||
when String : "'#{value}'"
|
||||
when NilClass : "nil"
|
||||
|
|
@ -296,7 +457,7 @@ module LuckySneaks
|
|||
# spec'ing the actual error message.
|
||||
def it_should_not_accept_as_valid(attribute, *values)
|
||||
options = values.extract_options!
|
||||
values.each do |value|
|
||||
values.flatten.each do |value|
|
||||
value_inspect = case value
|
||||
when String : "'#{value}'"
|
||||
when NilClass : "nil"
|
||||
|
|
@ -312,6 +473,7 @@ module LuckySneaks
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that the current model being spec'd doesn't allow mass-assignment
|
||||
# of the specified attribute.
|
||||
def it_should_not_mass_assign(attribute)
|
||||
|
|
@ -321,6 +483,14 @@ module LuckySneaks
|
|||
}.should_not change(instance, attribute)
|
||||
end
|
||||
end
|
||||
|
||||
def default_error_message(attribute)
|
||||
if defined?(I18n)
|
||||
I18n.translate attribute, :scope => "activerecord.errors.messages"
|
||||
else
|
||||
ActiveRecord::Errors.default_error_messages[attribute]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@ module LuckySneaks
|
|||
# to make your view specs less brittle and more DRY. You might also be interested
|
||||
# in checking out the example block [read: "describe"] level versions in of these
|
||||
# methods which can DRY things up even more:
|
||||
# LuckySneaks::ViewSpecHelpers::ExampleGroupLevelMethods
|
||||
# LuckySneaks::ViewSpecHelpers::ExampleGroupLevelMethods.
|
||||
module ViewSpecHelpers
|
||||
include LuckySneaks::CommonSpecHelpers
|
||||
include LuckySneaks::ViewStubHelpers
|
||||
include ActionController::PolymorphicRoutes
|
||||
|
||||
def self.included(base) # :nodoc:
|
||||
|
|
@ -21,7 +22,7 @@ module LuckySneaks
|
|||
have_tag("form[action=#{path}]")
|
||||
end
|
||||
|
||||
# Wraps a matcher that checks is the receiver contains any of several form elements
|
||||
# Wraps a matcher that checks if the receiver contains any of several form elements
|
||||
# that would return sufficient named parameters to allow editing of the specified
|
||||
# attribute on the specified instance. Example:
|
||||
#
|
||||
|
|
@ -36,7 +37,8 @@ module LuckySneaks
|
|||
# <textarea name="foo[bar]"></textarea>
|
||||
def allow_editing(instance, attribute)
|
||||
instance_name = instance.class.name.underscore.downcase
|
||||
if instance.send(attribute).is_a?(Time)
|
||||
column = instance.column_for_attribute(attribute)
|
||||
if column && [Date, Time].include?(column.klass)
|
||||
have_tag(
|
||||
"input[name='#{instance_name}[#{attribute}]'],
|
||||
select[name=?]", /#{instance_name}\[#{attribute}\(.*\)\]/
|
||||
|
|
@ -48,10 +50,20 @@ module LuckySneaks
|
|||
select[name='#{instance_name}[#{attribute}]'],
|
||||
textarea[name='#{instance_name}[#{attribute}]'],
|
||||
input[type='checkbox'][name='#{instance_name}[#{attribute}]'],
|
||||
input[type='checkbox'][name='#{instance_name}[#{attribute.to_s.tableize.singularize}_ids][]']"
|
||||
input[type='checkbox'][name='#{instance_name}[#{attribute.to_s.tableize.singularize}_ids][]'],
|
||||
input[type='radio'][name='#{instance_name}[#{attribute}]']"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Wraps a matcher that checks if the receiver contains a <tt>FORM</tt> element
|
||||
# whose <tt>enctype</tt> attribute is set to <tt>"multipart/form-data"<tt>
|
||||
# and contains an <tt>INPUT</tt> element whose <tt>name</tt> attribute correlates
|
||||
# with the provided instance and attribute.
|
||||
def allow_uploading(instance, attribute)
|
||||
instance_name = instance.class.name.underscore.downcase
|
||||
have_tag("form[enctype='multipart/form-data'] input[type='file'][name='#{instance_name}[#{attribute}]']")
|
||||
end
|
||||
|
||||
# Wraps a matcher that checks if the receiver contains an <tt>A</tt> element (link)
|
||||
# whose <tt>href</tt> attribute is set to the specified path or a <tt>FORM</tt>
|
||||
|
|
@ -78,7 +90,14 @@ module LuckySneaks
|
|||
# Wraps <tt>have_link_or_button_to polymorphic_path(instance)<tt> which
|
||||
# corresponds with the <tt>show</tt> method of the controller.
|
||||
def have_link_or_button_to_show(instance)
|
||||
have_link_or_button_to polymorphic_path(instance)
|
||||
path = polymorphic_path(instance)
|
||||
have_tag(
|
||||
"a[href='#{path}'],
|
||||
form[action='#{path}'][method='get'] input,
|
||||
form[action='#{path}'][method='get'] button,
|
||||
form[action='#{path}'] input[name='_method'][value='get'] + input,
|
||||
form[action='#{path}'] input[name='_method'][value='get'] + button"
|
||||
)
|
||||
end
|
||||
alias have_link_to_show have_link_or_button_to_show
|
||||
alias have_button_to_show have_link_or_button_to_show
|
||||
|
|
@ -99,7 +118,8 @@ module LuckySneaks
|
|||
path = polymorphic_path(instance)
|
||||
have_tag(
|
||||
"form[action='#{path}'] input[name='_method'][value='delete'] + input,
|
||||
form[action='#{path}'] input[name='_method'][value='delete'] + button"
|
||||
form[action='#{path}'] input[name='_method'][value='delete'] + button,
|
||||
a[href=\"#{path}\"][onclick*=\"f.method = 'POST'\"][onclick*=\"m.setAttribute('name', '_method'); m.setAttribute('value', 'delete')\"]"
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -121,9 +141,9 @@ module LuckySneaks
|
|||
def mock_and_assign(klass, *args)
|
||||
options = args.extract_options!
|
||||
mocked = if options[:stub]
|
||||
mock_model(klass, options[:stub])
|
||||
self.respond_to?(:stub_model) ? stub_model(klass, options[:stub]) : mock_model(klass, options[:stub])
|
||||
else
|
||||
mock_model(klass)
|
||||
self.respond_to?(:stub_model) ? stub_model(klass) : mock_model(klass)
|
||||
end
|
||||
yield mocked if block_given?
|
||||
self.assigns[args.first || "#{klass}".underscore] = mocked
|
||||
|
|
@ -133,12 +153,12 @@ module LuckySneaks
|
|||
# <tt>mock_and_assign</tt>. Accepts <tt>option[:size]</tt> which sets the size
|
||||
# of the array (default is 3).
|
||||
def mock_and_assign_collection(klass, *args)
|
||||
options = args.dup.extract_options!
|
||||
options = args.extract_options!
|
||||
return_me = Array.new(options[:size] || 3) do
|
||||
mocked = if options[:stub]
|
||||
mock_model(klass, options[:stub])
|
||||
self.respond_to?(:stub_model) ? stub_model(klass, options[:stub]) : mock_model(klass, options[:stub])
|
||||
else
|
||||
mock_model(klass)
|
||||
self.respond_to?(:stub_model) ? stub_model(klass) : mock_model(klass)
|
||||
end
|
||||
yield mocked if block_given?
|
||||
mocked
|
||||
|
|
@ -150,8 +170,8 @@ module LuckySneaks
|
|||
def do_render
|
||||
if @the_template
|
||||
render @the_template
|
||||
elsif File.exists?(File.join(RAILS_ROOT, "app/views", self.class.description_text))
|
||||
render self.class.description_text
|
||||
elsif File.exists?(File.join(RAILS_ROOT, "app/views", class_description_text))
|
||||
render class_description_text
|
||||
else
|
||||
error_message = "Cannot determine template for render. "
|
||||
error_message << "Please define @the_template in the before block "
|
||||
|
|
@ -182,6 +202,18 @@ module LuckySneaks
|
|||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_submit_to</tt>. See that method for more
|
||||
# details.
|
||||
def it_should_not_submit_to(hint = nil, &route)
|
||||
if hint.nil? && route.respond_to?(:to_ruby)
|
||||
hint = route.to_ruby.gsub(/(^proc \{)|(\}$)/, '').strip
|
||||
end
|
||||
it "should not submit to #{(hint || route)}" do
|
||||
do_render
|
||||
response.should_not submit_to(instance_eval(&route))
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation that the template uses Rails' <tt>form_for</tt> to generate
|
||||
# the proper form action and method to create or update the specified object.
|
||||
#
|
||||
|
|
@ -190,41 +222,85 @@ module LuckySneaks
|
|||
# not an instance variable, which would be nil in the scope of the example block.
|
||||
# If you use namespacing for your <tt>form_for</tt>, you'll have to manually write out
|
||||
# a similar spec.
|
||||
def it_should_have_form_for(name)
|
||||
def it_should_have_form_for(name, options = {})
|
||||
it "should have a form_for(@#{name})" do
|
||||
template.should_receive(:form_for).with(instance_for(name))
|
||||
if options.empty?
|
||||
template.should_receive(:form_for).with(instance_for(name))
|
||||
else
|
||||
template.should_receive(:form_for).with(instance_for(name), hash_including(options))
|
||||
end
|
||||
do_render
|
||||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_have_form_for</tt>. See that method for more
|
||||
# details.
|
||||
def it_should_not_have_form_for(name)
|
||||
def it_should_not_have_form_for(name, options = {})
|
||||
it "should not have a form_for(@#{name})" do
|
||||
template.should_not_receive(:form_for).with(instance_for(name))
|
||||
if options.empty?
|
||||
template.should_not_receive(:form_for).with(instance_for(name))
|
||||
else
|
||||
template.should_not_receive(:form_for).with(instance_for(name), hash_including(options))
|
||||
end
|
||||
do_render
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation which calls <tt>allow_editing</tt> on the response
|
||||
# from rendering the template. See that method for more details.
|
||||
# Creates an expectation which calls <tt>allow_editing</tt> on the rendered
|
||||
# template for each attribute specified. See the docs for <tt>allow_editing</tt>
|
||||
# for more details.
|
||||
#
|
||||
# <b>Note:</b> This method takes a string or symbol representing the instance
|
||||
# variable's name to send to <tt>allow_editing</tt>
|
||||
# not an instance variable, which would be nil in the scope of the example block.
|
||||
def it_should_allow_editing(name, method)
|
||||
it "should allow editing of @#{name}##{method}" do
|
||||
do_render
|
||||
response.should allow_editing(instance_for(name), method)
|
||||
def it_should_allow_editing(instance_name, *attributes)
|
||||
attributes.flatten!
|
||||
attributes.each do |attribute|
|
||||
it "should allow editing of @#{instance_name}##{attribute}" do
|
||||
do_render
|
||||
response.should allow_editing(instance_for(instance_name), attribute)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_allow_editing</tt>. See that method for more
|
||||
# details.
|
||||
def it_should_not_allow_editing(name, method)
|
||||
it "should not allow editing of @#{name}##{method}" do
|
||||
do_render
|
||||
response.should_not allow_editing(instance_for(name), method)
|
||||
def it_should_not_allow_editing(instance_name, *attributes)
|
||||
attributes.flatten!
|
||||
attributes.each do |attribute|
|
||||
it "should not allow editing of @#{instance_name}##{attribute}" do
|
||||
do_render
|
||||
response.should_not allow_editing(instance_for(instance_name), attribute)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Creates an expectation which calls <tt>allow_uploading</tt> on the rendered
|
||||
# template for each attribute specified. See the docs for <tt>allow_uploading</tt>
|
||||
# for more details.
|
||||
#
|
||||
# <b>Note:</b> This method takes a string or symbol representing the instance
|
||||
# variable's name to send to <tt>allow_uploading</tt>
|
||||
# not an instance variable, which would be nil in the scope of the example block.
|
||||
def it_should_allow_uploading(instance_name, *attributes)
|
||||
attributes.flatten!
|
||||
attributes.each do |attribute|
|
||||
it "should allow editing of @#{instance_name}##{attribute}" do
|
||||
do_render
|
||||
response.should allow_uploading(instance_for(instance_name), attribute)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_allow_uploading</tt>. See that method for more
|
||||
# details.
|
||||
def it_should_not_allow_uploading(instance_name, *attributes)
|
||||
attributes.flatten!
|
||||
attributes.each do |attribute|
|
||||
it "should not allow editing of @#{instance_name}##{attribute}" do
|
||||
do_render
|
||||
response.should_not allow_uploading(instance_for(instance_name), attribute)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -455,6 +531,47 @@ module LuckySneaks
|
|||
alias it_should_have_link_to_delete_each it_should_link_to_delete_each
|
||||
alias it_should_have_button_to_delete_each it_should_link_to_delete_each
|
||||
alias it_should_have_button_or_link_to_delete_each it_should_link_to_delete_each
|
||||
|
||||
# Creates an expectation that the template should call <tt>render :partial</tt>
|
||||
# with the specified template.
|
||||
def it_should_render_partial(name)
|
||||
it "should render :partial => '#{name}'" do
|
||||
template.should_receive(:render).with(hash_including(:partial => name))
|
||||
do_render
|
||||
end
|
||||
end
|
||||
|
||||
# Negative version of <tt>it_should_render_partial</tt>. See that method
|
||||
# for more details.
|
||||
def it_should_not_render_partial(name)
|
||||
it "should not render :partial => '#{name}'" do
|
||||
template.should_not_receive(:render).with(hash_including(:partial => name))
|
||||
do_render
|
||||
end
|
||||
end
|
||||
|
||||
# Sets <tt>@the_template</tt> (for use in <tt>do_render</tt>) using the current
|
||||
# example group description. Example:
|
||||
#
|
||||
# describe "users/index.haml.erb" do
|
||||
# use_describe_for_template!
|
||||
# # ...
|
||||
# end
|
||||
#
|
||||
# This is equivalent to setting <tt>@the_template = "users/index.haml.erb"</tt>
|
||||
# in a before block.
|
||||
def use_describe_for_template!
|
||||
template = self_description_text
|
||||
if File.exists?(File.join(RAILS_ROOT, "app/views", template))
|
||||
before(:each) do
|
||||
@the_template = template
|
||||
end
|
||||
else
|
||||
error_message = "You called use_describe_for_template! "
|
||||
error_message << "but 'app/views/#{template}' does not exist. "
|
||||
raise NameError, error_message
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
15
vendor/plugins/skinny_spec/lib/lucky_sneaks/view_stub_helpers.rb
vendored
Normal file
15
vendor/plugins/skinny_spec/lib/lucky_sneaks/view_stub_helpers.rb
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
$:.unshift File.join(File.dirname(__FILE__), "..")
|
||||
require "skinny_spec"
|
||||
|
||||
module LuckySneaks
|
||||
# These methods are designed to be used in your example <tt>before</tt> blocks to accomplish
|
||||
# a whole lot of functionality with just a tiny bit of effort.
|
||||
module ViewStubHelpers
|
||||
# Shorthand for the following stub:
|
||||
#
|
||||
# template.stub!(:render).with(hash_including(:partial => anything))
|
||||
def stub_partial_rendering!
|
||||
template.stub!(:render).with(hash_including(:partial => anything))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
# Let's make sure everyone else is loaded
|
||||
require File.expand_path(File.dirname(__FILE__) + "/../../../../config/environment")
|
||||
require File.expand_path(RAILS_ROOT + "/config/environment")
|
||||
require 'spec'
|
||||
require 'spec/rails'
|
||||
begin
|
||||
require 'ruby2ruby'
|
||||
rescue
|
||||
rescue LoadError
|
||||
puts "-----"
|
||||
puts "Attention: skinny_spec requires ruby2ruby for nicer route descriptions"
|
||||
puts "It is highly recommended that you install it: sudo gem install ruby2ruby"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue