" +
+ "
"
end
diff --git a/vendor/plugins/skinny_spec/generators/skinny_scaffold/skinny_scaffold_generator.rb b/vendor/plugins/skinny_spec/generators/skinny_scaffold/skinny_scaffold_generator.rb
index 7f6f2b25..3cde3564 100644
--- a/vendor/plugins/skinny_spec/generators/skinny_scaffold/skinny_scaffold_generator.rb
+++ b/vendor/plugins/skinny_spec/generators/skinny_scaffold/skinny_scaffold_generator.rb
@@ -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
diff --git a/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/controller_spec.rb b/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/controller_spec.rb
index dc6d5599..ff1b6b29 100644
--- a/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/controller_spec.rb
+++ b/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/controller_spec.rb
@@ -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 %>)
diff --git a/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/form.html_spec.rb b/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/form.html_spec.rb
index acdf2d01..bc6f6f24 100644
--- a/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/form.html_spec.rb
+++ b/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/form.html_spec.rb
@@ -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
diff --git a/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/index.html_spec.rb b/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/index.html_spec.rb
index 1b3e09d0..cfe213f5 100644
--- a/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/index.html_spec.rb
+++ b/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/index.html_spec.rb
@@ -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
diff --git a/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/index_partial.html_spec.rb b/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/index_partial.html_spec.rb
index 3f112e5e..2a10afb1 100644
--- a/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/index_partial.html_spec.rb
+++ b/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/index_partial.html_spec.rb
@@ -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 ? "," : "" %>
diff --git a/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/model_spec.rb b/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/model_spec.rb
index 119349fc..ed6a1945 100644
--- a/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/model_spec.rb
+++ b/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/model_spec.rb
@@ -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!
diff --git a/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/show.html_spec.rb b/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/show.html_spec.rb
index 1c6c7aa8..aefbbe17 100644
--- a/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/show.html_spec.rb
+++ b/vendor/plugins/skinny_spec/generators/skinny_scaffold/templates/show.html_spec.rb
@@ -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 ? "," : "" %>
diff --git a/vendor/plugins/skinny_spec/lib/lucky_sneaks/common_spec_helpers.rb b/vendor/plugins/skinny_spec/lib/lucky_sneaks/common_spec_helpers.rb
index 2506accb..0a7acff3 100644
--- a/vendor/plugins/skinny_spec/lib/lucky_sneaks/common_spec_helpers.rb
+++ b/vendor/plugins/skinny_spec/lib/lucky_sneaks/common_spec_helpers.rb
@@ -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
\ No newline at end of file
+end
diff --git a/vendor/plugins/skinny_spec/lib/lucky_sneaks/controller_request_helpers.rb b/vendor/plugins/skinny_spec/lib/lucky_sneaks/controller_request_helpers.rb
index a7cd5b94..4aeffaf4 100644
--- a/vendor/plugins/skinny_spec/lib/lucky_sneaks/controller_request_helpers.rb
+++ b/vendor/plugins/skinny_spec/lib/lucky_sneaks/controller_request_helpers.rb
@@ -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
\ No newline at end of file
+end
diff --git a/vendor/plugins/skinny_spec/lib/lucky_sneaks/controller_spec_helpers.rb b/vendor/plugins/skinny_spec/lib/lucky_sneaks/controller_spec_helpers.rb
index 43210f93..20bca87e 100644
--- a/vendor/plugins/skinny_spec/lib/lucky_sneaks/controller_spec_helpers.rb
+++ b/vendor/plugins/skinny_spec/lib/lucky_sneaks/controller_spec_helpers.rb
@@ -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
ActiveRecord::Base.find.
# 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")
#
#
Note: 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
it_should_find. This creates an expectation that
+ # the class never receives
find 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
it_should_initialize. This creates an expectation
+ # that the class never recieves
new 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
ActiveRecord::Base#save on the
# named instance. Example:
#
@@ -136,6 +162,15 @@ module LuckySneaks
end
end
+ # Negative version of
it_should_update. This creates an expectation
+ # that the instance never receives
save 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
ActiveRecord::Base#update_attributes
# on the named instance. Takes optional argument for
params 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
it_should_update. This creates an expectation
+ # that the instance never receives
update_attributes 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
it_should_destroy. This creates an expectation
+ # that the instance never receives
destroy 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
it_should_assign name => :nil. This method can take multiple
+ # instance variable names, creating this shorthand for each name. See the docs for
+ #
it_should_assign 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
it_should_find and
it_should_assign
# 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
it_should_find_and_assign. This creates an
+ # expectation that the class never receives
find 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
it_should_initialize and
it_should_assign
# 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
it_should_initialize_and_save.
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
it_should_initialize_and_assign. This creates an
+ # expectation that the class never receives
new 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
it_should_initialize and
it_should_save
# 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
it_should_initialize_and_assign.
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
it_should_find_and_assign.
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 (
flash or
session)
- # contains the specified key and value. To specify that the collection should be set
- # to
nil, specify the value as :nil instead.
+ # Creates an expectation that the specified collection (
flash,
session,
+ #
params,
cookies) contains the specified key and value. To specify that
+ # the collection should be set to
nil, 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
it_should_set :flash, :nil.
+ def it_should_not_set_flash(name)
+ it_should_set :flash, name, :nil
+ end
# Wraps
it_should_set :session. To specify that the collection should be set
# to
nil, specify the value as :nil instead.
@@ -289,6 +377,33 @@ module LuckySneaks
it_should_set :session, name, value, &block
end
+ # Wraps
it_should_set :session, :nil.
+ def it_should_not_set_session(name)
+ it_should_set :session, name, :nil
+ end
+
+ # Wraps
it_should_set :params. To specify that the collection should be set
+ # to
nil, specify the value as :nil instead.
+ def it_should_set_params(name, value = nil, &block)
+ it_should_set :params, name, value, &block
+ end
+
+ # Wraps
it_should_set :params, :nil.
+ def it_should_not_set_params(name)
+ it_should_set :params, name, :nil
+ end
+
+ # Wraps
it_should_set :cookies. To specify that the collection should be set
+ # to
nil, specify the value as :nil instead.
+ def it_should_set_cookies(name, value = nil, &block)
+ it_should_set :cookies, name, value, &block
+ end
+
+ # Wraps
it_should_set :cookies, :nil.
+ def it_should_not_set_cookies(name)
+ it_should_set :cookies, name, :nil
+ end
+
# Wraps the various
it_should_render_foo methods:
#
it_should_render_template,
it_should_render_partial,
#
it_should_render_xml,
it_should_render_json,
@@ -407,6 +522,27 @@ module LuckySneaks
end
end
+ # Negative version of
it_should_redirect_to.
+ 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
diff --git a/vendor/plugins/skinny_spec/lib/lucky_sneaks/controller_stub_helpers.rb b/vendor/plugins/skinny_spec/lib/lucky_sneaks/controller_stub_helpers.rb
index 950c7a17..6d78ce54 100644
--- a/vendor/plugins/skinny_spec/lib/lucky_sneaks/controller_stub_helpers.rb
+++ b/vendor/plugins/skinny_spec/lib/lucky_sneaks/controller_stub_helpers.rb
@@ -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
stub_create and
stub_update benefit from having a
valid_attributes
- # 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
skinny_scaffold or
- #
skinny_resourceful 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
find :all and returns a collection of
mock_model
# instances of that class. Accepts the following options:
#
+ #
:find_method:: Method to use as finder call. Default is
:find.
+ #
Note: When specifying the method, the call is stubbed
+ # to accept any arguments. Caveat programmer.
#
:format:: Format of the request. Used to only add
to_xml and
#
to_json when actually needed.
#
:size:: 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
stub_initialize which additionally defines an implicit request
post :create.
#
- #
Note: If
stub_create is provided an optional :params hash
- # or the method valid_attributes is defined within its scope,
- # those params will be added to the example's params object. If neither
- # are provided an ArgumentError will be raised.
+ # Note: If stub_create is provided an optional :params hash,
+ # those params will be added to the example's params 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 find and returns a single mock_model
# instances of that class. Accepts the following options:
#
- # :format:: Format of the request. Used to only add to_xml and
- # to_json when actually needed.
- # :stub:: Additional methods to stub on the instances
+ # :find_method:: Method to use as finder call. Default is :find.
+ # :format:: Format of the request. Used to only add to_xml and
+ # to_json when actually needed.
+ # :stub:: Additional methods to stub on the instances
+ # :current_object:: If set to true, find will set params[:id]
+ # using the id of the mock_model instance
+ # and use that value as an argument when stubbing find
#
# Any additional options will be passed as arguments to find.You will want
# to make sure to pass those arguments to the it_should_find 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
+
+ # Note: Use of this method with :child options (to mock
+ # association) is deprecated. Please use stub_association.
+ #
+ # Same as stub_find_one but setups the instance as the parent
+ # of the specified association. Example:
+ #
+ # stub_parent(Document, :child => :comments)
+ #
+ # This stubs Document.find, @document.comments (which
+ # will return Comment class), as well as params[:document_id].
+ # This method is meant to be used in the controller for the specified child
+ # (CommentsController 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 stub_find_one which additionally defines an implicit request put :update
# and stubs out the update_attribute method on the instance as well.
#
- # Note: If stub_update is provided an optional :params hash
- # or the method valid_attributes is defined within its scope,
- # those params will be added to the example's params object. If neither
- # are provided an ArgumentError will be raised.
+ # Note: If stub_update is provided an optional :params hash,
+ # those params will be added to the example's params 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:
+ #
+ # :stub:: 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
diff --git a/vendor/plugins/skinny_spec/lib/lucky_sneaks/model_spec_helpers.rb b/vendor/plugins/skinny_spec/lib/lucky_sneaks/model_spec_helpers.rb
index 471e8c2c..4119acc6 100644
--- a/vendor/plugins/skinny_spec/lib/lucky_sneaks/model_spec_helpers.rb
+++ b/vendor/plugins/skinny_spec/lib/lucky_sneaks/model_spec_helpers.rb
@@ -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.
#
- # Note: 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 have_many. 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
+ #
+ # Note: To spec these sorts of options using the example block helpers like
+ # it_should_have_many, just add them as options directly. This will use
+ # with_options 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.
+ #
+ # Note: 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 belongs_to
- # association with the specified model.
+ # Creates an expectation that the current model being spec'd has a belong_to
+ # association with the specified model. Accepts optional arguments which are appended to
+ # the belong_to 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 belong_to and its related matcher helpers.
#
# Note: 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 have_one
- # association with the specified model.
+ # association with the specified model. Accepts optional arguments which are appended to
+ # the have_one 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 have_one and its related matcher helpers.
#
# Note: 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 have_many
- # association with the specified model.
+ # association with the specified model. Accepts optional arguments which are appended to
+ # the have_many 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 have_many and its related matcher helpers.
#
# Note: 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 have_and_belong_to_many
- # association with the specified model.
+ # association with the specified model. Accepts optional arguments which are appended to
+ # the have_and_belong_to_many 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 have_and_belong_to_many and its related matcher helpers.
#
# Note: 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 validates_presence_of
# 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 it_should_validate_presence_of. 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
+ # :if/:unless).
+ 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 validates_inclusion_of
+ # 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 validates_numericality_of
# 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 it_should_validate_numericality_of. 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
+ # :if/:unless).
+ 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 validates_confirmation_of
# 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
#
# Note: This method will fail completely if valid_attributes
# 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 it_should_validate_uniqueness_of. 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
+ # :if/:unless).
+ 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 validates_format_of
# 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
\ No newline at end of file
+end
diff --git a/vendor/plugins/skinny_spec/lib/lucky_sneaks/view_spec_helpers.rb b/vendor/plugins/skinny_spec/lib/lucky_sneaks/view_spec_helpers.rb
index eb532554..fb8775a1 100644
--- a/vendor/plugins/skinny_spec/lib/lucky_sneaks/view_spec_helpers.rb
+++ b/vendor/plugins/skinny_spec/lib/lucky_sneaks/view_spec_helpers.rb
@@ -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
#
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 FORM element
+ # whose enctype attribute is set to "multipart/form-data"
+ # and contains an INPUT element whose name 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 A element (link)
# whose href attribute is set to the specified path or a FORM
@@ -78,7 +90,14 @@ module LuckySneaks
# Wraps have_link_or_button_to polymorphic_path(instance) which
# corresponds with the show 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
# mock_and_assign. Accepts option[:size] 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 it_should_submit_to. 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' form_for 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 form_for, 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 it_should_have_form_for. 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 allow_editing on the response
- # from rendering the template. See that method for more details.
+ # Creates an expectation which calls allow_editing on the rendered
+ # template for each attribute specified. See the docs for allow_editing
+ # for more details.
#
# Note: This method takes a string or symbol representing the instance
# variable's name to send to allow_editing
# 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 it_should_allow_editing. 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 allow_uploading on the rendered
+ # template for each attribute specified. See the docs for allow_uploading
+ # for more details.
+ #
+ # Note: This method takes a string or symbol representing the instance
+ # variable's name to send to allow_uploading
+ # 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 it_should_allow_uploading. 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 render :partial
+ # 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 it_should_render_partial. 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 @the_template (for use in do_render) using the current
+ # example group description. Example:
+ #
+ # describe "users/index.haml.erb" do
+ # use_describe_for_template!
+ # # ...
+ # end
+ #
+ # This is equivalent to setting @the_template = "users/index.haml.erb"
+ # 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
\ No newline at end of file
+end
diff --git a/vendor/plugins/skinny_spec/lib/lucky_sneaks/view_stub_helpers.rb b/vendor/plugins/skinny_spec/lib/lucky_sneaks/view_stub_helpers.rb
new file mode 100644
index 00000000..2dde384e
--- /dev/null
+++ b/vendor/plugins/skinny_spec/lib/lucky_sneaks/view_stub_helpers.rb
@@ -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 before 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
\ No newline at end of file
diff --git a/vendor/plugins/skinny_spec/lib/skinny_spec.rb b/vendor/plugins/skinny_spec/lib/skinny_spec.rb
index c7883884..3c366ce1 100644
--- a/vendor/plugins/skinny_spec/lib/skinny_spec.rb
+++ b/vendor/plugins/skinny_spec/lib/skinny_spec.rb
@@ -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"