Use current thoughtbot style in specs

This commit is contained in:
Gabe Berke-Williams 2012-12-20 00:04:27 -05:00
parent cc03053e50
commit af8f9a7bff
71 changed files with 1986 additions and 2273 deletions

View File

@ -25,8 +25,8 @@ When 'I generate a new rails application' do
And I set the "BUNDLE_GEMFILE" environment variable to "Gemfile"
And I successfully run `bundle install --local`
}
if RUBY_VERSION >= "1.9.3"
append_to_gemfile %(gem "rake", "~> 0.9.3.beta.1")
if RUBY_VERSION >= '1.9.3'
append_to_gemfile %(gem 'rake', '~> 0.9.3.beta.1')
step %(I successfully run `bundle update rake`)
end
end
@ -52,7 +52,7 @@ When 'I run the rspec generator' do
end
When 'I configure the application to use rspec-rails' do
append_to_gemfile "gem 'rspec-rails', '~> 2.8.1'"
append_to_gemfile %q(gem 'rspec-rails', '~> 2.8.1')
steps %{And I run `bundle install --local`}
end
@ -66,7 +66,7 @@ When 'I configure the application to use rspec-rails in test and development' do
end
When 'I configure the application to use shoulda-context' do
append_to_gemfile "gem 'shoulda-context', '~> 1.0.0'"
append_to_gemfile %q(gem 'shoulda-context', '~> 1.0.0')
steps %{And I run `bundle install --local`}
end
@ -106,7 +106,7 @@ end
module FileHelpers
def append_to(path, contents)
in_current_dir do
File.open(path, "a") do |file|
File.open(path, 'a') do |file|
file.puts
file.puts contents
end
@ -119,9 +119,9 @@ module FileHelpers
def comment_out_gem_in_gemfile(gemname)
in_current_dir do
gemfile = File.read("Gemfile")
gemfile = File.read('Gemfile')
gemfile.sub!(/^(\s*)(gem\s*['"]#{gemname})/, "\\1# \\2")
File.open("Gemfile", 'w'){ |file| file.write(gemfile) }
File.open('Gemfile', 'w'){ |file| file.write(gemfile) }
end
end
end

View File

@ -1,5 +1,5 @@
require 'aruba/cucumber'
Before do
@aruba_timeout_seconds = 120
@aruba_timeout_seconds = 60 * 2
end

View File

@ -1,5 +1,5 @@
PATH
remote: /Users/draper/Dropbox/Development/shoulda-matchers
remote: /Users/gabe/thoughtbot/open-source/shoulda-matchers
specs:
shoulda-matchers (1.4.2)
activesupport (>= 3.0.0)
@ -90,7 +90,7 @@ GEM
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (~> 0.14.4)
rake (10.0.2)
rake (10.0.3)
rdoc (3.12)
json (~> 1.4)
rspec (2.8.0)
@ -106,7 +106,7 @@ GEM
activesupport (>= 3.0)
railties (>= 3.0)
rspec (~> 2.8.0)
shoulda-context (1.0.1)
shoulda-context (1.0.2)
sqlite3 (1.3.6)
thor (0.14.6)
treetop (1.4.12)

View File

@ -1,5 +1,5 @@
PATH
remote: /Users/draper/Dropbox/Development/shoulda-matchers
remote: /Users/gabe/thoughtbot/open-source/shoulda-matchers
specs:
shoulda-matchers (1.4.2)
activesupport (>= 3.0.0)
@ -99,7 +99,7 @@ GEM
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (~> 0.14.6)
rake (10.0.2)
rake (10.0.3)
rdoc (3.12)
json (~> 1.4)
rspec (2.8.0)
@ -121,7 +121,7 @@ GEM
railties (~> 3.1.0)
sass (>= 3.1.10)
tilt (~> 1.3.2)
shoulda-context (1.0.1)
shoulda-context (1.0.2)
sprockets (2.0.4)
hike (~> 1.2)
rack (~> 1.0)

View File

@ -1,5 +1,5 @@
PATH
remote: /Users/draper/Dropbox/Development/shoulda-matchers
remote: /Users/gabe/thoughtbot/open-source/shoulda-matchers
specs:
shoulda-matchers (1.4.2)
activesupport (>= 3.0.0)
@ -73,7 +73,7 @@ GEM
mime-types (1.19)
mocha (0.12.7)
metaclass (~> 0.0.1)
multi_json (1.4.0)
multi_json (1.5.0)
polyglot (0.3.3)
rack (1.4.1)
rack-cache (1.2)
@ -97,7 +97,7 @@ GEM
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rake (10.0.2)
rake (10.0.3)
rdoc (3.12)
json (~> 1.4)
rspec (2.8.0)
@ -118,7 +118,7 @@ GEM
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
shoulda-context (1.0.1)
shoulda-context (1.0.2)
sprockets (2.2.2)
hike (~> 1.2)
multi_json (~> 1.0)

View File

@ -16,7 +16,7 @@ module Shoulda
#
# This code segment:
#
# describe UsersController, "on GET to show with a valid id" do
# describe UsersController, 'on GET to show with a valid id' do
# before(:each) do
# get :show, :id => User.first.to_param
# end
@ -26,7 +26,7 @@ module Shoulda
# it { should render_template(:show) }
# it { should not_set_the_flash) }
#
# it "should do something else really cool" do
# it 'does something else really cool' do
# assigns[:user].id.should == 1
# end
# end

View File

@ -1,7 +1,6 @@
module Shoulda # :nodoc:
module Matchers
module ActionController # :nodoc:
# Ensures that the controller assigned to the named instance variable.
#
# Options:

View File

@ -1,7 +1,6 @@
module Shoulda # :nodoc:
module Matchers
module ActionController # :nodoc:
# Ensures a controller redirected to the given url.
#
# Example:

View File

@ -1,7 +1,6 @@
module Shoulda # :nodoc:
module Matchers
module ActionController # :nodoc:
# Ensures a controller rendered the given template.
#
# Example:

View File

@ -42,9 +42,9 @@ module Shoulda # :nodoc:
end
def description
description = "render with "
description = 'render with '
if @expected_layout.nil?
description << "a layout"
description << 'a layout'
else
description << "the #{@expected_layout.inspect} layout"
end
@ -83,9 +83,9 @@ module Shoulda # :nodoc:
def result
if rendered_with_layout?
"rendered with " + rendered_layouts.map(&:inspect).join(", ")
'rendered with ' + rendered_layouts.map(&:inspect).join(', ')
else
"rendered without a layout"
'rendered without a layout'
end
end
end

View File

@ -11,16 +11,16 @@ module Shoulda # :nodoc:
#
# Examples:
#
# it { should route(:get, "/posts").
# it { should route(:get, '/posts').
# to(:controller => :posts, :action => :index) }
# it { should route(:get, "/posts/new").to(:action => :new) }
# it { should route(:post, "/posts").to(:action => :create) }
# it { should route(:get, "/posts/1").to(:action => :show, :id => 1) }
# it { should route(:get, "/posts/1/edit").to(:action => :edit, :id => 1) }
# it { should route(:put, "/posts/1").to(:action => :update, :id => 1) }
# it { should route(:delete, "/posts/1").
# it { should route(:get, '/posts/new').to(:action => :new) }
# it { should route(:post, '/posts').to(:action => :create) }
# it { should route(:get, '/posts/1').to(:action => :show, :id => 1) }
# it { should route(:get, '/posts/1/edit').to(:action => :edit, :id => 1) }
# it { should route(:put, '/posts/1').to(:action => :update, :id => 1) }
# it { should route(:delete, '/posts/1').
# to(:action => :destroy, :id => 1) }
# it { should route(:get, "/users/1/posts/1").
# it { should route(:get, '/users/1/posts/1').
# to(:action => :show, :id => 1, :user_id => 1) }
def route(method, path)
RouteMatcher.new(method, path, self)

View File

@ -82,12 +82,11 @@ module Shoulda # :nodoc:
if @value
expectation << " to #{@value.inspect}"
end
expectation
end
def result
if session.empty?
"no session variables were set"
'no session variables were set'
else
"the session was #{session.inspect}"
end

View File

@ -8,9 +8,9 @@ module Shoulda # :nodoc:
# Example:
#
# it { should set_the_flash }
# it { should set_the_flash.to("Thank you for placing this order.") }
# it { should set_the_flash.to('Thank you for placing this order.') }
# it { should set_the_flash.to(/created/i) }
# it { should set_the_flash[:alert].to("Password doesn't match") }
# it { should set_the_flash[:alert].to('Password does not match') }
# it { should set_the_flash.to(/logged in/i).now }
# it { should_not set_the_flash }
def set_the_flash
@ -96,7 +96,8 @@ module Shoulda # :nodoc:
@flash
else
@flash = @controller.flash.dup
@flash.instance_variable_set(:@used, @controller.flash.instance_variable_get(:@used).dup)
used = @controller.flash.instance_variable_get(:@used).dup
@flash.instance_variable_set(:@used, used)
sweep_flash_if_necessary
@flash
end
@ -117,7 +118,7 @@ module Shoulda # :nodoc:
def flash_description
if flash.blank?
"no flash was set"
'no flash was set'
else
"was #{flash.inspect}"
end
@ -129,9 +130,9 @@ module Shoulda # :nodoc:
def pretty_now
if @options[:now]
".now"
'.now'
else
""
''
end
end
@ -139,7 +140,7 @@ module Shoulda # :nodoc:
if @options[:key]
"[:#{@options[:key]}]"
else
""
''
end
end
end

View File

@ -115,7 +115,7 @@ module Shoulda # :nodoc:
end
def description
description = "send an email"
description = 'send an email'
description << " with a subject of #{@email_subject.inspect}" if @email_subject
description << " containing #{@body.inspect}" if @body
if @parts
@ -136,7 +136,7 @@ module Shoulda # :nodoc:
private
def expectation
expectation = "sent email"
expectation = 'sent email'
expectation << " with subject #{@email_subject.inspect}" if @subject_failed
expectation << " with body #{@body.inspect}" if @body_failed
@parts.each do |_, body, content_type|

View File

@ -30,7 +30,7 @@ module Shoulda
# %w(abcd 1234).each do |value|
# it { should_not allow_value(value).for(:phone_number) }
# end
# it { should allow_value("(123) 456-7890").for(:phone_number) }
# it { should allow_value('(123) 456-7890').for(:phone_number) }
# it { should_not allow_mass_assignment_of(:password) }
# it { should allow_value('Activated', 'Pending').for(:status).strict }
# it { should_not allow_value('Amazing').for(:status).strict }

View File

@ -25,7 +25,7 @@ module Shoulda # :nodoc:
def as(role)
if active_model_less_than_3_1?
raise "You can specify role only in Rails 3.1 or greater"
raise 'You can specify role only in Rails 3.1 or greater'
end
@options[:role] = role
self
@ -38,7 +38,7 @@ module Shoulda # :nodoc:
@negative_failure_message = "#{@attribute} was made accessible"
else
if protected_attributes.empty?
@negative_failure_message = "no attributes were protected"
@negative_failure_message = 'no attributes were protected'
else
@negative_failure_message = "#{class_name} is protecting " <<
"#{protected_attributes.to_a.to_sentence}, " <<
@ -57,7 +57,7 @@ module Shoulda # :nodoc:
end
def description
[base_description, role_description].compact.join(" ")
[base_description, role_description].compact.join(' ')
end
private

View File

@ -17,11 +17,11 @@ module Shoulda # :nodoc:
#
# Example:
# it { should_not allow_value('bad').for(:isbn) }
# it { should allow_value("isbn 1 2345 6789 0").for(:isbn) }
# it { should allow_value('isbn 1 2345 6789 0').for(:isbn) }
#
def allow_value(*values)
if values.empty?
raise ArgumentError, "need at least one argument"
raise ArgumentError, 'need at least one argument'
else
AllowValueMatcher.new(*values)
end

View File

@ -25,7 +25,7 @@ module Shoulda # :nodoc:
end
def allowed_types
""
''
end
end
end

View File

@ -22,7 +22,7 @@ module Shoulda # :nodoc:
end
class EnsureInclusionOfMatcher < ValidationMatcher # :nodoc:
ARBITRARY_OUTSIDE_STRING = "shouldamatchersteststring"
ARBITRARY_OUTSIDE_STRING = 'shouldamatchersteststring'
def initialize(attribute)
super(attribute)

View File

@ -1,7 +1,6 @@
module Shoulda
module Matchers
module ActiveModel
# Finds message information from exceptions thrown by #valid?
class ExceptionMessageFinder
def initialize(instance, attribute)

View File

@ -21,7 +21,7 @@ module Shoulda # :nodoc:
end
def allowed_types
"integer"
'integer'
end
def failure_message

View File

@ -39,23 +39,25 @@ module Shoulda # :nodoc:
private
def disallows_different_value
set_confirmation("some value")
matches = disallows_value_of("different value", @message)
set_confirmation('some value')
disallows_value_of('different value', @message)
end
def allows_same_value
set_confirmation("same value")
allows_value_of("same value", @message)
set_confirmation('same value')
allows_value_of('same value', @message)
end
def allows_missing_confirmation
set_confirmation(nil)
allows_value_of("any value", @message)
allows_value_of('any value', @message)
end
def set_confirmation(val)
setter = :"#{@confirmation}="
@subject.send(setter, val) if @subject.respond_to?(setter)
if @subject.respond_to?(setter)
@subject.send(setter, val)
end
end
end
end

View File

@ -1,7 +1,6 @@
module Shoulda # :nodoc:
module Matchers
module ActiveModel # :nodoc:
# Ensures that the model is not valid if the given attribute is not
# formatted correctly.
#
@ -27,7 +26,6 @@ module Shoulda # :nodoc:
end
class ValidateFormatOfMatcher < ValidationMatcher # :nodoc:
def initialize(attribute)
super
@options = {}
@ -44,20 +42,28 @@ module Shoulda # :nodoc:
end
def with_message(message)
@expected_message = message if message
if message
@expected_message = message
end
self
end
def with(value)
raise "You may not call both with and not_with" if @value_to_fail
@value_to_pass = value
self
if @value_to_fail
raise 'You may not call both with and not_with'
else
@value_to_pass = value
self
end
end
def not_with(value)
raise "You may not call both with and not_with" if @value_to_pass
@value_to_fail = value
self
if @value_to_pass
raise 'You may not call both with and not_with'
else
@value_to_fail = value
self
end
end
def matches?(subject)

View File

@ -79,8 +79,8 @@ module Shoulda # :nodoc:
end
def allowed_types
allowed = ["numeric"] + submatcher_allowed_types
allowed.join(", ")
allowed = ['numeric'] + submatcher_allowed_types
allowed.join(', ')
end
def submatcher_allowed_types

View File

@ -1,7 +1,6 @@
module Shoulda # :nodoc:
module Matchers
module ActiveModel # :nodoc:
# Ensures that the model is invalid if the given attribute is not unique.
#
# Internally, this uses values from existing records to test validations,
@ -57,14 +56,6 @@ module Shoulda # :nodoc:
self
end
def description
result = "require "
result << "case sensitive " unless @options[:case_insensitive]
result << "unique value for #{@attribute}"
result << " scoped to #{@options[:scopes].join(', ')}" if @options[:scopes].present?
result
end
def matches?(subject)
@subject = subject.class.new
@expected_message ||= :taken
@ -73,6 +64,14 @@ module Shoulda # :nodoc:
validate_after_scope_change?
end
def description
result = 'require '
result << 'case sensitive ' unless @options[:case_insensitive]
result << "unique value for #{@attribute}"
result << " scoped to #{@options[:scopes].join(', ')}" if @options[:scopes].present?
result
end
private
def existing
@ -85,7 +84,7 @@ module Shoulda # :nodoc:
def create_instance_in_database
@subject.class.new.tap do |instance|
instance.send("#{@attribute}=", "arbitrary_string")
instance.send("#{@attribute}=", 'arbitrary_string')
instance.save(:validate => false)
end
end

View File

@ -29,7 +29,7 @@ module Shoulda
def messages_description
if errors.empty?
"no errors"
'no errors'
else
"errors: #{pretty_error_messages(validated_instance)}"
end

View File

@ -78,7 +78,7 @@ module Shoulda
if config
true
else
@problem = "is not declared"
@problem = 'is not declared'
false
end
end
@ -129,9 +129,9 @@ module Shoulda
def should_or_should_not(value)
if value
"should"
'should'
else
"should not"
'should not'
end
end
end

View File

@ -260,7 +260,7 @@ module Shoulda # :nodoc:
if !@validate && !reflection.options[:validate] || @validate == reflection.options[:validate]
true
else
@missing = "#{@name} should have #{@validate} as validate"
@missing = "#{@name} should have :validate => #{@validate}"
false
end
end

View File

@ -149,11 +149,11 @@ module Shoulda # :nodoc:
def correct_scale?
return true unless @options.key?(:scale)
if matched_column.scale.to_s == @options[:scale].to_s
if actual_scale.to_s == @options[:scale].to_s
true
else
@missing = "#{model_class} has a db column named #{@column} " <<
"of scale #{matched_column.scale}, not #{@options[:scale]}."
@missing = "#{model_class} has a db column named #{@column} "
@missing << "of scale #{actual_scale}, not #{@options[:scale]}."
false
end
end
@ -166,9 +166,9 @@ module Shoulda # :nodoc:
else
@missing = "#{model_class} has a db column named #{@column} "
if @options[:primary]
@missing << "that is not primary, but should be"
@missing << 'that is not primary, but should be'
else
@missing << "that is primary, but should not be"
@missing << 'that is primary, but should not be'
end
false
end
@ -182,6 +182,10 @@ module Shoulda # :nodoc:
@subject.class
end
def actual_scale
matched_column.scale
end
def expectation
expected = "#{model_class.name} to #{description}"
end

View File

@ -26,7 +26,7 @@ module Shoulda # :nodoc:
else
if readonly_attributes.empty?
@failure_message = "#{class_name} attribute #{@attribute} " <<
"is not read-only"
'is not read-only'
else
@failure_message = "#{class_name} is making " <<
"#{readonly_attributes.to_a.to_sentence} " <<

View File

@ -1,7 +1,6 @@
module Shoulda # :nodoc:
module Matchers
module ActiveRecord # :nodoc:
# Ensure that the field becomes serialized.
#
# Options:
@ -10,6 +9,7 @@ module Shoulda # :nodoc:
# Example:
# it { should serialize(:details) }
# it { should serialize(:details).as(Hash) }
# it { should serialize(:details).as_instance_of(ExampleSerializer) }
#
def serialize(name)
SerializeMatcher.new(name)

View File

@ -3,11 +3,11 @@ module Shoulda
if Gem.ruby_version >= Gem::Version.new('1.8') && Gem.ruby_version < Gem::Version.new('1.9')
require 'test/unit'
AssertionError = Test::Unit::AssertionFailedError
elsif Gem.ruby_version >= Gem::Version.new("1.9")
elsif Gem.ruby_version >= Gem::Version.new('1.9')
require 'minitest/unit'
AssertionError = MiniTest::Assertion
else
raise "No unit test library available"
raise 'No unit test library available'
end
end
end

View File

@ -1,7 +1,7 @@
require 'spec_helper'
describe Shoulda::Matchers::ActionController::AssignToMatcher do
it "should include the actual class in the failure message" do
it 'includes the actual class in the failure message' do
define_class(:WrongClass) do
def to_s
'wrong class'
@ -15,48 +15,51 @@ describe Shoulda::Matchers::ActionController::AssignToMatcher do
matcher.failure_message.should =~ /but got wrong class \(WrongClass\)$/
end
context "a controller that assigns to an instance variable" do
let(:controller) { build_response { @var = 'value' } }
it "should accept assigning to that variable" do
context 'a controller that assigns to an instance variable' do
it 'accepts assigning to that variable' do
controller.should assign_to(:var)
end
it "should accept assigning to that variable with the correct class" do
it 'accepts assigning to that variable with the correct class' do
controller.should assign_to(:var).with_kind_of(String)
end
it "should reject assigning to that variable with another class" do
it 'rejects assigning to that variable with another class' do
controller.should_not assign_to(:var).with_kind_of(Fixnum)
end
it "should accept assigning the correct value to that variable" do
it 'accepts assigning the correct value to that variable' do
controller.should assign_to(:var).with('value')
end
it "should reject assigning another value to that variable" do
it 'rejects assigning another value to that variable' do
controller.should_not assign_to(:var).with('other')
end
it "should reject assigning to another variable" do
it 'rejects assigning to another variable' do
controller.should_not assign_to(:other)
end
it "should accept assigning to the same value in the test context" do
it 'accepts assigning to the same value in the test context' do
expected = 'value'
controller.should assign_to(:var).in_context(self).with { expected }
end
it "should reject assigning to the another value in the test context" do
it 'rejects assigning to the another value in the test context' do
expected = 'other'
controller.should_not assign_to(:var).in_context(self).with { expected }
end
def controller
build_response { @var = 'value' }
end
end
context "a controller that assigns a nil value to an instance variable" do
let(:controller) { build_response { @var = nil } }
it "should accept assigning to that variable" do
context 'a controller that assigns a nil value to an instance variable' do
it 'accepts assigning to that variable' do
controller = build_response do
@var = nil
end
controller.should assign_to(:var)
end
end

View File

@ -1,20 +1,22 @@
require 'spec_helper'
describe Shoulda::Matchers::ActionController::FilterParamMatcher do
context "given parameter filters" do
before do
Rails.application.config.filter_parameters = [:secret]
end
it 'accepts filtering a filtered parameter' do
filter(:secret)
it "should accept filtering that parameter" do
nil.should filter_param(:secret)
end
nil.should filter_param(:secret)
end
it "should reject filtering another parameter" do
matcher = filter_param(:other)
matcher.matches?(nil).should be_false
matcher.failure_message.should include("Expected other to be filtered")
matcher.failure_message.should =~ /secret/
end
it 'rejects filtering an unfiltered parameter' do
filter(:secret)
matcher = filter_param(:other)
matcher.matches?(nil).should be_false
matcher.failure_message.should =~ /Expected other to be filtered.*secret/
end
def filter(param)
Rails.application.config.filter_parameters = [param]
end
end

View File

@ -1,40 +1,42 @@
require 'spec_helper'
describe Shoulda::Matchers::ActionController::RedirectToMatcher do
context "a controller that redirects" do
let(:controller) do
build_response { redirect_to '/some/url' }
context 'a controller that redirects' do
it 'accepts redirecting to that url' do
controller_redirecting_to('/some/url').should redirect_to('/some/url')
end
it "accepts redirecting to that url" do
controller.should redirect_to('/some/url')
it 'rejects redirecting to a different url' do
controller_redirecting_to('/some/url').should_not
redirect_to('/some/other/url')
end
it "rejects redirecting to a different url" do
controller.should_not redirect_to('/some/other/url')
it 'accepts redirecting to that url in a block' do
controller_redirecting_to('/some/url').should
redirect_to('somewhere') { '/some/url' }
end
it "accepts redirecting to that url in a block" do
controller.should redirect_to('somewhere') { '/some/url' }
it 'rejects redirecting to a different url in a block' do
controller_redirecting_to('/some/url').should_not
redirect_to('somewhere else') { '/some/other/url' }
end
it "rejects redirecting to a different url in a block" do
controller.should_not redirect_to('somewhere else') { '/some/other/url' }
def controller_redirecting_to(url)
build_response { redirect_to url }
end
end
context "a controller that doesn't redirect" do
let(:controller) do
build_response { render :text => 'hello' }
end
context 'a controller that does not redirect' do
it 'rejects redirecting to a url' do
controller = build_response { render :text => 'hello' }
it "rejects redirecting to a url" do
controller.should_not redirect_to('/some/url')
end
end
it "provides the correct description when provided a block" do
it 'provides the correct description when provided a block' do
matcher = redirect_to('somewhere else') { '/some/other/url' }
matcher.description.should == 'redirect to somewhere else'
end
end

View File

@ -3,67 +3,76 @@ require 'spec_helper'
describe Shoulda::Matchers::ActionController::RenderTemplateMatcher do
include ActionController::TemplateAssertions
context "a controller that renders a template" do
let(:controller) { build_response(:action => 'show') { render } }
it "accepts rendering that template" do
controller.should render_template(:show)
context 'a controller that renders a template' do
it 'accepts rendering that template' do
controller_with_show.should render_template(:show)
end
it "rejects rendering a different template" do
controller.should_not render_template(:index)
it 'rejects rendering a different template' do
controller_with_show.should_not render_template(:index)
end
it "accepts rendering that template in the given context" do
controller.should render_template(:show).in_context(self)
it 'accepts rendering that template in the given context' do
controller_with_show.should render_template(:show).in_context(self)
end
it "rejects rendering a different template in the given context" do
controller.should_not render_template(:index).in_context(self)
it 'rejects rendering a different template in the given context' do
controller_with_show.should_not render_template(:index).in_context(self)
end
def controller_with_show
build_response(:action => 'show') { render }
end
end
context "a controller that renders a partial" do
let(:controller) { build_response(:partial => '_customer') { render :partial => 'customer' } }
it "accepts rendering that partial" do
controller.should render_template(:partial => '_customer')
context 'a controller that renders a partial' do
it 'accepts rendering that partial' do
controller_with_customer_partial.should
render_template(:partial => '_customer')
end
it "rejects rendering a different template" do
controller.should_not render_template(:partial => '_client')
it 'rejects rendering a different template' do
controller_with_customer_partial.should_not
render_template(:partial => '_client')
end
it "accepts rendering that template in the given context" do
controller.should render_template(:partial => '_customer').in_context(self)
it 'accepts rendering that template in the given context' do
controller_with_customer_partial.should
render_template(:partial => '_customer').in_context(self)
end
it "rejects rendering a different template in the given context" do
controller.should_not render_template(:partial => '_client').in_context(self)
it 'rejects rendering a different template in the given context' do
controller_with_customer_partial.should_not
render_template(:partial => '_client').in_context(self)
end
def controller_with_customer_partial
build_response(:partial => '_customer') { render :partial => 'customer' }
end
end
context "a controller that doesn't render partials" do
let(:controller) { build_response(:action => 'show') { render } }
context 'a controller that does not render partials' do
it 'accepts not rendering a partial' do
controller = build_response(:action => 'show') { render }
it "should not render a partial" do
controller.should render_template(:partial => false)
end
end
context "a controller that renders a partial several times" do
let(:controller) { build_response(:partial => '_customer') { render :partial => 'customer', :collection => [1,2] } }
context 'a controller that renders a partial several times' do
it 'accepts rendering that partial twice' do
controller = build_response(:partial => '_customer') do
render :partial => 'customer', :collection => [1,2]
end
it "accepts rendering that partial twice" do
controller.should render_template(:partial => '_customer', :count => 2)
end
end
context "a controller that doesn't render a template" do
let(:controller) { build_response { render :nothing => true } }
it "rejects rendering a template" do
controller.should_not render_template(:show)
context 'a controller that does not render a template' do
it 'rejects rendering a template' do
build_response { render :nothing => true }.should_not
render_template(:show)
end
end
end

View File

@ -3,53 +3,56 @@ require 'spec_helper'
describe Shoulda::Matchers::ActionController::RenderWithLayoutMatcher do
include ActionController::TemplateAssertions
context "a controller that renders with a layout" do
let(:controller) { build_response { render :layout => 'wide' } }
context 'a controller that renders with a layout' do
it 'accepts rendering with any layout' do
controller_with_wide_layout.should render_with_layout
end
before do
it 'accepts rendering with that layout' do
controller_with_wide_layout.should render_with_layout(:wide)
end
it 'rejects rendering with another layout' do
controller_with_wide_layout.should_not render_with_layout(:other)
end
def controller_with_wide_layout
create_view('layouts/wide.html.erb', 'some content, <%= yield %>')
end
it "should accept rendering with any layout" do
controller.should render_with_layout
end
it "should accept rendering with that layout" do
controller.should render_with_layout(:wide)
end
it "should reject rendering with another layout" do
controller.should_not render_with_layout(:other)
build_response { render :layout => 'wide' }
end
end
context "a controller that renders without a layout" do
let(:controller) { build_response { render :layout => false } }
context 'a controller that renders without a layout' do
it "should reject rendering with a layout" do
controller.should_not render_with_layout
it 'rejects rendering with a layout' do
controller_without_layout = build_response { render :layout => false }
controller_without_layout.should_not render_with_layout
end
end
context "a controller that renders a partial" do
let(:controller) { build_response { render :partial => 'partial' } }
context 'a controller that renders a partial' do
it 'rejects rendering with a layout' do
controller_with_partial = build_response { render :partial => 'partial' }
it "should reject rendering with a layout" do
controller.should_not render_with_layout
controller_with_partial.should_not render_with_layout
end
end
context "given a context with layouts" do
let(:layout) { 'happy' }
let(:controller) { build_response { render :layout => false } }
context 'given a context with layouts' do
it 'accepts that layout in that context' do
set_in_context_layout('happy')
before do
controller_without_layout.should render_with_layout('happy').in_context(self)
end
def set_in_context_layout(layout)
@layouts = Hash.new(0)
@layouts[layout] = 1
end
it "should accept that layout in that context" do
controller.should render_with_layout(layout).in_context(self)
def controller_without_layout
build_response { render :layout => false }
end
end
end

View File

@ -1,28 +1,31 @@
require 'spec_helper'
describe Shoulda::Matchers::ActionController::RespondWithContentTypeMatcher do
context "a controller responding with content type :xml" do
let(:controller) { build_response { render :xml => { :user => "thoughtbot" }.to_xml } }
it 'generates the correct description' do
expected = 'respond with content type of application/xml'
it "should accept responding with content type :xml" do
controller.should respond_with_content_type(:xml)
end
it "should accept responding with content type 'application/xml'" do
controller.should respond_with_content_type('application/xml')
end
it "should accept responding with content type /xml/" do
controller.should respond_with_content_type(/xml/)
end
it "should reject responding with another content type" do
controller.should_not respond_with_content_type(:json)
end
respond_with_content_type(:xml).description.should == expected
end
it "should generate the correct test name" do
respond_with_content_type(:xml).description.
should == "respond with content type of application/xml"
it 'accepts responding with content type as symbol' do
xml_controller.should respond_with_content_type(:xml)
end
it 'accepts responding with qualified MIME-style content type' do
xml_controller.should respond_with_content_type('application/xml')
end
it 'accepts responding with a regex matching the content type' do
xml_controller.should respond_with_content_type(/xml/)
end
it 'rejects responding with another content type' do
xml_controller.should_not respond_with_content_type(:json)
end
def xml_controller
build_response do
render :xml => { :user => 'thoughtbot' }.to_xml
end
end
end

View File

@ -1,83 +1,31 @@
require 'spec_helper'
describe Shoulda::Matchers::ActionController::RespondWithMatcher do
context "a controller responding with success" do
let(:controller) { build_response { render :text => "text", :status => 200 } }
statuses = { :success => 200, :redirect => 301, :missing => 404, :error => 500,
:not_implemented => 501 }
it "should accept responding with 200" do
controller.should respond_with(200)
end
statuses.each do |human_name, numeric_code|
context "a controller responding with #{human_name}" do
it 'accepts responding with a numeric response code' do
controller_with_status(numeric_code).should respond_with(numeric_code)
end
it "should accept responding with :success" do
controller.should respond_with(:success)
end
it 'accepts responding with a symbol response code' do
controller_with_status(numeric_code).should respond_with(human_name)
end
it "should reject responding with another status" do
controller.should_not respond_with(:error)
it 'rejects responding with another status' do
another_status = statuses.except(human_name).keys.first
controller_with_status(numeric_code).should_not
respond_with(another_status)
end
end
end
context "a controller responding with redirect" do
let(:controller) { build_response { render :text => "text", :status => 301 } }
it "should accept responding with 301" do
controller.should respond_with(301)
end
it "should accept responding with :redirect" do
controller.should respond_with(:redirect)
end
it "should reject responding with another status" do
controller.should_not respond_with(:error)
end
end
context "a controller responding with missing" do
let(:controller) { build_response { render :text => "text", :status => 404 } }
it "should accept responding with 404" do
controller.should respond_with(404)
end
it "should accept responding with :missing" do
controller.should respond_with(:missing)
end
it "should reject responding with another status" do
controller.should_not respond_with(:success)
end
end
context "a controller responding with error" do
let(:controller) { build_response { render :text => "text", :status => 500 } }
it "should accept responding with 500" do
controller.should respond_with(500)
end
it "should accept responding with :error" do
controller.should respond_with(:error)
end
it "should reject responding with another status" do
controller.should_not respond_with(:success)
end
end
context "a controller responding with not implemented" do
let(:controller) { build_response { render :text => "text", :status => 501 } }
it "should accept responding with 501" do
controller.should respond_with(501)
end
it "should accept responding with :not_implemented" do
controller.should respond_with(:not_implemented)
end
it "should reject responding with another status" do
controller.should_not respond_with(:success)
def controller_with_status(status)
build_response do
render :text => 'text', :status => status
end
end
end

View File

@ -1,65 +1,65 @@
require 'spec_helper'
describe Shoulda::Matchers::ActionController::RouteMatcher do
context "given a controller with a defined glob url" do
let(:controller) { define_controller('Examples').new }
context 'given a controller with a defined glob url' do
it 'accepts glob route' do
controller = define_controller('Examples').new
before do
define_routes do
match 'examples/*id', :to => 'examples#example'
end
end
it "should accept glob route" do
controller.should route(:get, '/examples/foo/bar').
to(:action => 'example', :id => 'foo/bar')
end
end
context "given a controller with a defined route" do
let!(:controller) { define_controller('Examples').new }
context 'given a controller with a defined route' do
before do
define_routes do
match 'examples/:id', :to => 'examples#example'
end
end
it "should accept routing the correct path to the correct parameters" do
controller.should route(:get, '/examples/1').
it 'accepts routing the correct path to the correct parameters' do
route_examples_to_examples.should route(:get, '/examples/1').
to(:action => 'example', :id => '1')
end
it "should accept a symbol controller" do
it 'accepts a symbol controller' do
route_examples_to_examples
Object.new.should route(:get, '/examples/1').
to(:controller => :examples,
:action => 'example',
:id => '1')
to(:controller => :examples, :action => 'example', :id => '1')
end
it "should accept a symbol action" do
controller.should route(:get, '/examples/1').
it 'accepts a symbol action' do
route_examples_to_examples.should route(:get, '/examples/1').
to(:action => :example, :id => '1')
end
it "should accept a non-string parameter" do
controller.should route(:get, '/examples/1').
it 'accepts a non-string parameter' do
route_examples_to_examples.should route(:get, '/examples/1').
to(:action => 'example', :id => 1)
end
it "should reject an undefined route" do
controller.should_not route(:get, '/bad_route').to(:var => 'value')
it 'rejects an undefined route' do
route_examples_to_examples.should_not
route(:get, '/bad_route').to(:var => 'value')
end
it "should reject a route for another controller" do
it 'rejects a route for another controller' do
route_examples_to_examples
other = define_controller('Other').new
other.should_not route(:get, '/examples/1').
to(:action => 'example', :id => '1')
end
it "should reject a route for different parameters" do
controller.should_not route(:get, '/examples/1').
it 'rejects a route for different parameters' do
route_examples_to_examples.should_not route(:get, '/examples/1').
to(:action => 'other', :id => '1')
end
def route_examples_to_examples
define_routes do
get 'examples/:id', :to => 'examples#example'
end
define_controller('Examples').new
end
end
end

View File

@ -1,46 +1,51 @@
require 'spec_helper'
describe Shoulda::Matchers::ActionController::SetSessionMatcher do
context "a controller that sets a session variable" do
let(:controller) do
build_response do
session[:var] = 'value'
session[:false_var] = false
end
context 'a controller that sets a session variable' do
it 'accepts assigning to that variable' do
controller_with_session(:var => 'hi').should set_session(:var)
end
it "should accept assigning to that variable" do
controller.should set_session(:var)
it 'accepts assigning the correct value to that variable' do
controller_with_session(:var => 'hi').should set_session(:var).to('hi')
end
it "should accept assigning the correct value to that variable" do
controller.should set_session(:var).to('value')
it 'rejects assigning another value to that variable' do
controller_with_session(:var => 'hi').should_not set_session(:var).to('other')
end
it "should reject assigning another value to that variable" do
controller.should_not set_session(:var).to('other')
it 'rejects assigning to another variable' do
controller_with_session(:var => 'hi').should_not set_session(:other)
end
it "should reject assigning to another variable" do
controller.should_not set_session(:other)
it 'accepts assigning nil to another variable' do
controller_with_session(:var => 'hi').should set_session(:other).to(nil)
end
it "should accept assigning nil to another variable" do
controller.should set_session(:other).to(nil)
it 'accepts assigning false to that variable' do
controller_with_session(:var => false).should set_session(:var).to(false)
end
it "should accept assigning false to that variable" do
controller.should set_session(:false_var).to(false)
end
it "should accept assigning to the same value in the test context" do
it 'accepts assigning to the same value in the test context' do
expected = 'value'
controller.should set_session(:var).in_context(self).to { expected }
controller_with_session(:var => expected).should
set_session(:var).in_context(self).to { expected }
end
it "should reject assigning to the another value in the test context" do
it 'rejects assigning to the another value in the test context' do
expected = 'other'
controller.should_not set_session(:var).in_context(self).to { expected }
controller_with_session(:var => 'unexpected').should_not
set_session(:var).in_context(self).to { expected }
end
def controller_with_session(session_hash)
build_response do
session_hash.each do |key, value|
session[key] = value
end
end
end
end
end

View File

@ -1,130 +1,155 @@
require 'spec_helper'
describe Shoulda::Matchers::ActionController::SetTheFlashMatcher do
it "should fail with unmatchable to" do
expect{
it 'fails with unmatchable #to' do
expect {
set_the_flash.to(1).should
}.to raise_error("cannot match against 1")
}.to raise_error('cannot match against 1')
end
context "a controller that sets a flash message" do
let(:controller) { build_response { flash[:notice] = 'value' } }
it "should accept setting any flash message" do
controller.should set_the_flash
context 'a controller that sets a flash message' do
it 'accepts setting any flash message' do
controller_with_flash(:notice => 'hi').should set_the_flash
end
it "should accept setting the exact flash message" do
controller.should set_the_flash.to('value')
it 'accepts setting the exact flash message' do
controller_with_flash(:notice => 'hi').should set_the_flash.to('hi')
end
it "should accept setting a matched flash message" do
controller.should set_the_flash.to(/value/)
it 'accepts setting a matched flash message' do
controller_with_flash(:notice => 'hello').should set_the_flash.to(/he/)
end
it "should reject setting a different flash message" do
controller.should_not set_the_flash.to('other')
it 'rejects setting a different flash message' do
controller_with_flash(:notice => 'hi').should_not
set_the_flash.to('other')
end
it "should reject setting a different pattern" do
controller.should_not set_the_flash.to(/other/)
it 'rejects setting a different pattern' do
controller_with_flash(:notice => 'hi').should_not
set_the_flash.to(/other/)
end
end
context "a controller that sets a flash.now message" do
let(:controller) { build_response { flash.now[:notice] = 'value' } }
it "should reject setting any flash message" do
controller.should_not set_the_flash
context 'a controller that sets a flash.now message' do
it 'rejects setting any flash message' do
controller_with_flash_now.should_not set_the_flash
end
it "should accept setting any flash.now message" do
controller.should set_the_flash.now
it 'accepts setting any flash.now message' do
controller_with_flash_now.should set_the_flash.now
end
it "should accept setting the exact flash.now message" do
controller.should set_the_flash.to('value').now
it 'accepts setting the exact flash.now message' do
controller_with_flash_now(:notice => 'hi').should
set_the_flash.now.to('hi')
end
it "should accept setting a matched flash.now message" do
controller.should set_the_flash.to(/value/).now
it 'accepts setting a matched flash.now message' do
controller_with_flash_now(:notice => 'flasher').should
set_the_flash.now.to(/lash/)
end
it "should reject setting a different flash.now message" do
controller.should_not set_the_flash.to('other').now
it 'rejects setting a different flash.now message' do
controller_with_flash_now(:notice => 'hi').should_not
set_the_flash.now.to('other')
end
it "should reject setting a different flash.now pattern" do
controller.should_not set_the_flash.to(/other/).now
it 'rejects setting a different flash.now pattern' do
controller_with_flash_now(:notice => 'hi').should_not
set_the_flash.now.to(/other/)
end
end
context "a controller that sets a flash message of notice and alert" do
let(:controller) do
build_response do
flash[:notice] = 'value'
flash[:alert] = 'other'
end
end
context 'a controller that sets flash messages for multiple keys' do
it 'accepts flash message for either key' do
controller = controller_with_flash(:notice => 'one', :alert => 'two')
it "should accept flash message of notice" do
controller.should set_the_flash[:notice]
controller.should set_the_flash[:alert]
end
it "should accept flash message of alert" do
controller.should set_the_flash[:notice]
it 'rejects a flash message that is not one of the set keys' do
controller_with_flash(:notice => 'one', :alert => 'two').should_not
set_the_flash[:warning]
end
it "should reject flash message of warning" do
controller.should_not set_the_flash[:warning]
it 'accepts exact flash message of notice' do
controller_with_flash(:notice => 'one', :alert => 'two').should
set_the_flash[:notice].to('one')
end
it "should accept exact flash message of notice" do
controller.should set_the_flash[:notice].to('value')
it 'accepts setting a matched flash message of notice' do
controller_with_flash(:notice => 'one', :alert => 'two').should
set_the_flash[:notice].to(/on/)
end
it "should accept setting a matched flash message of notice" do
controller.should set_the_flash[:notice].to(/value/)
it 'rejects setting a different flash message of notice' do
controller_with_flash(:notice => 'one', :alert => 'two').should_not
set_the_flash[:notice].to('other')
end
it "should reject setting a different flash message of notice" do
controller.should_not set_the_flash[:notice].to('other')
end
it "should reject setting a different pattern" do
controller.should_not set_the_flash[:notice].to(/other/)
it 'rejects setting a different pattern' do
controller_with_flash(:notice => 'one', :alert => 'two').should_not
set_the_flash[:notice].to(/other/)
end
end
context "a controller that sets multiple flash messages" do
let(:controller) do
build_response do
context 'a controller that sets flash and flash.now' do
it 'accepts setting any flash.now message' do
controller = build_response do
flash.now[:notice] = 'value'
flash[:success] = 'great job'
end
end
it "should accept setting any flash.now message" do
controller.should set_the_flash.now
controller.should set_the_flash
end
it "should accept setting a matched flash.now message" do
controller.should set_the_flash.to(/value/).now
it 'accepts setting a matched flash.now message' do
controller = build_response do
flash.now[:notice] = 'value'
flash[:success] = 'great job'
end
controller.should set_the_flash.now.to(/value/)
controller.should set_the_flash.to(/great/)
end
it "should reject setting a different flash.now message" do
controller.should_not set_the_flash.to('other').now
it 'rejects setting a different flash.now message' do
controller = build_response do
flash.now[:notice] = 'value'
flash[:success] = 'great job'
end
controller.should_not set_the_flash.now.to('other')
controller.should_not set_the_flash.to('other')
end
end
context "a controller that doesn't set a flash message" do
let(:controller) { build_response }
context 'a controller that does not set a flash message' do
it 'rejects setting any flash message' do
controller_with_no_flashes.should_not set_the_flash
end
end
it "should reject setting any flash message" do
controller.should_not set_the_flash
def controller_with_no_flashes
build_response
end
def controller_with_flash(flash_hash)
build_response do
flash_hash.each do |key, value|
flash[key] = value
end
end
end
def controller_with_flash_now(flash_hash = { :notice => 'hi' })
build_response do
flash_hash.each do |key, value|
flash.now[key] = value
end
end
end
end

View File

@ -1,22 +1,23 @@
require 'spec_helper'
describe Shoulda::Matchers::ActionMailer::HaveSentEmailMatcher do
subject { Shoulda::Matchers::ActionMailer::HaveSentEmailMatcher.new(self) }
subject { described_class.new(self) }
after { ::ActionMailer::Base.deliveries.clear }
def add_mail_to_deliveries(params = nil)
::ActionMailer::Base.deliveries << Mailer.the_email(params)
end
context "testing with instance variables with no multipart" do
context 'testing with instance variables with no multipart' do
let(:info) do
{
:from => "do-not-reply@example.com",
:reply_to => "reply-to-me@example.com",
:to => "myself@me.com",
:cc => ["you@you.com", "joe@bob.com", "hello@goodbye.com"],
:bcc => ["test@example.com", "sam@bob.com", "goodbye@hello.com"],
:subject => "This is spam",
:body => "Every email is spam."
:from => 'do-not-reply@example.com',
:reply_to => 'reply-to-me@example.com',
:to => 'myself@me.com',
:cc => ['you@you.com', 'joe@bob.com', 'hello@goodbye.com'],
:bcc => ['test@example.com', 'sam@bob.com', 'goodbye@hello.com'],
:subject => 'This is spam',
:body => 'Every email is spam.'
}
end
@ -29,55 +30,53 @@ describe Shoulda::Matchers::ActionMailer::HaveSentEmailMatcher do
add_mail_to_deliveries(info)
end
after { ::ActionMailer::Base.deliveries.clear }
it "should send an e-mail based on subject" do
it 'sends an e-mail based on subject' do
should have_sent_email.with_subject{ info[:subject] }
end
it "should send an e-mail based on recipient" do
it 'sends an e-mail based on recipient' do
should have_sent_email.to(nil) { info[:to] }
end
it "should send an e-mail based on sender" do
it 'sends an e-mail based on sender' do
should have_sent_email.from{ info[:from] }
end
it "should send an e-email based on reply_to" do
it 'sends an e-email based on reply_to' do
should have_sent_email.reply_to { info[:reply_to] }
end
it "should send an e-mail based on cc" do
it 'sends an e-mail based on cc' do
should have_sent_email.cc{ info[:cc][0] }
end
it "should send an e-mail based on cc list" do
it 'sends an e-mail based on cc list' do
should have_sent_email.with_cc{ info[:cc] }
end
it "should send an e-mail based on bcc" do
it 'sends an e-mail based on bcc' do
should have_sent_email.bcc{ info[:bcc][0] }
end
it "should send an e-mail based on bcc list" do
it 'sends an e-mail based on bcc list' do
should have_sent_email.with_bcc{ info[:bcc] }
end
it "should send an e-mail based on body" do
it 'sends an e-mail based on body' do
should have_sent_email.with_body{ info[:body] }
end
end
context "testing with instance variables with multiple parts" do
context 'testing with instance variables with multiple parts' do
let(:info) do
{
:from => "do-not-reply@example.com",
:to => "myself@me.com",
:cc => ["you@you.com", "joe@bob.com", "hello@goodbye.com"],
:bcc => ["test@example.com", "sam@bob.com", "goodbye@hello.com"],
:subject => "This is spam",
:text => "Every email is spam.",
:html => "<h1>HTML is spam.</h1><p>Notably.</p>"
:from => 'do-not-reply@example.com',
:to => 'myself@me.com',
:cc => ['you@you.com', 'joe@bob.com', 'hello@goodbye.com'],
:bcc => ['test@example.com', 'sam@bob.com', 'goodbye@hello.com'],
:subject => 'This is spam',
:text => 'Every email is spam.',
:html => '<h1>HTML is spam.</h1><p>Notably.</p>'
}
end
@ -93,170 +92,164 @@ describe Shoulda::Matchers::ActionMailer::HaveSentEmailMatcher do
add_mail_to_deliveries(info)
end
after { ::ActionMailer::Base.deliveries.clear }
it "should send emails with text and html parts" do
it 'sends emails with text and html parts' do
should have_sent_email.with_part('text/plain') { info[:text] }.with_part('text/html') { info[:html] }
end
it "should have the block override the method argument" do
it 'should have the block override the method argument' do
should have_sent_email.with_part('text/plain', 'foo') { info[:text] }.with_part('text/html', /bar/) { info[:html] }
end
end
context "an email without multiple parts" do
context 'an email without multiple parts' do
before do
define_mailer :mailer, [:the_email] do
def the_email(params)
mail :from => "do-not-reply@example.com",
:to => "myself@me.com",
:subject => "This is spam",
:cc => ["you@you.com", "joe@bob.com", "hello@goodbye.com"],
:bcc => ["test@example.com", "sam@bob.com", "goodbye@hello.com"],
:body => "Every email is spam."
mail :from => 'do-not-reply@example.com',
:to => 'myself@me.com',
:subject => 'This is spam',
:cc => ['you@you.com', 'joe@bob.com', 'hello@goodbye.com'],
:bcc => ['test@example.com', 'sam@bob.com', 'goodbye@hello.com'],
:body => 'Every email is spam.'
end
end
add_mail_to_deliveries
end
after { ::ActionMailer::Base.deliveries.clear }
it "accepts sent-email when it is not multipart" do
it 'accepts sent-email when it is not multipart' do
should_not have_sent_email.multipart
matcher = have_sent_email.multipart(true)
matcher.matches?(Mailer.the_email(nil))
matcher.failure_message.should =~ /Expected sent email being multipart/
end
it "matches the body with a regexp" do
it 'matches the body with a regexp' do
should have_sent_email.with_body(/email is spam/)
end
it "matches the body with a string" do
should have_sent_email.with_body("Every email is spam.")
should_not have_sent_email.with_body("emails is")
it 'matches the body with a string' do
should have_sent_email.with_body('Every email is spam.')
should_not have_sent_email.with_body('emails is')
end
end
context "an email with both a text/plain and text/html part" do
context 'an email with both a text/plain and text/html part' do
before do
define_mailer :mailer, [:the_email] do
def the_email(params)
mail :from => "do-not-reply@example.com",
:to => "myself@me.com",
:cc => ["you@you.com", "joe@bob.com", "hello@goodbye.com"],
:bcc => ["test@example.com", "sam@bob.com", "goodbye@hello.com"],
:subject => "This is spam" do |format|
mail :from => 'do-not-reply@example.com',
:to => 'myself@me.com',
:cc => ['you@you.com', 'joe@bob.com', 'hello@goodbye.com'],
:bcc => ['test@example.com', 'sam@bob.com', 'goodbye@hello.com'],
:subject => 'This is spam' do |format|
format.text { render :text => "Every email is spam." }
format.html { render :text => "<h1>HTML is spam.</h1><p>Notably.</p>" }
format.text { render :text => 'Every email is spam.' }
format.html { render :text => '<h1>HTML is spam.</h1><p>Notably.</p>' }
end
end
end
add_mail_to_deliveries
end
after { ::ActionMailer::Base.deliveries.clear }
it "accepts sent e-mail based on the subject" do
it 'accepts sent e-mail based on the subject' do
should have_sent_email.with_subject(/is spam$/)
matcher = have_sent_email.with_subject(/totally safe/)
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email with subject/
end
it "accepts sent e-mail based on a string sender" do
it 'accepts sent e-mail based on a string sender' do
should have_sent_email.from('do-not-reply@example.com')
matcher = have_sent_email.from('you@example.com')
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email from/
end
it "accepts sent e-mail based on a regexp sender" do
it 'accepts sent e-mail based on a regexp sender' do
should have_sent_email.from(/@example\.com/)
matcher = have_sent_email.from(/you@/)
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email from/
end
it "accepts sent e-mail based on the body" do
it 'accepts sent e-mail based on the body' do
should have_sent_email.with_body(/is spam\./)
matcher = have_sent_email.with_body(/totally safe/)
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email with body/
end
it "accepts sent e-mail based on a text/plain part" do
it 'accepts sent e-mail based on a text/plain part' do
should have_sent_email.with_part('text/plain', /is spam\./)
matcher = have_sent_email.with_part('text/plain', /HTML is spam/)
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email with a text\/plain part containing/
end
it "accepts sent e-mail based on a text/html part" do
it 'accepts sent e-mail based on a text/html part' do
should have_sent_email.with_part('text/html', /HTML is spam/)
matcher = have_sent_email.with_part('text/html', /HTML is not spam\./)
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email with a text\/html part containing/
end
it "accept sent e-mail based on the recipient" do
it 'accept sent e-mail based on the recipient' do
should have_sent_email.to('myself@me.com')
matcher = have_sent_email.to('you@example.com')
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email to/
end
it "accepts sent e-mail based on cc string" do
it 'accepts sent e-mail based on cc string' do
should have_sent_email.cc('joe@bob.com')
matcher = have_sent_email.cc('you@example.com')
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email cc/
end
it "accepts sent-email based on cc regex" do
it 'accepts sent-email based on cc regex' do
should have_sent_email.cc(/@bob\.com/)
matcher = have_sent_email.cc(/us@/)
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email cc/
end
it "accepts sent e-mail based on cc list" do
it 'accepts sent e-mail based on cc list' do
should have_sent_email.with_cc(['you@you.com', 'joe@bob.com'])
matcher = have_sent_email.with_cc(['you@example.com'])
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email with cc/
end
it "accepts sent e-mail based on bcc string" do
should have_sent_email.bcc("goodbye@hello.com")
matcher = have_sent_email.bcc("test@hello.com")
it 'accepts sent e-mail based on bcc string' do
should have_sent_email.bcc('goodbye@hello.com')
matcher = have_sent_email.bcc('test@hello.com')
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email bcc/
end
it "accepts sent e-mail based on bcc regex" do
it 'accepts sent e-mail based on bcc regex' do
should have_sent_email.bcc(/@example\.com/)
matcher = have_sent_email.bcc(/you@/)
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email bcc/
end
it "accepts sent e-mail based on bcc list" do
it 'accepts sent e-mail based on bcc list' do
should have_sent_email.with_bcc(['sam@bob.com', 'test@example.com'])
matcher = have_sent_email.with_bcc(['you@you.com', 'joe@bob.com'])
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email with bcc/
end
it "accepts sent-email when it is multipart" do
it 'accepts sent-email when it is multipart' do
should have_sent_email.multipart
matcher = have_sent_email.multipart(false)
matcher.matches?(nil)
matcher.failure_message.should =~ /Expected sent email not being multipart/
end
it "lists all the deliveries within failure message" do
it 'lists all the deliveries within failure message' do
add_mail_to_deliveries
matcher = have_sent_email.to('you@example.com')
@ -264,7 +257,7 @@ describe Shoulda::Matchers::ActionMailer::HaveSentEmailMatcher do
matcher.failure_message.should =~ /Deliveries:\n"This is spam" to \["myself@me\.com"\]\n"This is spam" to \["myself@me\.com"\]/
end
it "allows chaining" do
it 'allows chaining' do
should have_sent_email.with_subject(/spam/).from('do-not-reply@example.com').with_body(/spam/).
with_part('text/plain', /is spam\./).with_part('text/html', /HTML is spam/).to('myself@me.com')
should_not have_sent_email.with_subject(/ham/).from('you@example.com').with_body(/ham/).
@ -272,22 +265,22 @@ describe Shoulda::Matchers::ActionMailer::HaveSentEmailMatcher do
end
end
context "testing multiple email deliveries at once" do
context 'testing multiple email deliveries at once' do
let(:info1) do
{
:from => "do-not-reply@example.com",
:to => "one@me.com",
:subject => "subject",
:body => "body"
:from => 'do-not-reply@example.com',
:to => 'one@me.com',
:subject => 'subject',
:body => 'body'
}
end
let(:info2) do
{
:from => "do-not-reply@example.com",
:to => "two@me.com",
:subject => "subject",
:body => "body"
:from => 'do-not-reply@example.com',
:to => 'two@me.com',
:subject => 'subject',
:body => 'body'
}
end
@ -301,33 +294,31 @@ describe Shoulda::Matchers::ActionMailer::HaveSentEmailMatcher do
add_mail_to_deliveries(info2)
end
after { ::ActionMailer::Base.deliveries.clear }
it "should send an e-mail based on recipient 1" do
should have_sent_email.to("one@me.com")
it 'sends an e-mail based on recipient 1' do
should have_sent_email.to('one@me.com')
end
it "should send an e-mail based on recipient 2" do
should have_sent_email.to("two@me.com")
it 'sends an e-mail based on recipient 2' do
should have_sent_email.to('two@me.com')
end
end
it "provides a detailed description of the e-mail expected to be sent" do
it 'provides a detailed description of the e-mail expected to be sent' do
matcher = have_sent_email
matcher.description.should == 'send an email'
matcher = matcher.with_subject("Welcome!")
matcher.description.should == 'send an email with a subject of "Welcome!"'
matcher = matcher.with_body("Welcome, human!")
matcher.description.should == 'send an email with a subject of "Welcome!" containing "Welcome, human!"'
matcher = matcher.with_part('text/plain', 'plain')
matcher.description.should == 'send an email with a subject of "Welcome!" containing "Welcome, human!" having a text/plain part containing "plain"'
matcher = matcher.with_subject('Welcome!')
matcher.description.should == %q(send an email with a subject of "Welcome!")
matcher = matcher.with_body('Welcome, human!')
matcher.description.should == %q(send an email with a subject of "Welcome!" containing "Welcome, human!")
matcher = matcher.with_part("text/plain", "plain")
matcher.description.should == %q(send an email with a subject of "Welcome!" containing "Welcome, human!" having a text/plain part containing "plain")
matcher = matcher.with_part('text/html', 'html')
matcher.description.should == 'send an email with a subject of "Welcome!" containing "Welcome, human!" having a text/plain part containing "plain" having a text/html part containing "html"'
matcher = matcher.from("alien@example.com")
matcher.description.should == 'send an email with a subject of "Welcome!" containing "Welcome, human!" having a text/plain part containing "plain" having a text/html part containing "html" from "alien@example.com"'
matcher = matcher.to("human@example.com")
matcher.description.should == 'send an email with a subject of "Welcome!" containing "Welcome, human!" having a text/plain part containing "plain" having a text/html part containing "html" from "alien@example.com" to "human@example.com"'
matcher = matcher.reply_to("reply-to-me@example.com")
matcher.description.should == 'send an email with a subject of "Welcome!" containing "Welcome, human!" having a text/plain part containing "plain" having a text/html part containing "html" from "alien@example.com" reply to "reply-to-me@example.com" to "human@example.com"'
matcher.description.should == %q(send an email with a subject of "Welcome!" containing "Welcome, human!" having a text/plain part containing "plain" having a text/html part containing "html")
matcher = matcher.from('alien@example.com')
matcher.description.should == %q(send an email with a subject of "Welcome!" containing "Welcome, human!" having a text/plain part containing "plain" having a text/html part containing "html" from "alien@example.com")
matcher = matcher.to('human@example.com')
matcher.description.should == %q(send an email with a subject of "Welcome!" containing "Welcome, human!" having a text/plain part containing "plain" having a text/html part containing "html" from "alien@example.com" to "human@example.com")
matcher = matcher.reply_to('reply-to-me@example.com')
matcher.description.should == %q(send an email with a subject of "Welcome!" containing "Welcome, human!" having a text/plain part containing "plain" having a text/html part containing "html" from "alien@example.com" reply to "reply-to-me@example.com" to "human@example.com")
end
end

View File

@ -1,115 +1,111 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::AllowMassAssignmentOfMatcher do
describe "#description" do
context '#description' do
context 'without a role' do
it 'includes the attribute name' do
matcher = Shoulda::Matchers::ActiveModel::AllowMassAssignmentOfMatcher.new(:attr)
matcher.description.should eq("allow mass assignment of attr")
described_class.new(:attr).description.should ==
'allow mass assignment of attr'
end
end
if active_model_3_1?
context 'with a role' do
it 'includes the attribute name and the role' do
matcher = Shoulda::Matchers::ActiveModel::AllowMassAssignmentOfMatcher.new(:attr).as(:admin)
matcher.description.should eq("allow mass assignment of attr as admin")
described_class.new(:attr).as(:admin).description.should ==
'allow mass assignment of attr as admin'
end
end
end
end
context "an attribute that is blacklisted from mass-assignment" do
let(:model) do
define_model(:example, :attr => :string) do
attr_protected :attr
context 'an attribute that is blacklisted from mass-assignment' do
it 'rejects being mass-assignable' do
model = define_model(:example, :blacklisted => :string) do
attr_protected :blacklisted
end.new
end
it "should reject being mass-assignable" do
model.should_not allow_mass_assignment_of(:attr)
model.should_not allow_mass_assignment_of(:blacklisted)
end
end
context "an attribute that is not whitelisted for mass-assignment" do
let(:model) do
define_model(:example, :attr => :string, :other => :string) do
attr_accessible :other
context 'an attribute that is not whitelisted for mass-assignment' do
it 'rejects being mass-assignable' do
model = define_model(:example, :not_whitelisted => :string,
:whitelisted => :string) do
attr_accessible :whitelisted
end.new
end
it "should reject being mass-assignable" do
model.should_not allow_mass_assignment_of(:attr)
model.should_not allow_mass_assignment_of(:not_whitelisted)
end
end
context "an attribute that is whitelisted for mass-assignment" do
let(:model) do
define_model(:example, :attr => :string) do
attr_accessible :attr
end.new
end
it "should accept being mass-assignable" do
model.should allow_mass_assignment_of(:attr)
context 'an attribute that is whitelisted for mass-assignment' do
it 'accepts being mass-assignable' do
define_model(:example, :whitelisted => :string) do
attr_accessible :whitelisted
end.new.should allow_mass_assignment_of(:whitelisted)
end
end
context "an attribute not included in the mass-assignment blacklist" do
let(:model) do
define_model(:example, :attr => :string, :other => :string) do
attr_protected :other
context 'an attribute not included in the mass-assignment blacklist' do
it 'accepts being mass-assignable' do
model = define_model(:example, :not_blacklisted => :string,
:blacklisted => :string) do
attr_protected :blacklisted
end.new
end
it "should accept being mass-assignable" do
model.should allow_mass_assignment_of(:attr)
model.should allow_mass_assignment_of(:not_blacklisted)
end
end
unless active_model_3_2?
context "an attribute on a class with no protected attributes" do
let(:model) { define_model(:example, :attr => :string).new }
it "should accept being mass-assignable" do
model.should allow_mass_assignment_of(:attr)
context 'an attribute on a class with no protected attributes' do
it 'accepts being mass-assignable' do
no_protected_attributes.should allow_mass_assignment_of(:attr)
end
it "should assign a negative failure message" do
it 'assigns a negative failure message' do
matcher = allow_mass_assignment_of(:attr)
matcher.matches?(model).should == true
matcher.matches?(no_protected_attributes).should be_true
matcher.negative_failure_message.should_not be_nil
end
end
def no_protected_attributes
define_model(:example, :attr => :string).new
end
end
context "an attribute on a class with all protected attributes" do
let(:model) do
define_model(:example, :attr => :string) do
attr_accessible
end.new
context 'an attribute on a class with all protected attributes' do
it 'rejects being mass-assignable' do
all_protected_attributes.should_not allow_mass_assignment_of(:attr)
end
it "should reject being mass-assignable" do
model.should_not allow_mass_assignment_of(:attr)
def all_protected_attributes
define_model(:example, :attr => :string) do
attr_accessible nil
end.new
end
end
if active_model_3_1?
context "an attribute included in the mass-assignment whitelist for admin role only" do
let(:model) do
context 'an attribute included in the mass-assignment whitelist for admin role only' do
it 'rejects being mass-assignable' do
mass_assignable_as_admin.should_not allow_mass_assignment_of(:attr)
end
it 'accepts being mass-assignable for admin' do
mass_assignable_as_admin.should allow_mass_assignment_of(:attr).as(:admin)
end
def mass_assignable_as_admin
define_model(:example, :attr => :string) do
attr_accessible :attr, :as => :admin
end.new
end
it "should reject being mass-assignable" do
model.should_not allow_mass_assignment_of(:attr)
end
it "should accept being mass-assignable for admin" do
model.should allow_mass_assignment_of(:attr).as(:admin)
end
end
end
end

View File

@ -1,47 +1,62 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::AllowValueMatcher do
context "an attribute with a format validation" do
let(:model) do
define_model :example, :attr => :string do
validates_format_of :attr, :with => /abc/
end.new
context "#description" do
it 'describes itself with multiple values' do
matcher = allow_value('foo', 'bar').for(:baz)
matcher.description.should == 'allow baz to be set to any of ["foo", "bar"]'
end
it "allows a good value" do
model.should allow_value("abcde").for(:attr)
it 'describes itself with a single value' do
matcher = allow_value('foo').for(:baz)
matcher.description.should == 'allow baz to be set to "foo"'
end
it "rejects a bad value" do
model.should_not allow_value("xyz").for(:attr)
end
if active_model_3_2?
it 'describes itself with a strict validation' do
strict_matcher = allow_value('xyz').for(:attr).strict
it "allows several good values" do
model.should allow_value("abcde", "deabc").for(:attr)
end
it "rejects several bad values" do
model.should_not allow_value("xyz", "zyx", nil, []).for(:attr)
strict_matcher.description.should ==
%q(doesn't raise when attr is set to "xyz")
end
end
end
context "an attribute with a format validation and a custom message" do
let(:model) do
define_model :example, :attr => :string do
validates_format_of :attr, :with => /abc/, :message => 'bad value'
end.new
context 'an attribute with a validation' do
it 'allows a good value' do
validating_format(:with => /abc/).should allow_value('abcde').for(:attr)
end
it "allows a good value" do
model.should allow_value('abcde').for(:attr).with_message(/bad/)
it 'rejects a bad value' do
validating_format(:with => /abc/).should_not allow_value('xyz').for(:attr)
end
it "rejects a bad value" do
model.should_not allow_value('xyz').for(:attr).with_message(/bad/)
it 'allows several good values' do
validating_format(:with => /abc/).should
allow_value('abcde', 'deabc').for(:attr)
end
it 'rejects several bad values' do
validating_format(:with => /abc/).should_not
allow_value('xyz', 'zyx', nil, []).for(:attr)
end
end
context "an attribute with several validations" do
context 'an attribute with a validation and a custom message' do
it 'allows a good value' do
validating_format(:with => /abc/, :message => 'bad value').should
allow_value('abcde').for(:attr).with_message(/bad/)
end
it 'rejects a bad value' do
validating_format(:with => /abc/, :message => 'bad value').should_not
allow_value('xyz').for(:attr).with_message(/bad/)
end
end
context 'an attribute with several validations' do
let(:model) do
define_model :example, :attr => :string do
validates_presence_of :attr
@ -50,10 +65,10 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher do
:less_than_or_equal_to => 50000
end.new
end
bad_values = [nil, "", "abc", "0", "50001", "123456", []]
bad_values = [nil, '', 'abc', '0', '50001', '123456', []]
it "allows a good value" do
model.should allow_value("12345").for(:attr)
it 'allows a good value' do
model.should allow_value('12345').for(:attr)
end
bad_values.each do |bad_value|
@ -62,70 +77,48 @@ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher do
end
end
it "rejects bad values (#{bad_values.map(&:inspect).join(', ')})" do
it "rejects several bad values (#{bad_values.map(&:inspect).join(', ')})" do
model.should_not allow_value(*bad_values).for(:attr)
end
end
context "an AllowValueMatcher with multiple values" do
it "should describe itself" do
matcher = allow_value("foo", "bar").for(:baz)
matcher.description.should == 'allow baz to be set to any of ["foo", "bar"]'
end
end
context "an AllowValueMatcher with a single value" do
it "should describe itself" do
matcher = allow_value("foo").for(:baz)
matcher.description.should eq('allow baz to be set to "foo"')
end
it "allows you to call description before calling matches?" do
context 'with a single value' do
it 'allows you to call description before calling matches?' do
model = define_model(:example, :attr => :string).new
matcher = Shoulda::Matchers::ActiveModel::AllowValueMatcher.new("foo").for(:attr)
matcher = described_class.new('foo').for(:attr)
matcher.description
expect { matcher.matches?(model) }.not_to raise_error
expect { matcher.matches?(model) }.not_to raise_error(NoMethodError)
end
end
context "an AllowValueMatcher with no values" do
it "raises an error" do
lambda do
allow_value.for(:baz)
end.should raise_error(ArgumentError, /at least one argument/)
context 'with no values' do
it 'raises an error' do
expect { allow_value.for(:baz) }.to
raise_error(ArgumentError, /at least one argument/)
end
end
if Rails::VERSION::STRING.to_f >= 3.2
context "an attribute with a strict format validation" do
let(:model) do
define_model :example, :attr => :string do
validates_format_of :attr, :with => /abc/, :strict => true
end.new
if active_model_3_2?
context 'an attribute with a strict format validation' do
it 'strictly rejects a bad value' do
validating_format(:with => /abc/, :strict => true).should_not
allow_value('xyz').for(:attr).strict
end
it "strictly rejects a bad value" do
model.should_not allow_value("xyz").for(:attr).strict
it 'strictly allows a bad value with a different message' do
validating_format(:with => /abc/, :strict => true).should
allow_value('xyz').for(:attr).with_message(/abc/).strict
end
it "strictly allows a bad value with a different message" do
model.should allow_value("xyz").for(:attr).with_message(/abc/).strict
end
it 'provides a useful negative failure message' do
matcher = allow_value('xyz').for(:attr).strict.with_message(/abc/)
it "describes itself" do
allow_value("xyz").for(:attr).strict.description.
should == %{doesn't raise when attr is set to "xyz"}
end
matcher.matches?(validating_format(:with => /abc/, :strict => true))
it "provides a useful negative failure message" do
matcher = allow_value("xyz").for(:attr).strict.with_message(/abc/)
matcher.matches?(model)
matcher.negative_failure_message.
should == 'Expected exception to include /abc/ ' +
'when attr is set to "xyz", got Attr is invalid'
matcher.negative_failure_message.should == 'Expected exception to include /abc/ ' +
'when attr is set to "xyz", got Attr is invalid'
end
end
end
end

View File

@ -1,65 +1,43 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::DisallowValueMatcher do
it "does not allow any types" do
matcher = Shoulda::Matchers::ActiveModel::DisallowValueMatcher.new("abcde")
matcher.allowed_types.should == ""
it 'does not allow any types' do
matcher('abcde').allowed_types.should == ''
end
context "an attribute with a format validation" do
before do
define_model :example, :attr => :string do
validates_format_of :attr, :with => /abc/
end
@model = Example.new
context 'an attribute with a format validation' do
it 'does not match if the value is allowed' do
validating_format(:with => /abc/).should_not matcher('abcde').for(:attr)
end
it "does not match if the value is allowed" do
matcher = new_matcher("abcde")
matcher.for(:attr)
matcher.matches?(@model).should be_false
end
it "matches if the value is not allowed" do
matcher = new_matcher("xyz")
matcher.for(:attr)
matcher.matches?(@model).should be_true
it 'matches if the value is not allowed' do
validating_format(:with => /abc/).should matcher('xyz').for(:attr)
end
end
context "an attribute with a format validation and a custom message" do
before do
define_model :example, :attr => :string do
validates_format_of :attr, :with => /abc/, :message => 'good message'
end
@model = Example.new
end
it "does not match if the value and message are both correct" do
matcher = new_matcher("abcde")
matcher.for(:attr).with_message('good message')
matcher.matches?(@model).should be_false
context 'an attribute with a format validation and a custom message' do
it 'does not match if the value and message are both correct' do
validating_format(:with => /abc/, :message => 'good message').should_not
matcher('abcde').for(:attr).with_message('good message')
end
it "delegates its failure message to its allow matcher's negative failure message" do
allow_matcher = stub_everything(:negative_failure_message => "allow matcher failure")
allow_matcher = stub_everything(:negative_failure_message => 'allow matcher failure')
Shoulda::Matchers::ActiveModel::AllowValueMatcher.stubs(:new).returns(allow_matcher)
matcher = new_matcher("abcde")
matcher.for(:attr).with_message('good message')
matcher.matches?(@model)
matcher = matcher('abcde').for(:attr).with_message('good message')
matcher.matches?(validating_format(:with => /abc/, :message => 'good message'))
matcher.failure_message.should == "allow matcher failure"
matcher.failure_message.should == 'allow matcher failure'
end
it "matches if the message is correct but the value is not" do
matcher = new_matcher("xyz")
matcher.for(:attr).with_message('good message')
matcher.matches?(@model).should be_true
it 'matches if the message is correct but the value is not' do
validating_format(:with => /abc/, :message => 'good message').should
matcher('xyz').for(:attr).with_message('good message')
end
end
def new_matcher(value)
matcher = Shoulda::Matchers::ActiveModel::DisallowValueMatcher.new(value)
def matcher(value)
described_class.new(value)
end
end

View File

@ -1,79 +1,68 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::EnsureExclusionOfMatcher do
context "an attribute which must be excluded of a range" do
before do
@model = define_model(:example, :attr => :integer) do
validates_exclusion_of :attr, :in => 2..5
end.new
context 'an attribute which must be excluded from a range' do
it 'accepts ensuring the correct range' do
validating_exclusion(:in => 2..5).should
ensure_exclusion_of(:attr).in_range(2..5)
end
it "should accept ensuring the correct range" do
@model.should ensure_exclusion_of(:attr).in_range(2..5)
it 'rejects ensuring excluded value' do
validating_exclusion(:in => 2..5).should_not
ensure_exclusion_of(:attr).in_range(2..6)
end
it "should reject ensuring excluded value" do
@model.should_not ensure_exclusion_of(:attr).in_range(2..6)
end
it "should not override the default message with a blank" do
@model.should ensure_exclusion_of(:attr).in_range(2..5).with_message(nil)
it 'does not override the default message with a blank' do
validating_exclusion(:in => 2..5).should
ensure_exclusion_of(:attr).in_range(2..5).with_message(nil)
end
end
context "an attribute with a custom ranged value validation" do
before do
@model = define_model(:example, :attr => :string) do
validates_exclusion_of :attr, :in => 2..4, :message => 'not good'
end.new
end
it "should accept ensuring the correct range" do
@model.should ensure_exclusion_of(:attr).in_range(2..4).with_message(/not good/)
context 'an attribute with a custom validation message' do
it 'accepts ensuring the correct range' do
validating_exclusion(:in => 2..4, :message => 'not good').should
ensure_exclusion_of(:attr).in_range(2..4).with_message(/not good/)
end
end
context "an attribute with custom range validations" do
before do
define_model :example, :attr => :integer do
validate :custom_validation
def custom_validation
if attr >= 2 && attr <= 5
errors.add(:attr, 'shoud be out of this range')
end
context 'an attribute with custom range validations' do
it 'accepts ensuring the correct range and messages' do
model = custom_validation do
if attr >= 2 && attr <= 5
errors.add(:attr, 'should be out of this range')
end
end
@model = Example.new
end
it "should accept ensuring the correct range and messages" do
@model.should ensure_exclusion_of(:attr).in_range(2..5).with_message(/shoud be out of this range/)
model.should ensure_exclusion_of(:attr).in_range(2..5).
with_message(/should be out of this range/)
end
end
context "an attribute which must be excluded in an array" do
before do
@model = define_model(:example, :attr => :string) do
validates_exclusion_of :attr, :in => %w(one two)
end.new
context 'an attribute which must be excluded from an array' do
it 'accepts with correct array' do
validating_exclusion(:in => %w(one two)).should
ensure_exclusion_of(:attr).in_array(%w(one two))
end
it "accepts with correct array" do
@model.should ensure_exclusion_of(:attr).in_array(%w(one two))
it 'rejects when only part of array matches' do
validating_exclusion(:in => %w(one two)).should_not
ensure_exclusion_of(:attr).in_array(%w(one wrong_value))
end
it "rejects when only part of array matches" do
@model.should_not ensure_exclusion_of(:attr).in_array(%w(one wrong_value))
it 'rejects when array does not match at all' do
validating_exclusion(:in => %w(one two)).should_not
ensure_exclusion_of(:attr).in_array(%w(cat dog))
end
it "rejects when array doesn't match at all" do
@model.should_not ensure_exclusion_of(:attr).in_array(%w(cat dog))
it 'has correct description' do
ensure_exclusion_of(:attr).in_array([true, 'dog']).description.should ==
'ensure exclusion of attr in [true, "dog"]'
end
end
it "has correct description" do
ensure_exclusion_of(:attr).in_array([true, 'dog']).description.should == 'ensure exclusion of attr in [true, "dog"]'
end
def validating_exclusion(options)
define_model(:example, :attr => :integer) do
validates_exclusion_of :attr, options
end.new
end
end

View File

@ -1,181 +1,171 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::EnsureInclusionOfMatcher do
context "with no validations" do
before do
@model = define_model(:example, :attr => :string) do
end.new
end
it "should reject an array which does not have a validator defined" do
@model.should_not ensure_inclusion_of(:attr).in_array(%w(Yes No))
context 'with no validations' do
it 'rejects an array which does not have a validator defined' do
define_model(:example, :attr => :string).new.should_not
ensure_inclusion_of(:attr).in_array(%w(Yes No))
end
end
context "with true/false values" do
it "can verify outside values to ensure the negative case" do
model = define_model(:example, :attr => :string).new
model.should_not ensure_inclusion_of(:attr).in_array([true, false])
context 'with true/false values' do
it 'can verify outside values to ensure the negative case' do
define_model(:example, :attr => :string).new.should_not
ensure_inclusion_of(:attr).in_array([true, false])
end
end
context "where we cannot determine a value outside the array" do
it "should raise a custom exception" do
context 'where we cannot determine a value outside the array' do
it 'raises a custom exception' do
model = define_model(:example, :attr => :string).new
arbitrary_string = Shoulda::Matchers::ActiveModel::EnsureInclusionOfMatcher::ARBITRARY_OUTSIDE_STRING
arbitrary_string = described_class::ARBITRARY_OUTSIDE_STRING
expect { model.should ensure_inclusion_of(:attr).in_array([arbitrary_string]) }.to raise_error Shoulda::Matchers::ActiveModel::CouldNotDetermineValueOutsideOfArray
end
end
context "an attribute which must be included in a range" do
before do
@model = define_model(:example, :attr => :integer) do
validates_inclusion_of :attr, :in => 2..5
end.new
context 'an attribute which must be included in a range' do
it 'accepts ensuring the correct range' do
validating_inclusion(:in => 2..5).should
ensure_inclusion_of(:attr).in_range(2..5)
end
it "should accept ensuring the correct range" do
@model.should ensure_inclusion_of(:attr).in_range(2..5)
it 'rejects ensuring a lower minimum value' do
validating_inclusion(:in => 2..5).should_not
ensure_inclusion_of(:attr).in_range(1..5)
end
it "should reject ensuring a lower minimum value" do
@model.should_not ensure_inclusion_of(:attr).in_range(1..5)
it 'rejects ensuring a higher minimum value' do
validating_inclusion(:in => 2..5).should_not
ensure_inclusion_of(:attr).in_range(3..5)
end
it "should reject ensuring a higher minimum value" do
@model.should_not ensure_inclusion_of(:attr).in_range(3..5)
it 'rejects ensuring a lower maximum value' do
validating_inclusion(:in => 2..5).should_not
ensure_inclusion_of(:attr).in_range(2..4)
end
it "should reject ensuring a lower maximum value" do
@model.should_not ensure_inclusion_of(:attr).in_range(2..4)
it 'rejects ensuring a higher maximum value' do
validating_inclusion(:in => 2..5).should_not
ensure_inclusion_of(:attr).in_range(2..6)
end
it "should reject ensuring a higher maximum value" do
@model.should_not ensure_inclusion_of(:attr).in_range(2..6)
end
it "should not override the default message with a blank" do
@model.should ensure_inclusion_of(:attr).in_range(2..5).with_message(nil)
it 'does not override the default message with a blank' do
validating_inclusion(:in => 2..5).should
ensure_inclusion_of(:attr).in_range(2..5).with_message(nil)
end
end
context "an attribute with a custom ranged value validation" do
before do
@model = define_model(:example, :attr => :string) do
validates_inclusion_of :attr, :in => 2..4, :message => 'not good'
end.new
end
it "should accept ensuring the correct range" do
@model.should ensure_inclusion_of(:attr).in_range(2..4).with_message(/not good/)
context 'an attribute with a custom ranged value validation' do
it 'accepts ensuring the correct range' do
validating_inclusion(:in => 2..4, :message => 'not good').should
ensure_inclusion_of(:attr).in_range(2..4).with_message(/not good/)
end
end
context "an attribute with custom range validations" do
before do
define_model :example, :attr => :integer do
validate :custom_validation
def custom_validation
if attr < 2
errors.add(:attr, 'too low')
elsif attr > 5
errors.add(:attr, 'too high')
end
context 'an attribute with custom range validations' do
it 'accepts ensuring the correct range and messages' do
model = custom_validation do
if attr < 2
errors.add(:attr, 'too low')
elsif attr > 5
errors.add(:attr, 'too high')
end
end
@model = Example.new
end
it "should accept ensuring the correct range and messages" do
@model.should ensure_inclusion_of(:attr).in_range(2..5).with_low_message(/low/).with_high_message(/high/)
model.should ensure_inclusion_of(:attr).in_range(2..5).
with_low_message(/low/).with_high_message(/high/)
end
end
context "an attribute which must be included in an array" do
before do
@model = define_model(:example, :attr => :string) do
validates_inclusion_of :attr, :in => %w(one two)
end.new
context 'an attribute which must be included in an array' do
it 'accepts with correct array' do
validating_inclusion(:in => %w(one two)).should
ensure_inclusion_of(:attr).in_array(%w(one two))
end
it "accepts with correct array" do
@model.should ensure_inclusion_of(:attr).in_array(%w(one two))
it 'rejects when only part of array matches' do
validating_inclusion(:in => %w(one two)).should_not
ensure_inclusion_of(:attr).in_array(%w(one wrong_value))
end
it "rejects when only part of array matches" do
@model.should_not ensure_inclusion_of(:attr).in_array(%w(one wrong_value))
it 'rejects when array does not match at all' do
validating_inclusion(:in => %w(one two)).should_not
ensure_inclusion_of(:attr).in_array(%w(cat dog))
end
it "rejects when array doesn't match at all" do
@model.should_not ensure_inclusion_of(:attr).in_array(%w(cat dog))
it 'has correct description' do
ensure_inclusion_of(:attr).in_array([true, "dog"]).description.should ==
'ensure inclusion of attr in [true, "dog"]'
end
it "has correct description" do
ensure_inclusion_of(:attr).in_array([true, 'dog']).description.should == 'ensure inclusion of attr in [true, "dog"]'
it 'rejects allow_blank' do
validating_inclusion(:in => %w(one two)).should_not
ensure_inclusion_of(:attr).in_array(%w(one two)).allow_blank(true)
end
it "rejects allow_blank" do
@model.should_not ensure_inclusion_of(:attr).in_array(['one', 'two']).allow_blank(true)
@model.should ensure_inclusion_of(:attr).in_array(['one', 'two']).allow_blank(false)
it 'accepts allow_blank(false)' do
validating_inclusion(:in => %w(one two)).should
ensure_inclusion_of(:attr).in_array(%w(one two)).allow_blank(false)
end
it "rejects allow_nil" do
@model.should_not ensure_inclusion_of(:attr).in_array(['one', 'two']).allow_nil(true)
@model.should ensure_inclusion_of(:attr).in_array(['one', 'two']).allow_nil(false)
it 'rejects allow_nil' do
validating_inclusion(:in => %w(one two)).should_not
ensure_inclusion_of(:attr).in_array(%w(one two)).allow_nil(true)
end
it 'accepts allow_nil(false)' do
validating_inclusion(:in => %w(one two)).should
ensure_inclusion_of(:attr).in_array(%w(one two)).allow_nil(false)
end
end
context "allowed blank and allowed nil" do
before do
@model = define_model(:example, :attr => :string) do
validates_inclusion_of :attr, :in => %w(one two), :allow_blank => true, :allow_nil => true
end.new
context 'with allowed blank and allowed nil' do
it 'accepts allow_blank' do
validating_inclusion(:in => %w(one two), :allow_blank => true).should
ensure_inclusion_of(:attr).in_array(%w(one two)).allow_blank
end
it "allows allow_blank" do
@model.should ensure_inclusion_of(:attr).in_array(['one', 'two']).allow_blank(true)
@model.should ensure_inclusion_of(:attr).in_array(['one', 'two']).allow_blank()
@model.should_not ensure_inclusion_of(:attr).in_array(['one', 'two']).allow_blank(false)
it 'rejects allow_blank(false)' do
validating_inclusion(:in => %w(one two), :allow_blank => true).should_not
ensure_inclusion_of(:attr).in_array(%w(one two)).allow_blank(false)
end
it "allows allow_nil" do
@model.should ensure_inclusion_of(:attr).in_array(['one', 'two']).allow_nil(true)
@model.should ensure_inclusion_of(:attr).in_array(['one', 'two']).allow_nil()
@model.should_not ensure_inclusion_of(:attr).in_array(['one', 'two']).allow_nil(false)
it 'accepts allow_nil' do
validating_inclusion(:in => %w(one two), :allow_nil => true).should
ensure_inclusion_of(:attr).in_array(%w(one two)).allow_nil
end
it 'rejects allow_nil' do
validating_inclusion(:in => %w(one two), :allow_nil => true).should_not
ensure_inclusion_of(:attr).in_array(%w(one two)).allow_nil(false)
end
end
context "an attribute allowing some blank values but not others" do
before do
@model = define_model(:example, :attr => :string) do
validates_inclusion_of :attr, :in => ['one', 'two', '']
end.new
end
it "rejects allow_blank" do
@model.should_not ensure_inclusion_of(:attr).in_array(['one', 'two', '']).allow_blank(true)
@model.should ensure_inclusion_of(:attr).in_array(['one', 'two', '']).allow_blank(false)
context 'an attribute allowing some blank values but not others' do
it 'rejects allow_blank' do
validating_inclusion(:in => ['one', 'two', '']).should_not
ensure_inclusion_of(:attr).in_array(['one', 'two', '']).allow_blank(true)
end
end
if Rails::VERSION::STRING.to_f >= 3.2
context "a strict attribute which must be included in a range" do
before do
@model = define_model(:example, :attr => :integer) do
validates_inclusion_of :attr, :in => 2..5, :strict => true
end.new
if active_model_3_2?
context 'a strict attribute which must be included in a range' do
it 'accepts ensuring the correct range' do
validating_inclusion(:in => 2..5, :strict => true).should
ensure_inclusion_of(:attr).in_range(2..5).strict
end
it "should accept ensuring the correct range" do
@model.should ensure_inclusion_of(:attr).in_range(2..5).strict
end
it "should not accept ensuring another range" do
@model.should_not ensure_inclusion_of(:attr).in_range(2..6).strict
it 'rejects ensuring another range' do
validating_inclusion(:in => 2..5, :strict => true).should_not
ensure_inclusion_of(:attr).in_range(2..6).strict
end
end
end
def validating_inclusion(options)
define_model(:example, :attr => :integer) do
validates_inclusion_of :attr, options
end.new
end
end

View File

@ -1,138 +1,112 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::EnsureLengthOfMatcher do
context "an attribute with a non-zero minimum length validation" do
before do
@model = define_model(:example, :attr => :string) do
validates_length_of :attr, :minimum => 4
end.new
context 'an attribute with a non-zero minimum length validation' do
it 'accepts ensuring the correct minimum length' do
validating_length(:minimum => 4).should
ensure_length_of(:attr).is_at_least(4)
end
it "should accept ensuring the correct minimum length" do
@model.should ensure_length_of(:attr).is_at_least(4)
it 'rejects ensuring a lower minimum length with any message' do
validating_length(:minimum => 4).should_not
ensure_length_of(:attr).is_at_least(3).with_short_message(/.*/)
end
it "should reject ensuring a lower minimum length with any message" do
@model.should_not ensure_length_of(:attr).is_at_least(3).with_short_message(/.*/)
it 'rejects ensuring a higher minimum length with any message' do
validating_length(:minimum => 4).should_not
ensure_length_of(:attr).is_at_least(5).with_short_message(/.*/)
end
it "should reject ensuring a higher minimum length with any message" do
@model.should_not ensure_length_of(:attr).is_at_least(5).with_short_message(/.*/)
end
it "should not override the default message with a blank" do
@model.should ensure_length_of(:attr).is_at_least(4).with_short_message(nil)
it 'does not override the default message with a blank' do
validating_length(:minimum => 4).should
ensure_length_of(:attr).is_at_least(4).with_short_message(nil)
end
end
context "an attribute with a minimum length validation of 0" do
before do
@model = define_model(:example, :attr => :string) do
validates_length_of :attr, :minimum => 0
end.new
context 'an attribute with a minimum length validation of 0' do
it 'accepts ensuring the correct minimum length' do
validating_length(:minimum => 0).should
ensure_length_of(:attr).is_at_least(0) end
end
context 'an attribute with a maximum length' do
it 'accepts ensuring the correct maximum length' do
validating_length(:maximum => 4).should
ensure_length_of(:attr).is_at_most(4)
end
it "should accept ensuring the correct minimum length" do
@model.should ensure_length_of(:attr).is_at_least(0)
it 'rejects ensuring a lower maximum length with any message' do
validating_length(:maximum => 4).should_not
ensure_length_of(:attr).is_at_most(3).with_long_message(/.*/)
end
it 'rejects ensuring a higher maximum length with any message' do
validating_length(:maximum => 4).should_not
ensure_length_of(:attr).is_at_most(5).with_long_message(/.*/)
end
it 'does not override the default message with a blank' do
validating_length(:maximum => 4).should
ensure_length_of(:attr).is_at_most(4).with_long_message(nil)
end
end
context "an attribute with a maximum length" do
before do
@model = define_model(:example, :attr => :string) do
validates_length_of :attr, :maximum => 4
end.new
context 'an attribute with a required exact length' do
it 'accepts ensuring the correct length' do
validating_length(:is => 4).should ensure_length_of(:attr).is_equal_to(4)
end
it "should accept ensuring the correct maximum length" do
@model.should ensure_length_of(:attr).is_at_most(4)
it 'rejects ensuring a lower maximum length with any message' do
validating_length(:is => 4).should_not
ensure_length_of(:attr).is_equal_to(3).with_message(/.*/)
end
it "should reject ensuring a lower maximum length with any message" do
@model.should_not ensure_length_of(:attr).is_at_most(3).with_long_message(/.*/)
it 'rejects ensuring a higher maximum length with any message' do
validating_length(:is => 4).should_not
ensure_length_of(:attr).is_equal_to(5).with_message(/.*/)
end
it "should reject ensuring a higher maximum length with any message" do
@model.should_not ensure_length_of(:attr).is_at_most(5).with_long_message(/.*/)
end
it "should not override the default message with a blank" do
@model.should ensure_length_of(:attr).is_at_most(4).with_long_message(nil)
it 'does not override the default message with a blank' do
validating_length(:is => 4).should
ensure_length_of(:attr).is_equal_to(4).with_message(nil)
end
end
context "an attribute with a required exact length" do
before do
@model = define_model(:example, :attr => :string) do
validates_length_of :attr, :is => 4
end.new
end
it "should accept ensuring the correct length" do
@model.should ensure_length_of(:attr).is_equal_to(4)
end
it "should reject ensuring a lower maximum length with any message" do
@model.should_not ensure_length_of(:attr).is_equal_to(3).with_message(/.*/)
end
it "should reject ensuring a higher maximum length with any message" do
@model.should_not ensure_length_of(:attr).is_equal_to(5).with_message(/.*/)
end
it "should not override the default message with a blank" do
@model.should ensure_length_of(:attr).is_equal_to(4).with_message(nil)
end
end
context "an attribute with a required exact length and another validation" do
before do
@model = define_model(:example, :attr => :string) do
context 'an attribute with a required exact length and another validation' do
it 'accepts ensuring the correct length' do
model = define_model(:example, :attr => :string) do
validates_length_of :attr, :is => 4
validates_numericality_of :attr
end.new
end
it "should accept ensuring the correct length" do
@model.should ensure_length_of(:attr).is_equal_to(4)
model.should ensure_length_of(:attr).is_equal_to(4)
end
end
context "an attribute with a custom minimum length validation" do
before do
@model = define_model(:example, :attr => :string) do
validates_length_of :attr, :minimum => 4, :too_short => 'short'
end.new
end
it "should accept ensuring the correct minimum length" do
@model.should ensure_length_of(:attr).is_at_least(4).with_short_message(/short/)
end
end
context "an attribute with a custom maximum length validation" do
before do
@model = define_model(:example, :attr => :string) do
validates_length_of :attr, :maximum => 4, :too_long => 'long'
end.new
end
it "should accept ensuring the correct minimum length" do
@model.should ensure_length_of(:attr).is_at_most(4).with_long_message(/long/)
end
end
context "an attribute without a length validation" do
before do
@model = define_model(:example, :attr => :string).new
end
it "should reject ensuring a minimum length" do
@model.should_not ensure_length_of(:attr).is_at_least(1)
context 'an attribute with a custom minimum length validation' do
it 'accepts ensuring the correct minimum length' do
validating_length(:minimum => 4, :too_short => 'foobar').should
ensure_length_of(:attr).is_at_least(4).with_short_message(/foo/)
end
end
context 'an attribute with a custom maximum length validation' do
it 'accepts ensuring the correct minimum length' do
validating_length(:maximum => 4, :too_long => 'foobar').should
ensure_length_of(:attr).is_at_most(4).with_long_message(/foo/)
end
end
context 'an attribute without a length validation' do
it 'rejects ensuring a minimum length' do
define_model(:example, :attr => :string).new.should_not
ensure_length_of(:attr).is_at_least(1)
end
end
def validating_length(options = {})
define_model(:example, :attr => :string) do
validates_length_of :attr, options
end.new
end
end

View File

@ -1,14 +1,14 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::ExceptionMessageFinder do
if Rails::VERSION::STRING.to_f >= 3.2
if active_model_3_2?
context '#allow_description' do
it 'describes its attribute' do
finder = build_finder(:attribute => :attr)
description = finder.allow_description('allowed values')
description.should == "doesn't raise when attr is set to allowed values"
description.should == %q(doesn't raise when attr is set to allowed values)
end
end

View File

@ -1,129 +1,140 @@
# encoding: UTF-8
require "spec_helper"
def store_translations(options = {:without => []})
options[:without] = Array.wrap(options[:without] || [])
translations = {
:activerecord => {
:errors => {
:models => {
:example => {
:attributes => {
:attr => {}
}
}
},
:messages => {}
}
},
:errors => {
:attributes => {
:attr => {}
},
:messages => {}
}
}
unless options[:without].include?(:model_attribute)
translations[:activerecord][:errors][:models][:example][:attributes][:attr][:blank] = "Don't you do that to me!"
translations[:activerecord][:errors][:models][:example][:attributes][:attr][:wrong_length] = "Don't you do that to me!"
end
unless options[:without].include?(:model)
translations[:activerecord][:errors][:models][:example][:blank] = 'Give it one more try!'
translations[:activerecord][:errors][:models][:example][:wrong_length] = 'Give it one more try!'
end
unless options[:without].include?(:message)
translations[:activerecord][:errors][:messages][:blank] = 'Oh no!'
translations[:activerecord][:errors][:messages][:wrong_length] = 'Oh no!'
end
unless options[:without].include?(:attribute)
translations[:errors][:attributes][:attr][:blank] = 'Seriously?'
translations[:errors][:attributes][:attr][:wrong_length] = 'Seriously?'
end
I18n.backend.store_translations(:en, translations)
end
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::Helpers do
include Shoulda::Matchers::ActiveModel
after { I18n.backend.reload! }
describe "default_error_message" do
before do
define_model :example, :attr => :string do
validates_presence_of :attr
validates_length_of :attr, :is => 40, :allow_blank => true
end
@model = Example.new
end
after { I18n.backend.reload! }
context "if the translation for the model attributes error exists" do
it "provides the right error message for validate_presence_of" do
describe 'default_error_message' do
context 'if the translation for the model attributes error exists' do
it 'provides the right error message for validate_presence_of' do
store_translations
@model.should validate_presence_of(:attr)
assert_presence_validation_has_correct_message
end
it "provides the right error message for validates_length_of" do
it 'provides the right error message for validates_length_of' do
store_translations
@model.should ensure_length_of(:attr).is_equal_to(40)
assert_length_validation_has_correct_message
end
end
context "if no translation for the model attributes error exists" do
context "and the translation for the models error exists" do
it "provides the right error message for validate_presence_of" do
context 'if no translation for the model attributes error exists' do
context 'and the translation for the models error exists' do
it 'provides the right error message for validate_presence_of' do
store_translations(:without => :model_attribute)
@model.should validate_presence_of(:attr)
assert_presence_validation_has_correct_message
end
it "provides the right error message for validates_length_of" do
it 'provides the right error message for validates_length_of' do
store_translations(:without => :model_attribute)
@model.should ensure_length_of(:attr).is_equal_to(40)
assert_length_validation_has_correct_message
end
end
context "and no translation for the models error exists" do
context "and the translation for the message exists" do
it "provides the right error message for validate_presence_of" do
context 'and no translation for the models error exists' do
context 'and the translation for the message exists' do
it 'provides the right error message for validate_presence_of' do
store_translations(:without => [:model_attribute, :model])
@model.should validate_presence_of(:attr)
assert_presence_validation_has_correct_message
end
it "provides the right error message for validates_length_of" do
it 'provides the right error message for validates_length_of' do
store_translations(:without => [:model_attribute, :model])
@model.should ensure_length_of(:attr).is_equal_to(40)
assert_length_validation_has_correct_message
end
end
context "and no translation for the message exists" do
context "and the translation for the attribute exists" do
it "provides the right error message for validate_presence_of" do
context 'and no translation for the message exists' do
context 'and the translation for the attribute exists' do
it 'provides the right error message for validate_presence_of' do
store_translations(:without => [:model_attribute, :model, :message])
@model.should validate_presence_of(:attr)
assert_presence_validation_has_correct_message
end
it "provides the right error message for validates_length_of" do
it 'provides the right error message for validates_length_of' do
store_translations(:without => [:model_attribute, :model, :message])
@model.should ensure_length_of(:attr).is_equal_to(40)
assert_length_validation_has_correct_message
end
end
context "and no translation for the attribute exists" do
it "provides the general error message for validate_presence_of" do
@model.should validate_presence_of(:attr)
context 'and no translation for the attribute exists' do
it 'provides the general error message for validate_presence_of' do
assert_presence_validation_has_correct_message
end
it "provides the general error message for validates_length_of" do
@model.should ensure_length_of(:attr).is_equal_to(40)
it 'provides the general error message for validates_length_of' do
assert_length_validation_has_correct_message
end
end
end
end
end
end
def assert_presence_validation_has_correct_message
define_model :example, :attr => :string do
validates_presence_of :attr
end.new.should validate_presence_of(:attr)
end
def assert_length_validation_has_correct_message
define_model :example, :attr => :string do
validates_length_of :attr, :is => 40, :allow_blank => true
end.new.should ensure_length_of(:attr).is_equal_to(40)
end
def store_translations(options = {:without => []})
options[:without] = Array.wrap(options[:without] || [])
translations = {
:activerecord => {
:errors => {
:models => {
:example => {
:attributes => {
:attr => {}
}
}
},
:messages => {}
}
},
:errors => {
:attributes => {
:attr => {}
},
:messages => {}
}
}
unless options[:without].include?(:model_attribute)
translations[:activerecord][:errors][:models][:example][:attributes][:attr][:blank] = "Don't you do that to me!"
translations[:activerecord][:errors][:models][:example][:attributes][:attr][:wrong_length] = "Don't you do that to me!"
end
unless options[:without].include?(:model)
translations[:activerecord][:errors][:models][:example][:blank] = 'Give it one more try!'
translations[:activerecord][:errors][:models][:example][:wrong_length] = 'Give it one more try!'
end
unless options[:without].include?(:message)
translations[:activerecord][:errors][:messages][:blank] = 'Oh no!'
translations[:activerecord][:errors][:messages][:wrong_length] = 'Oh no!'
end
unless options[:without].include?(:attribute)
translations[:errors][:attributes][:attr][:blank] = 'Seriously?'
translations[:errors][:attributes][:attr][:wrong_length] = 'Seriously?'
end
I18n.backend.store_translations(:en, translations)
end
end

View File

@ -1,69 +1,54 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::OnlyIntegerMatcher do
context "given an attribute that only allows integer values" do
before do
define_model :example, :attr => :string do
validates_numericality_of :attr, { :only_integer => true }
end
@model = Example.new
context 'given an attribute that only allows integer values' do
it 'matches' do
only_integer.should new_matcher
end
it "matches" do
matcher = new_matcher(:attr)
matcher.matches?(@model).should be_true
it 'allows integer types' do
new_matcher.allowed_types.should == 'integer'
end
it "allows integer types" do
matcher = new_matcher(:attr)
matcher.allowed_types.should == "integer"
end
it "returns itself when given a message" do
matcher = new_matcher(:attr)
matcher.with_message("some message").should == matcher
it 'returns itself when given a message' do
matcher = new_matcher
matcher.with_message('some message').should == matcher
end
end
context "given an attribute that only allows integer values with a custom validation message" do
before do
define_model :example, :attr => :string do
validates_numericality_of :attr, { :only_integer => true, :message => 'custom' }
end
@model = Example.new
context 'given an attribute that only allows integer values with a custom validation message' do
it 'only accepts integer values for that attribute with that message' do
only_integer(:message => 'custom').should
new_matcher.with_message(/custom/)
end
it "should only allow integer values for that attribute with that message" do
matcher = new_matcher(:attr)
matcher.with_message(/custom/)
matcher.matches?(@model).should be_true
end
it "should not allow integer values for that attribute with another message" do
matcher = new_matcher(:attr)
matcher.with_message(/wrong/)
matcher.matches?(@model).should be_false
it 'rejects integer values for that attribute with another message' do
only_integer(:message => 'custom').should_not
new_matcher.with_message(/wrong/)
end
end
context "given an attribute that allows values other than integers" do
before do
@model = define_model(:example, :attr => :string).new
context 'when the model does not have an only_integer validation' do
it 'does not match' do
define_model(:example, :attr => :string).new.should_not new_matcher
end
it "does not match" do
matcher = new_matcher(:attr)
matcher.matches?(@model).should be_false
end
it 'fails with the ActiveRecord :not_an_integer message' do
matcher = new_matcher
matcher.matches?(define_model(:example, :attr => :string).new)
it "should fail with the ActiveRecord :not_an_integer message" do
matcher = new_matcher(:attr)
matcher.matches?(@model)
matcher.failure_message.should include 'Expected errors to include "must be an integer"'
end
end
def new_matcher(attribute)
matcher = Shoulda::Matchers::ActiveModel::OnlyIntegerMatcher.new(attribute)
def new_matcher
described_class.new(:attr)
end
def only_integer(options = {})
define_model :example, :attr => :string do
validates_numericality_of :attr, { :only_integer => true }.merge(options)
end.new
end
end

View File

@ -1,43 +1,41 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidateAcceptanceOfMatcher do
context "an attribute which must be accepted" do
before do
@model = define_model(:example, :attr => :string) do
validates_acceptance_of :attr
end.new
context 'a model with an acceptance validation' do
it 'accepts when the attributes match' do
validating_acceptance.should matcher
end
it "should require that attribute to be accepted" do
@model.should validate_acceptance_of(:attr)
end
it "should not overwrite the default message with nil" do
@model.should validate_acceptance_of(:attr).with_message(nil)
it 'does not overwrite the default message with nil' do
validating_acceptance.should matcher.with_message(nil)
end
end
context "an attribute that does not need to be accepted" do
before do
@model = define_model(:example, :attr => :string).new
end
it "should not require that attribute to be accepted" do
@model.should_not validate_acceptance_of(:attr)
context 'a model without an acceptance validation' do
it 'rejects' do
define_model(:example, :attr => :string).new.should_not matcher
end
end
context "an attribute which must be accepted with a custom message" do
before do
@model = define_model(:example, :attr => :string) do
validates_acceptance_of :attr, :message => 'custom'
end.new
context 'an attribute which must be accepted with a custom message' do
it 'accepts when the message matches' do
validating_acceptance(:message => 'custom').should
matcher.with_message(/custom/)
end
it "should require that attribute to be accepted with that message" do
@model.should validate_acceptance_of(:attr).with_message(/custom/)
it 'rejects when the message does not match' do
validating_acceptance(:message => 'custom').should_not
matcher.with_message(/wrong/)
end
end
def matcher
validate_acceptance_of(:attr)
end
def validating_acceptance(options = {})
define_model(:example, :attr => :string) do
validates_acceptance_of :attr, options
end.new
end
end

View File

@ -1,48 +1,41 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidateConfirmationOfMatcher do
context "an attribute which needs confirmation" do
before do
define_model(:example, :attr => :string) do
validates_confirmation_of :attr
end
@model = Example.new
context 'a model with a confirmation validation' do
it 'accepts' do
validating_confirmation.should matcher
end
it "should require confirmation of that attribute" do
@model.should validate_confirmation_of(:attr)
end
it "should not override the default message with a blank" do
@model.should validate_confirmation_of(:attr).with_message(nil)
it 'does not override the default message with a blank' do
validating_confirmation.should matcher.with_message(nil)
end
end
context "an attribute which must be confirmed with a custom message" do
before do
define_model :example, :attr => :string do
validates_confirmation_of :attr, :message => 'custom'
end
@model = Example.new
end
it "should require confirmation of that attribute with that message" do
@model.should validate_confirmation_of(:attr).with_message(/custom/)
end
it "should not require confirmation of that attribute with another message" do
@model.should_not validate_confirmation_of(:attr)
context 'a model without a confirmation validation' do
it 'rejects' do
define_model(:example, :attr => :string).new.should_not matcher
end
end
context "an attribute which doesn't need confirmation" do
before do
@model = define_model(:example, :attr => :string).new
context 'a confirmation validation with a custom message' do
it 'accepts when the message matches' do
validating_confirmation(:message => 'custom').should
matcher.with_message(/custom/)
end
it "should not require confirmation of that attribute" do
@model.should_not validate_confirmation_of(:attr)
it 'rejects when the messages do not match' do
validating_confirmation(:message => 'custom').should_not
matcher.with_message(/wrong/)
end
end
def matcher
validate_confirmation_of(:attr)
end
def validating_confirmation(options = {})
define_model(:example, :attr => :string) do
validates_confirmation_of :attr, options
end.new
end
end

View File

@ -1,79 +1,82 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidateFormatOfMatcher do
context "a postal code" do
before do
define_model :example, :attr => :string do
validates_format_of :attr, :with => /^\d{5}$/
end
@model = Example.new
context 'a model with a format validation' do
it 'accepts when format matches ' do
validating_format(:with => /^\d{5}$/).should matcher.with('12345')
end
it "is valid" do
@model.should validate_format_of(:attr).with('12345')
it 'rejects blank with should_not' do
validating_format(:with => /^\d{5}$/).should_not matcher.with(' ')
end
it "is not valid with blank" do
@model.should_not validate_format_of(:attr).with(' ')
@model.should validate_format_of(:attr).not_with(' ')
it 'rejects blank with not_with' do
validating_format(:with => /^\d{5}$/).should matcher.not_with(' ')
end
it "is not valid with nil" do
@model.should_not validate_format_of(:attr).with(nil)
it 'rejects nil' do
validating_format(:with => /^\d{5}$/).should_not matcher.with(nil)
end
it "is not valid with alpha in zip" do
@model.should_not validate_format_of(:attr).with('1234a')
@model.should validate_format_of(:attr).not_with('1234a')
it 'rejects a non-matching format with should_not' do
validating_format(:with => /^\d{5}$/).should_not matcher.with('1234a')
end
it "is not valid with too few digits" do
@model.should_not validate_format_of(:attr).with('1234')
@model.should validate_format_of(:attr).not_with('1234')
it 'rejects a non-matching format with not_with' do
validating_format(:with => /^\d{5}$/).should matcher.not_with('1234a')
end
it "is not valid with too many digits" do
@model.should_not validate_format_of(:attr).with('123456')
@model.should validate_format_of(:attr).not_with('123456')
end
it "raises error if you try to call both with and not_with" do
expect { validate_format_of(:attr).not_with('123456').with('12345') }.
to raise_error(RuntimeError)
it 'raises an error if you try to call both with and not_with' do
expect {
validate_format_of(:attr).not_with('123456').with('12345')
}.to raise_error(RuntimeError)
end
end
context "when allow_blank and allow_nil are set" do
before do
define_model :example, :attr => :string do
validates_format_of :attr, :with => /^\d{5}$/, :allow_blank => true, :allow_nil => true
end
@model = Example.new
end
it "is valid when attr is nil" do
@model.should validate_format_of(:attr).with(nil)
end
it "is valid when attr is blank" do
@model.should validate_format_of(:attr).with(' ')
end
describe "#allow_blank" do
it "allows allow_blank" do
@model.should validate_format_of(:attr).allow_blank
@model.should validate_format_of(:attr).allow_blank(true)
@model.should_not validate_format_of(:attr).allow_blank(false)
end
end
describe "#allow_nil" do
it "allows allow_nil" do
@model.should validate_format_of(:attr).allow_nil
@model.should validate_format_of(:attr).allow_nil(true)
@model.should_not validate_format_of(:attr).allow_nil(false)
end
context 'a model without a format validation' do
it 'rejects' do
define_model(:example, :attr => :string).new.should_not
matcher.with('hello')
end
end
context 'when allow_blank or allow_nil are set' do
it 'is valid when attr is nil' do
validating_format(:with => /abc/, :allow_nil => true).should
matcher.with(nil)
end
it 'is valid when attr is blank' do
validating_format(:with => /abc/, :allow_blank => true).should
matcher.with(' ')
end
end
context '#allow_blank' do
it 'accepts when allow_blank matches' do
validating_format(:with => /abc/, :allow_blank => true).should
matcher.allow_blank
end
it 'rejects when allow_blank does not match' do
validating_format(:with => /abc/, :allow_blank => false).should_not
matcher.allow_blank
end
end
context '#allow_nil' do
it 'accepts when allow_nil matches' do
validating_format(:with => /abc/, :allow_nil => true).should
matcher.allow_nil
end
it 'rejects when allow_nil does not match' do
validating_format(:with => /abc/, :allow_nil => false).should_not
matcher.allow_nil
end
end
def matcher
validate_format_of(:attr)
end
end

View File

@ -1,112 +1,73 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidateNumericalityOfMatcher do
it "should state in its description that it allows only numeric values" do
matcher = Shoulda::Matchers::ActiveModel::ValidateNumericalityOfMatcher.new(:attr)
matcher.description.should == "only allow numeric values for attr"
end
context "given a numeric attribute" do
before do
define_model :example, :attr => :string do
validates_numericality_of :attr
end
@model = Example.new
end
it "should only allow numeric values for that attribute" do
matcher = new_matcher(:attr)
matcher.matches?(@model).should be_true
end
it "should not override the default message with a blank" do
matcher = new_matcher(:attr)
matcher.with_message(nil)
matcher.matches?(@model).should be_true
end
context "when asked to enforce integer values for that attribute" do
it "should not match" do
matcher = new_matcher(:attr)
matcher.only_integer
matcher.matches?(@model).should be_false
end
it "should fail with the ActiveRecord :not_an_integer message" do
matcher = new_matcher(:attr)
matcher.only_integer
matcher.matches?(@model)
matcher.failure_message.should include 'Expected errors to include "must be an integer"'
end
context '#description' do
it 'states that it allows only numeric values' do
matcher.description.should == 'only allow numeric values for attr'
end
end
context "given a numeric attribute which must be integer" do
before do
define_model :example, :attr => :string do
validates_numericality_of :attr, { :only_integer => true }
end
@model = Example.new
context 'with a model with a numericality validation' do
it 'accepts' do
validating_numericality.should matcher
end
it "allows integer values for that attribute" do
matcher = new_matcher(:attr)
matcher.only_integer
matcher.matches?(@model).should be_true
end
it "does not allow non-integer values for that attribute" do
matcher = new_matcher(:attr)
matcher.only_integer
matcher.matches?(@model).should be_true
end
it "should state in its description that it allows only integer values" do
matcher = new_matcher(:attr)
matcher.only_integer
matcher.description.should == "only allow numeric, integer values for attr"
it 'does not override the default message with a blank' do
validating_numericality.should matcher.with_message(nil)
end
end
context "given a numeric attribute with a custom validation message" do
before do
define_model :example, :attr => :string do
validates_numericality_of :attr, :message => 'custom'
end
@model = Example.new
context 'with a model without a numericality validation' do
it 'rejects' do
define_model(:example, :attr => :string).new.should_not matcher
end
it "should only allow numeric values for that attribute with that message" do
matcher = new_matcher(:attr)
matcher.with_message(/custom/)
matcher.matches?(@model).should be_true
end
it 'rejects with the ActiveRecord :not_an_integer message' do
the_matcher = matcher.only_integer
it "should not allow numeric values for that attribute with another message" do
matcher = new_matcher(:attr)
matcher.with_message(/wrong/)
matcher.matches?(@model).should be_false
the_matcher.matches?(define_model(:example, :attr => :string).new)
the_matcher.failure_message.should include 'Expected errors to include "must be an integer"'
end
end
context "given a non-numeric attribute" do
before do
@model = define_model(:example, :attr => :string).new
context 'with the only_integer option' do
it 'allows integer values for that attribute' do
validating_numericality(:only_integer => true).should matcher.only_integer
end
it "should not only allow numeric values for that attribute" do
matcher = new_matcher(:attr)
matcher.matches?(@model).should be_false
it 'rejects when the model does not enforce integer values' do
validating_numericality.should_not matcher.only_integer
end
it "should fail with the ActiveRecord :not_a_number message" do
matcher = new_matcher(:attr)
matcher.matches?(@model)
matcher.failure_message.should include 'Expected errors to include "is not a number"'
it 'rejects with the ActiveRecord :not_an_integer message' do
the_matcher = matcher.only_integer
the_matcher.matches?(validating_numericality)
the_matcher.failure_message.should include 'Expected errors to include "must be an integer"'
end
end
def new_matcher(attr)
Shoulda::Matchers::ActiveModel::ValidateNumericalityOfMatcher.new(attr)
context 'with a custom validation message' do
it 'accepts when the messages match' do
validating_numericality(:message => 'custom').should
matcher.with_message(/custom/)
end
it 'rejects when the messages do not match' do
validating_numericality(:message => 'custom').should_not
matcher.with_message(/wrong/)
end
end
def validating_numericality(options = {})
define_model :example, :attr => :string do
validates_numericality_of :attr, options
end.new
end
def matcher
validate_numericality_of(:attr)
end
end

View File

@ -1,135 +1,127 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidatePresenceOfMatcher do
context "a required attribute" do
before do
define_model :example, :attr => :string do
validates_presence_of :attr
end
@model = Example.new
context 'a model with a presence validation' do
it 'accepts' do
validating_presence.should matcher
end
it "should require a value" do
@model.should validate_presence_of(:attr)
end
it "should not override the default message with a blank" do
@model.should validate_presence_of(:attr).with_message(nil)
it 'does not override the default message with a blank' do
validating_presence.should matcher.with_message(nil)
end
end
context "a required attribute on a class using ActiveModel::Validations" do
before do
define_active_model_class("Example", :accessors => [:attr]) do
validates_presence_of :attr
end
@model = Example.new
end
it "should require a value" do
@model.should validate_presence_of(:attr)
end
it "should not override the default message with a blank" do
@model.should validate_presence_of(:attr).with_message(nil)
context 'a model without a presence validation' do
it 'rejects' do
define_model(:example, :attr => :string).new.should_not matcher
end
end
context "an optional attribute" do
before do
@model = define_model(:example, :attr => :string).new
context 'an ActiveModel class with a presence validation' do
it 'accepts' do
active_model_validating_presence.should matcher
end
it "should not require a value" do
@model.should_not validate_presence_of(:attr)
it 'does not override the default message with a blank' do
active_model_validating_presence.should matcher.with_message(nil)
end
end
context "an optional attribute on a class using ActiveModel::Validations" do
before do
@model = define_active_model_class("Example", :accessors => [:attr]).new
end
it "should not require a value" do
@model.should_not validate_presence_of(:attr)
context 'an ActiveModel class without a presence validation' do
it 'rejects' do
define_active_model_class('Example', :accessors => [:attr]).new.should_not
matcher
end
end
context "a required has_many association" do
before do
define_model :child
@model = define_model :parent do
has_many :children
validates_presence_of :children
end.new
end
it "should require the attribute to be set" do
@model.should validate_presence_of(:children)
context 'a has_many association with a presence validation' do
it 'requires the attribute to be set' do
has_many_children(:presence => true).should validate_presence_of(:children)
end
end
context "an optional has_many association" do
before do
define_model :child
@model = define_model :parent do
has_many :children
end.new
end
it "should not require the attribute to be set" do
@model.should_not validate_presence_of(:children)
context 'a has_many association without a presence validation' do
it 'does not require the attribute to be set' do
has_many_children(:presence => false).should_not
validate_presence_of(:children)
end
end
context "a required has_and_belongs_to_many association" do
context 'a required has_and_belongs_to_many association' do
before do
define_model :child
@model = define_model :parent do
has_and_belongs_to_many :children
validates_presence_of :children
end.new
create_table "children_parents", :id => false do |t|
create_table 'children_parents', :id => false do |t|
t.integer :child_id
t.integer :parent_id
end
end
it "should require the attribute to be set" do
it 'accepts' do
@model.should validate_presence_of(:children)
end
end
context "an optional has_and_belongs_to_many association" do
context 'an optional has_and_belongs_to_many association' do
before do
define_model :child
@model = define_model :parent do
has_and_belongs_to_many :children
end.new
create_table "children_parents", :id => false do |t|
create_table 'children_parents', :id => false do |t|
t.integer :child_id
t.integer :parent_id
end
end
it "should not require the attribute to be set" do
it 'rejects' do
@model.should_not validate_presence_of(:children)
end
end
if Rails::VERSION::STRING.to_f >= 3.2
context "a strictly required attribute" do
before do
define_model :example, :attr => :string do
validates_presence_of :attr, :strict => true
end
@model = Example.new
if active_model_3_2?
context 'a strictly required attribute' do
it 'accepts when the :strict options match' do
validating_presence(:strict => true).should matcher.strict
end
it "should require a value" do
@model.should validate_presence_of(:attr).strict
it 'rejects when the :strict options do not match' do
validating_presence(:strict => false).should_not matcher.strict
end
end
it 'does not override the default message with a blank' do
validating_presence(:strict => true).should
matcher.strict.with_message(nil)
end
end
def matcher
validate_presence_of(:attr)
end
def validating_presence(options = {})
define_model :example, :attr => :string do
validates_presence_of :attr, options
end.new
end
def active_model_validating_presence
define_active_model_class('Example', :accessors => [:attr]) do
validates_presence_of :attr
end.new
end
def has_many_children(options = {})
define_model :child
define_model :parent do
has_many :children
if options[:presence]
validates_presence_of :children
end
end.new
end
end

View File

@ -1,154 +1,175 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
context "a unique attribute" do
before do
@model = define_model(:example, :attr => :string,
:other => :integer) do
context 'a model without a a uniqueness validation' do
it 'rejects' do
model = define_model(:example, :attr => :string) { attr_accessible :attr } .new
Example.create!(:attr => 'value')
model.should_not matcher
end
end
context 'a model with a uniqueness validation' do
context 'with an existing record' do
it 'requires a unique value for that attribute' do
create_existing
validating_uniqueness_with_other.should matcher
end
it 'accepts when the subject is an existing record' do
create_existing.should matcher
end
it 'rejects when a scope is specified' do
create_existing
validating_uniqueness_with_other.should_not matcher.scoped_to(:other)
end
def create_existing
define_model_with_other
Example.create!(:attr => 'value', :other => 1)
end
end
context 'without an existing record' do
it 'does not require a created instance' do
define_model_with_other
Example.count.should == 0
validating_uniqueness_with_other.should matcher
end
end
def define_model_with_other(options = {})
@model ||= define_model(:example, :attr => :string, :other => :integer) do
attr_accessible :attr, :other
validates_uniqueness_of :attr
end.new
end
context "with an existing value" do
before do
@existing = Example.create!(:attr => 'value', :other => 1)
end
it "should require a unique value for that attribute" do
@model.should validate_uniqueness_of(:attr)
end
it "should pass when the subject is an existing record" do
@existing.should validate_uniqueness_of(:attr)
end
it "should fail when a scope is specified" do
@model.should_not validate_uniqueness_of(:attr).scoped_to(:other)
validates_uniqueness_of :attr, options
end
end
context "without an existing value" do
before do
Example.find(:first).should be_nil
@matcher = validate_uniqueness_of(:attr)
end
it "does not not require a created instance" do
@model.should @matcher
end
def validating_uniqueness_with_other(options = {})
define_model_with_other.new
end
end
context "a unique attribute with a custom error and an existing value" do
before do
@model = define_model(:example, :attr => :string) do
context 'a model with a uniqueness validation, a custom error, and an existing record' do
it 'rejects when the actual message does not match the default message' do
validating_uniqueness_with_existing_record(:message => 'Bad value').
should_not matcher
end
it 'rejects when the messages do not match' do
validating_uniqueness_with_existing_record(:message => 'Bad value').
should_not matcher.with_message(/abc/)
end
it 'accepts when the messages match' do
validating_uniqueness_with_existing_record(:message => 'Bad value').
should matcher.with_message(/Bad/)
end
def validating_uniqueness_with_existing_record(options = {})
model = define_model(:example, :attr => :string) do
attr_accessible :attr
validates_uniqueness_of :attr, :message => 'Bad value'
validates_uniqueness_of :attr, options
end.new
Example.create!(:attr => 'value')
end
it "should fail when checking the default message" do
@model.should_not validate_uniqueness_of(:attr)
end
it "should fail when checking a message that doesn't match" do
@model.should_not validate_uniqueness_of(:attr).with_message(/abc/i)
end
it "should pass when checking a message that matches" do
@model.should validate_uniqueness_of(:attr).with_message(/bad/i)
model
end
end
context "a scoped unique attribute with an existing value" do
before do
@model = define_model(:example, :attr => :string,
:scope1 => :integer,
:scope2 => :integer,
:other => :integer) do
context 'a model with a scoped uniqueness validation with an existing value' do
it 'accepts when the correct scope is specified' do
validating_scoped_uniqueness([:scope1, :scope2]).should
matcher.scoped_to(:scope1, :scope2)
end
it 'accepts when the subject is an existing record' do
define_scoped_model([:scope1, :scope2])
create_existing_record.should matcher.scoped_to(:scope1, :scope2)
end
it 'rejects when too narrow of a scope is specified' do
validating_scoped_uniqueness([:scope1, :scope2]).should_not
matcher.scoped_to(:scope1, :scope2, :other)
end
it 'rejects when too broad of a scope is specified' do
validating_scoped_uniqueness([:scope1, :scope2]).should_not
matcher.scoped_to(:scope1)
end
it 'rejects when a different scope is specified' do
validating_scoped_uniqueness([:scope1]).should_not
matcher.scoped_to(:other)
end
it 'rejects when no scope is specified' do
validating_scoped_uniqueness([:scope1]).should_not matcher
end
it 'rejects when a non-existent attribute is specified as a scope' do
validating_scoped_uniqueness([:scope1]).should_not
matcher.scoped_to(:fake)
end
def create_existing_record
@existing ||= Example.create!(:attr => 'value', :scope1 => 1, :scope2 => 2, :other => 3)
end
def define_scoped_model(scope)
define_model(:example, :attr => :string, :scope1 => :integer,
:scope2 => :integer, :other => :integer) do
attr_accessible :attr, :scope1, :scope2, :other
validates_uniqueness_of :attr, :scope => [:scope1, :scope2]
end.new
@existing = Example.create!(:attr => 'value', :scope1 => 1, :scope2 => 2, :other => 3)
validates_uniqueness_of :attr, :scope => scope
end
end
it "should pass when the correct scope is specified" do
@model.should validate_uniqueness_of(:attr).scoped_to(:scope1, :scope2)
end
it "should pass when the subject is an existing record" do
@existing.should validate_uniqueness_of(:attr).scoped_to(:scope1, :scope2)
end
it "should fail when too narrow of a scope is specified" do
@model.should_not validate_uniqueness_of(:attr).scoped_to(:scope1, :scope2, :other)
end
it "should fail when too broad of a scope is specified" do
@model.should_not validate_uniqueness_of(:attr).scoped_to(:scope1)
end
it "should fail when a different scope is specified" do
@model.should_not validate_uniqueness_of(:attr).scoped_to(:other)
end
it "should fail when no scope is specified" do
@model.should_not validate_uniqueness_of(:attr)
end
it "should fail when a non-existent attribute is specified as a scope" do
@model.should_not validate_uniqueness_of(:attr).scoped_to(:fake)
def validating_scoped_uniqueness(scope)
model = define_scoped_model(scope).new
create_existing_record
model
end
end
context "a non-unique attribute with an existing value" do
before do
@model = define_model(:example, :attr => :string) do
attr_accessible :attr
end.new
Example.create!(:attr => 'value')
context 'a model with a case-sensitive uniqueness validation on a string attribute and an existing record' do
it 'accepts a case-sensitive value for that attribute' do
case_sensitive_validation_with_existing_value(:string).should
matcher
end
it "should not require a unique value for that attribute" do
@model.should_not validate_uniqueness_of(:attr)
it 'rejects a case-insensitive value for that attribute' do
case_sensitive_validation_with_existing_value(:string).should_not
matcher.case_insensitive
end
end
context "a case sensitive unique attribute with an existing value" do
before do
@model = define_model(:example, :attr => :string) do
attr_accessible :attr
validates_uniqueness_of :attr, :case_sensitive => true
end.new
Example.create!(:attr => 'value')
context 'a model with a case-sensitive uniqueness validation on an integer attribute with an existing value' do
it 'accepts a case-insensitive value for that attribute' do
case_sensitive_validation_with_existing_value(:integer).should
matcher.case_insensitive
end
it "should not require a unique, case-insensitive value for that attribute" do
@model.should_not validate_uniqueness_of(:attr).case_insensitive
end
it "should require a unique, case-sensitive value for that attribute" do
@model.should validate_uniqueness_of(:attr)
it 'accepts a case-sensitive value for that attribute' do
case_sensitive_validation_with_existing_value(:integer).should matcher
end
end
context "a case sensitive unique integer attribute with an existing value" do
before do
@model = define_model(:example, :attr => :integer) do
attr_accessible :attr
validates_uniqueness_of :attr, :case_sensitive => true
end.new
def case_sensitive_validation_with_existing_value(attr_type)
model = define_model(:example, :attr => attr_type) do
attr_accessible :attr
validates_uniqueness_of :attr, :case_sensitive => true
end.new
if attr_type == :string
Example.create!(:attr => 'value')
elsif attr_type == :integer
Example.create!(:attr => 1)
else
raise 'Must be :string or :integer'
end
model
end
it "should require a unique, case-insensitive value for that attribute" do
@model.should validate_uniqueness_of(:attr).case_insensitive
end
it "should require a unique, case-sensitive value for that attribute" do
@model.should validate_uniqueness_of(:attr)
end
def matcher
validate_uniqueness_of(:attr)
end
end

View File

@ -51,7 +51,6 @@ describe Shoulda::Matchers::ActiveModel::ValidationMessageFinder do
context '#messages_description' do
it 'describes errors for the given attribute' do
value = 'xyz'
finder = build_finder(
:attribute => :attr,
:format => /abc/,

View File

@ -1,84 +1,106 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveRecord::AcceptNestedAttributesForMatcher do
before do
define_model :child, :parent_id => :integer
define_model :parent do
has_many :children
end
it 'accepts an existing declaration' do
accepting_children.should accept_nested_attributes_for(:children)
end
let(:parent) { Parent.new }
let(:matcher) { accept_nested_attributes_for(:children) }
it 'rejects a missing declaration' do
matcher = children_matcher
it "should accept an existing declaration" do
Parent.accepts_nested_attributes_for :children
matcher.matches?(parent).should be_true
matcher.matches?(rejecting_children).should be_false
matcher.failure_message.should == 'Expected Parent to accept nested attributes for children (is not declared)'
end
it "should reject a missing declaration" do
matcher.matches?(parent).should be_false
matcher.failure_message.should == "Expected Parent to accept nested attributes for children (is not declared)"
end
context 'allow_destroy' do
it 'accepts a valid truthy value' do
matching = accepting_children(:allow_destroy => true)
context "allow_destroy" do
it "should accept a valid truthy value" do
Parent.accepts_nested_attributes_for :children, :allow_destroy => true
matcher.allow_destroy(true).matches?(parent).should be_true
matching.should children_matcher.allow_destroy(true)
end
it "should accept a valid falsey value" do
Parent.accepts_nested_attributes_for :children, :allow_destroy => false
matcher.allow_destroy(false).matches?(parent).should be_true
it 'accepts a valid falsey value' do
matching = accepting_children(:allow_destroy => false)
matching.should children_matcher.allow_destroy(false)
end
it "should reject an invalid truthy value" do
Parent.accepts_nested_attributes_for :children, :allow_destroy => true
matcher.allow_destroy(false).matches?(parent).should be_false
it 'rejects an invalid truthy value' do
matcher = children_matcher
matching = accepting_children(:allow_destroy => true)
matcher.allow_destroy(false).matches?(matching).should be_false
matcher.failure_message.should =~ /should not allow destroy/
end
it "should reject an invalid falsey value" do
Parent.accepts_nested_attributes_for :children, :allow_destroy => false
matcher.allow_destroy(true).matches?(parent).should be_false
it 'rejects an invalid falsey value' do
matcher = children_matcher
matching = accepting_children(:allow_destroy => false)
matcher.allow_destroy(true).matches?(matching).should be_false
matcher.failure_message.should =~ /should allow destroy/
end
end
context "limit" do
it "should accept a correct value" do
Parent.accepts_nested_attributes_for :children, :limit => 3
matcher.limit(3).matches?(parent).should be_true
context 'limit' do
it 'accepts a correct value' do
accepting_children(:limit => 3).should children_matcher.limit(3)
end
it "should reject a false value" do
Parent.accepts_nested_attributes_for :children, :limit => 3
matcher.limit(2).matches?(parent).should be_false
it 'rejects a false value' do
matcher = children_matcher
rejecting = accepting_children(:limit => 3)
matcher.limit(2).matches?(rejecting).should be_false
matcher.failure_message.should =~ /limit should be 2, got 3/
end
end
context "update_only" do
it "should accept a valid truthy value" do
Parent.accepts_nested_attributes_for :children, :update_only => true
matcher.update_only(true).matches?(parent).should be_true
context 'update_only' do
it 'accepts a valid truthy value' do
accepting_children(:update_only => true).should
children_matcher.update_only(true)
end
it "should accept a valid falsey value" do
Parent.accepts_nested_attributes_for :children, :update_only => false
matcher.update_only(false).matches?(parent).should be_true
it 'accepts a valid falsey value' do
accepting_children(:update_only => false).should
children_matcher.update_only(false)
end
it "should reject an invalid truthy value" do
Parent.accepts_nested_attributes_for :children, :update_only => true
matcher.update_only(false).matches?(parent).should be_false
it 'rejects an invalid truthy value' do
matcher = children_matcher.update_only(false)
rejecting = accepting_children(:update_only => true)
matcher.matches?(rejecting).should be_false
matcher.failure_message.should =~ /should not be update only/
end
it "should reject an invalid falsey value" do
Parent.accepts_nested_attributes_for :children, :update_only => false
matcher.update_only(true).matches?(parent).should be_false
it 'rejects an invalid falsey value' do
matcher = children_matcher.update_only(true)
rejecting = accepting_children(:update_only => false)
matcher.matches?(rejecting).should be_false
matcher.failure_message.should =~ /should be update only/
end
end
def accepting_children(options = {})
define_model :child, :parent_id => :integer
define_model :parent do
has_many :children
accepts_nested_attributes_for :children, options
end.new
end
def children_matcher
accept_nested_attributes_for(:children)
end
def rejecting_children
define_model :child, :parent_id => :integer
define_model :parent do
has_many :children
end.new
end
end

View File

@ -1,210 +1,185 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
context "belong_to" do
before do
@matcher = belong_to(:parent)
context 'belong_to' do
it 'accepts a good association with the default foreign key' do
belonging_to_parent.should belong_to(:parent)
end
it "should accept a good association with the default foreign key" do
define_model :parent
define_model :child, :parent_id => :integer do
belongs_to :parent
end
Child.new.should @matcher
it 'rejects a nonexistent association' do
define_model(:child).new.should_not belong_to(:parent)
end
it "should reject a nonexistent association" do
define_model :child
Child.new.should_not @matcher
end
it "should reject an association of the wrong type" do
it 'rejects an association of the wrong type' do
define_model :parent, :child_id => :integer
child_class = define_model :child do
has_one :parent
end
Child.new.should_not @matcher
define_model(:child) { has_one :parent }.new.should_not belong_to(:parent)
end
it "should reject an association that has a nonexistent foreign key" do
it 'rejects an association that has a nonexistent foreign key' do
define_model :parent
define_model :child do
belongs_to :parent
end
Child.new.should_not @matcher
define_model(:child) { belongs_to :parent }.new.should_not belong_to(:parent)
end
it "should accept an association with an existing custom foreign key" do
it 'accepts an association with an existing custom foreign key' do
define_model :parent
define_model :child, :guardian_id => :integer do
belongs_to :parent, :foreign_key => 'guardian_id'
end
Child.new.should @matcher
Child.new.should belong_to(:parent)
end
it "should accept a polymorphic association" do
define_model :child, :parent_type => :string,
:parent_id => :integer do
it 'accepts a polymorphic association' do
define_model :child, :parent_type => :string, :parent_id => :integer do
belongs_to :parent, :polymorphic => true
end
Child.new.should @matcher
Child.new.should belong_to(:parent)
end
it "should accept an association with a valid :dependent option" do
define_model :parent
define_model :child, :parent_id => :integer do
belongs_to :parent, :dependent => :destroy
end
Child.new.should @matcher.dependent(:destroy)
it 'accepts an association with a valid :dependent option' do
belonging_to_parent(:dependent => :destroy).should
belong_to(:parent).dependent(:destroy)
end
it "should reject an association with a bad :dependent option" do
define_model :parent
define_model :child, :parent_id => :integer do
belongs_to :parent
end
Child.new.should_not @matcher.dependent(:destroy)
it 'rejects an association with a bad :dependent option' do
belonging_to_parent.should_not belong_to(:parent).dependent(:destroy)
end
it "should accept an association with a valid :conditions option" do
it 'accepts an association with a valid :conditions option' do
define_model :parent, :adopter => :boolean
define_model :child, :parent_id => :integer do
belongs_to :parent, :conditions => { :adopter => true }
end
Child.new.should @matcher.conditions(:adopter => true)
Child.new.should belong_to(:parent).conditions(:adopter => true)
end
it "should reject an association with a bad :conditions option" do
it 'rejects an association with a bad :conditions option' do
define_model :parent, :adopter => :boolean
define_model :child, :parent_id => :integer do
belongs_to :parent
end
Child.new.should_not @matcher.conditions(:adopter => true)
Child.new.should_not belong_to(:parent).conditions(:adopter => true)
end
it "should accept an association with a valid :class_name option" do
define_model :tree_parent, :adopter => :boolean
it 'accepts an association with a valid :class_name option' do
belonging_to_parent(:class_name => 'TreeParent').should
belong_to(:parent).class_name('TreeParent')
end
it 'rejects an association with a bad :class_name option' do
belonging_to_parent(:class_name => 'TreeParent').should_not
belong_to(:parent).class_name('TreeChild')
end
context 'validate' do
[false, true].each do |validate_value|
context 'when the model has :validate => #{validate_value}' do
it 'accepts a matching validate option' do
belonging_to_parent(:validate => validate_value).should
belong_to(:parent).validate(validate_value)
end
it 'rejects a non-matching validate option' do
belonging_to_parent(:validate => validate_value).should_not
belong_to(:parent).validate(!validate_value)
end
it 'defaults to validate(true)' do
if validate_value
belonging_to_parent(:validate => validate_value).should
belong_to(:parent).validate
else
belonging_to_parent(:validate => validate_value).should_not
belong_to(:parent).validate
end
end
end
end
end
context 'an association without a :validate option' do
it 'accepts validate(false)' do
belonging_to_parent.should belong_to(:parent).validate(false)
end
it 'rejects validate(true)' do
belonging_to_parent.should_not belong_to(:parent).validate(true)
end
it 'rejects validate()' do
belonging_to_parent.should_not belong_to(:parent).validate
end
end
def belonging_to_parent(options = {})
define_model :parent
define_model :child, :parent_id => :integer do
belongs_to :parent, :class_name => 'TreeParent'
end
Child.new.should @matcher.class_name('TreeParent')
belongs_to :parent, options
end.new
end
it "should reject an association with a bad :class_name option" do
define_model :parent, :adopter => :boolean
define_model :child, :parent_id => :integer do
belongs_to :parent
end
Child.new.should_not @matcher.class_name('TreeChild')
end
context 'should accept an association with a false :validate option' do
before do
define_model :parent, :adopter => :boolean
define_model :child, :parent_id => :integer do
belongs_to :parent, :validate => false
end
end
subject { Child.new }
specify { subject.should @matcher.validate(false) }
specify { subject.should_not @matcher.validate(true) }
specify { subject.should_not @matcher.validate }
end
context 'should accept an association with a true :validate option' do
before do
define_model :parent, :adopter => :boolean
define_model :child, :parent_id => :integer do
belongs_to :parent, :validate => true
end
end
subject { Child.new }
specify { subject.should_not @matcher.validate(false) }
specify { subject.should @matcher.validate(true) }
specify { subject.should @matcher.validate }
end
context 'should accept an association without a :validate option' do
before do
define_model :parent, :adopter => :boolean
define_model :child, :parent_id => :integer do
belongs_to :parent
end
end
subject { Child.new }
specify { subject.should @matcher.validate(false) }
specify { subject.should_not @matcher.validate(true) }
specify { subject.should_not @matcher.validate }
end
end
context "have_many" do
before do
@matcher = have_many(:children)
context 'have_many' do
it 'accepts a valid association without any options' do
having_many_children.should have_many(:children)
end
it "should accept a valid association without any options" do
define_model :child, :parent_id => :integer
define_model :parent do
has_many :children
end
Parent.new.should @matcher
end
it "should accept a valid association with a :through option" do
it 'accepts a valid association with a :through option' do
define_model :child
define_model :conception, :child_id => :integer,
:parent_id => :integer do
define_model :conception, :child_id => :integer,
:parent_id => :integer do
belongs_to :child
end
define_model :parent do
has_many :conceptions
has_many :children, :through => :conceptions
end
Parent.new.should @matcher
Parent.new.should have_many(:children)
end
it "should accept a valid association with an :as option" do
define_model :child, :guardian_type => :string,
:guardian_id => :integer
it 'accepts a valid association with an :as option' do
define_model :child, :guardian_type => :string, :guardian_id => :integer
define_model :parent do
has_many :children, :as => :guardian
end
Parent.new.should @matcher
Parent.new.should have_many(:children)
end
it "should reject an association that has a nonexistent foreign key" do
it 'rejects an association that has a nonexistent foreign key' do
define_model :child
define_model :parent do
has_many :children
end
Parent.new.should_not @matcher
Parent.new.should_not have_many(:children)
end
it "should reject an association with a bad :as option" do
it 'rejects an association with a bad :as option' do
define_model :child, :caretaker_type => :string,
:caretaker_id => :integer
:caretaker_id => :integer
define_model :parent do
has_many :children, :as => :guardian
end
Parent.new.should_not @matcher
Parent.new.should_not have_many(:children)
end
it "should reject an association that has a bad :through option" do
define_model :child, :parent_id => :integer
define_model :parent do
has_many :children
end
@matcher.through(:conceptions).matches?(Parent.new).should be_false
@matcher.failure_message.should =~ /does not have any relationship to conceptions/
it 'rejects an association that has a bad :through option' do
matcher = have_many(:children).through(:conceptions)
matcher.matches?(having_many_children).should be_false
matcher.failure_message.should =~ /does not have any relationship to conceptions/
end
it "should reject an association that has the wrong :through option" do
it 'rejects an association that has the wrong :through option' do
define_model :child
define_model :conception, :child_id => :integer,
:parent_id => :integer do
define_model :conception, :child_id => :integer,
:parent_id => :integer do
belongs_to :child
end
define_model :parent do
@ -212,246 +187,197 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
has_many :relationships
has_many :children, :through => :conceptions
end
@matcher.through(:relationships).matches?(Parent.new).should be_false
@matcher.failure_message.should =~ /through relationships, but got it through conceptions/
matcher = have_many(:children).through(:relationships)
matcher.matches?(Parent.new).should be_false
matcher.failure_message.should =~ /through relationships, but got it through conceptions/
end
it "should accept an association with a valid :dependent option" do
define_model :child, :parent_id => :integer
define_model :parent do
has_many :children, :dependent => :destroy
end
Parent.new.should @matcher.dependent(:destroy)
it 'accepts an association with a valid :dependent option' do
having_many_children(:dependent => :destroy).should
have_many(:children).dependent(:destroy)
end
it "should reject an association with a bad :dependent option" do
define_model :child, :parent_id => :integer
define_model :parent do
has_many :children
end
Parent.new.should_not @matcher.dependent(:destroy)
it 'rejects an association with a bad :dependent option' do
having_many_children.should_not have_many(:children).dependent(:destroy)
end
it "should accept an association with a valid :order option" do
define_model :child, :parent_id => :integer
define_model :parent do
has_many :children, :order => :id
end
Parent.new.should @matcher.order(:id)
it 'accepts an association with a valid :order option' do
having_many_children(:order => :id).should
have_many(:children).order(:id)
end
it "should reject an association with a bad :order option" do
define_model :child, :parent_id => :integer
define_model :parent do
has_many :children
end
Parent.new.should_not @matcher.order(:id)
it 'rejects an association with a bad :order option' do
having_many_children.should_not have_many(:children).order(:id)
end
it "should accept an association with a valid :conditions option" do
it 'accepts an association with a valid :conditions option' do
define_model :child, :parent_id => :integer, :adopted => :boolean
define_model :parent do
has_many :children, :conditions => { :adopted => true }
end
Parent.new.should @matcher.conditions({ :adopted => true })
Parent.new.should have_many(:children).conditions(:adopted => true)
end
it "should reject an association with a bad :conditions option" do
it 'rejects an association with a bad :conditions option' do
define_model :child, :parent_id => :integer, :adopted => :boolean
define_model :parent do
has_many :children
end
Parent.new.should_not @matcher.conditions({ :adopted => true })
Parent.new.should_not have_many(:children).conditions(:adopted => true)
end
it "should accept an association with a valid :class_name option" do
define_model :node, :parent_id => :integer, :adopted => :boolean
it 'accepts an association with a valid :class_name option' do
define_model :node, :parent_id => :integer
define_model :parent do
has_many :children, :class_name => 'Node'
end
Parent.new.should @matcher.class_name('Node')
Parent.new.should have_many(:children).class_name('Node')
end
it "should reject an association with a bad :class_name option" do
define_model :child, :parent_id => :integer, :adopted => :boolean
define_model :parent do
has_many :children
it 'rejects an association with a bad :class_name option' do
having_many_children.should_not have_many(:children).class_name('Node')
end
context 'validate' do
it 'accepts when the :validate option matches' do
having_many_children(:validate => false).should have_many(:children).validate(false)
end
Parent.new.should_not @matcher.class_name('Node')
end
context 'should accept an association with a false :validate option' do
before do
define_model :child, :parent_id => :integer, :adopted => :boolean
define_model :parent do
has_many :children, :validate => false
end
it 'rejects when the :validate option does not match' do
having_many_children(:validate => true).should_not have_many(:children).validate(false)
end
subject { Parent.new }
specify { subject.should @matcher.validate(false) }
specify { subject.should_not @matcher.validate(true) }
specify { subject.should_not @matcher.validate }
end
context 'should accept an association with a true :validate option' do
before do
define_model :child, :parent_id => :integer, :adopted => :boolean
define_model :parent do
has_many :children, :validate => true
end
it 'assumes validate() means validate(true)' do
having_many_children(:validate => false).should_not
have_many(:children).validate
end
subject { Parent.new }
specify { subject.should_not @matcher.validate(false) }
specify { subject.should @matcher.validate(true) }
specify { subject.should @matcher.validate }
end
context 'should accept an association without a :validate option' do
before do
define_model :child, :parent_id => :integer, :adopted => :boolean
define_model :parent do
has_many :children
end
it 'matches validate(false) to having no validate option specified' do
having_many_children.should have_many(:children).validate(false)
end
subject { Parent.new }
specify { subject.should @matcher.validate(false) }
specify { subject.should_not @matcher.validate(true) }
specify { subject.should_not @matcher.validate }
end
it "should accept an association with a nonstandard reverse foreign key, using :inverse_of" do
it 'accepts an association with a nonstandard reverse foreign key, using :inverse_of' do
define_model :child, :ancestor_id => :integer do
belongs_to :ancestor, :inverse_of => :children, :class_name => :Parent
end
define_model :parent do
has_many :children, :inverse_of => :ancestor
end
Parent.new.should @matcher
Parent.new.should have_many(:children)
end
it "should reject an association with a nonstandard reverse foreign key, if :inverse_of is not correct" do
it 'rejects an association with a nonstandard reverse foreign key, if :inverse_of is not correct' do
define_model :child, :mother_id => :integer do
belongs_to :mother, :inverse_of => :children, :class_name => :Parent
end
define_model :parent do
has_many :children, :inverse_of => :ancestor
end
Parent.new.should_not @matcher
Parent.new.should_not have_many(:children)
end
def having_many_children(options = {})
define_model :child, :parent_id => :integer
define_model :parent do
has_many :children, options
end.new
end
end
context "have_one" do
before do
@matcher = have_one(:detail)
context 'have_one' do
it 'accepts a valid association without any options' do
having_one_detail.should have_one(:detail)
end
it "should accept a valid association without any options" do
define_model :detail, :person_id => :integer
define_model :person do
has_one :detail
end
Person.new.should @matcher
end
it "should accept a valid association with an :as option" do
define_model :detail, :detailable_id => :integer,
:detailable_type => :string
it 'accepts a valid association with an :as option' do
define_model :detail, :detailable_id => :integer,
:detailable_type => :string
define_model :person do
has_one :detail, :as => :detailable
end
Person.new.should @matcher
Person.new.should have_one(:detail)
end
it "should reject an association that has a nonexistent foreign key" do
it 'rejects an association that has a nonexistent foreign key' do
define_model :detail
define_model :person do
has_one :detail
end
Person.new.should_not @matcher
Person.new.should_not have_one(:detail)
end
it "should accept an association with an existing custom foreign key" do
it 'accepts an association with an existing custom foreign key' do
define_model :detail, :detailed_person_id => :integer
define_model :person do
has_one :detail, :foreign_key => :detailed_person_id
end
Person.new.should @matcher.with_foreign_key(:detailed_person_id)
Person.new.should have_one(:detail).with_foreign_key(:detailed_person_id)
end
it "should reject an association with a bad :as option" do
define_model :detail, :detailable_id => :integer,
:detailable_type => :string
it 'rejects an association with a bad :as option' do
define_model :detail, :detailable_id => :integer,
:detailable_type => :string
define_model :person do
has_one :detail, :as => :describable
end
Person.new.should_not @matcher
Person.new.should_not have_one(:detail)
end
it "should accept an association with a valid :dependent option" do
define_model :detail, :person_id => :integer
define_model :person do
has_one :detail, :dependent => :destroy
end
Person.new.should @matcher.dependent(:destroy)
it 'accepts an association with a valid :dependent option' do
having_one_detail(:dependent => :destroy).should
have_one(:detail).dependent(:destroy)
end
it "should reject an association with a bad :dependent option" do
define_model :detail, :person_id => :integer
define_model :person do
has_one :detail
end
Person.new.should_not @matcher.dependent(:destroy)
it 'rejects an association with a bad :dependent option' do
having_one_detail.should_not have_one(:detail).dependent(:destroy)
end
it "should accept an association with a valid :order option" do
define_model :detail, :person_id => :integer
define_model :person do
has_one :detail, :order => :id
end
Person.new.should @matcher.order(:id)
it 'accepts an association with a valid :order option' do
having_one_detail(:order => :id).should have_one(:detail).order(:id)
end
it "should reject an association with a bad :order option" do
define_model :detail, :person_id => :integer
define_model :person do
has_one :detail
end
Person.new.should_not @matcher.order(:id)
it 'rejects an association with a bad :order option' do
having_one_detail.should_not have_one(:detail).order(:id)
end
it "should accept an association with a valid :conditions option" do
it 'accepts an association with a valid :conditions option' do
define_model :detail, :person_id => :integer, :disabled => :boolean
define_model :person do
has_one :detail, :conditions => { :disabled => true}
end
Person.new.should @matcher.conditions(:disabled => true)
Person.new.should have_one(:detail).conditions(:disabled => true)
end
it "should reject an association with a bad :conditions option" do
it 'rejects an association with a bad :conditions option' do
define_model :detail, :person_id => :integer, :disabled => :boolean
define_model :person do
has_one :detail
end
Person.new.should_not @matcher.conditions(:disabled => true)
Person.new.should_not have_one(:detail).conditions(:disabled => true)
end
it "should accept an association with a valid :class_name option" do
define_model :person_detail, :person_id => :integer, :disabled => :boolean
define_model :person do
has_one :detail, :class_name => 'PersonDetail'
end
Person.new.should @matcher.class_name('PersonDetail')
it 'accepts an association with a valid :class_name option' do
having_one_detail(:class_name => 'PersonDetail').should
have_one(:detail).class_name('PersonDetail')
end
it "should reject an association with a bad :class_name option" do
define_model :detail, :person_id => :integer, :disabled => :boolean
define_model :person do
has_one :detail
end
Person.new.should_not @matcher.class_name('PersonDetail')
it 'rejects an association with a bad :class_name option' do
having_one_detail.should_not have_one(:detail).class_name('NotSet')
end
it "should accept an association with a through" do
it 'accepts an association with a through' do
define_model :detail
define_model :account do
@ -463,180 +389,145 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
has_one :detail, :through => :account
end
Person.new.should @matcher.through(:account)
Person.new.should have_one(:detail).through(:account)
end
it "should reject an association with a through" do
define_model :detail
it 'rejects an association with a bad through' do
having_one_detail.should_not have_one(:detail).through(:account)
end
context 'validate' do
it 'accepts when the :validate option matches' do
having_one_detail(:validate => false).should
have_one(:detail).validate(false)
end
it 'rejects when the :validate option does not match' do
having_one_detail(:validate => true).should_not
have_one(:detail).validate(false) end
it 'assumes validate() means validate(true)' do
having_one_detail(:validate => false).should_not
have_one(:detail).validate
end
it 'matches validate(false) to having no validate option specified' do
having_one_detail.should have_one(:detail).validate(false)
end
end
def having_one_detail(options = {})
define_model :detail, :person_id => :integer
define_model :person do
has_one :detail
end
Person.new.should_not @matcher.through(:account)
has_one :detail, options
end.new
end
context 'should accept an association with a false :validate option' do
before do
define_model :detail, :person_id => :integer, :disabled => :boolean
define_model :person do
has_one :detail, :validate => false
end
end
subject { Person.new }
specify { subject.should @matcher.validate(false) }
specify { subject.should_not @matcher.validate(true) }
specify { subject.should_not @matcher.validate }
end
context 'should accept an association with a true :validate option' do
before do
define_model :detail, :person_id => :integer, :disabled => :boolean
define_model :person do
has_one :detail, :validate => true
end
end
subject { Person.new }
specify { subject.should_not @matcher.validate(false) }
specify { subject.should @matcher.validate(true) }
specify { subject.should @matcher.validate }
end
context 'should accept an association without a :validate option' do
before do
define_model :detail, :person_id => :integer, :disabled => :boolean
define_model :person do
has_one :detail
end
end
subject { Person.new }
specify { subject.should @matcher.validate(false) }
specify { subject.should_not @matcher.validate(true) }
specify { subject.should_not @matcher.validate }
end
end
context "have_and_belong_to_many" do
before do
@matcher = have_and_belong_to_many(:relatives)
end
context 'have_and_belong_to_many' do
it 'accepts a valid association' do
having_and_belonging_to_many_relatives.should
have_and_belong_to_many(:relatives)
end
it "should accept a valid association" do
define_model :relatives
define_model :person do
has_and_belongs_to_many :relatives
end
define_model :people_relative, :person_id => :integer,
:relative_id => :integer
Person.new.should @matcher
end
it "should reject a nonexistent association" do
it 'rejects a nonexistent association' do
define_model :relatives
define_model :person
define_model :people_relative, :person_id => :integer,
:relative_id => :integer
Person.new.should_not @matcher
define_model :people_relative, :id => false, :person_id => :integer,
:relative_id => :integer
Person.new.should_not have_and_belong_to_many(:relatives)
end
it "should reject an association with a nonexistent join table" do
it 'rejects an association with a nonexistent join table' do
define_model :relatives
define_model :person do
has_and_belongs_to_many :relatives
end
Person.new.should_not @matcher
Person.new.should_not have_and_belong_to_many(:relatives)
end
it "should reject an association of the wrong type" do
it 'rejects an association of the wrong type' do
define_model :relatives, :person_id => :integer
define_model :person do
has_many :relatives
end
Person.new.should_not @matcher
Person.new.should_not have_and_belong_to_many(:relatives)
end
it "should accept an association with a valid :conditions option" do
it 'accepts an association with a valid :conditions option' do
define_model :relatives, :adopted => :boolean
define_model :person do
has_and_belongs_to_many :relatives, :conditions => { :adopted => true }
end
define_model :people_relative, :person_id => :integer,
:relative_id => :integer
Person.new.should @matcher.conditions(:adopted => true)
define_model :people_relative, :id => false, :person_id => :integer,
:relative_id => :integer
Person.new.should
have_and_belong_to_many(:relatives).conditions(:adopted => true)
end
it "should reject an association with a bad :conditions option" do
it 'rejects an association with a bad :conditions option' do
define_model :relatives, :adopted => :boolean
define_model :person do
has_and_belongs_to_many :relatives
end
define_model :people_relative, :person_id => :integer,
:relative_id => :integer
Person.new.should_not @matcher.conditions(:adopted => true)
define_model :people_relative, :id => false, :person_id => :integer,
:relative_id => :integer
Person.new.should_not
have_and_belong_to_many(:relatives).conditions(:adopted => true)
end
it "should accept an association with a valid :class_name option" do
it 'accepts an association with a valid :class_name option' do
define_model :person_relatives, :adopted => :boolean
define_model :person do
has_and_belongs_to_many :relatives, :class_name => 'PersonRelatives'
end
define_model :people_person_relative, :person_id => :integer,
:person_relative_id => :integer
Person.new.should @matcher.class_name('PersonRelatives')
define_model :people_person_relative, :person_id => :integer,
:person_relative_id => :integer
Person.new.should
have_and_belong_to_many(:relatives).class_name('PersonRelatives')
end
it "should reject an association with a bad :class_name option" do
define_model :relatives, :adopted => :boolean
it 'rejects an association with a bad :class_name option' do
having_and_belonging_to_many_relatives.should_not
have_and_belong_to_many(:relatives).class_name('PersonRelatives')
end
context 'validate' do
it 'accepts when the :validate option matches' do
having_and_belonging_to_many_relatives(:validate => false).should
have_and_belong_to_many(:relatives).validate(false)
end
it 'rejects when the :validate option does not match' do
having_and_belonging_to_many_relatives(:validate => true).should
have_and_belong_to_many(:relatives).validate(false)
end
it 'assumes validate() means validate(true)' do
having_and_belonging_to_many_relatives(:validate => false).should_not
have_and_belong_to_many(:relatives).validate
end
it 'matches validate(false) to having no validate option specified' do
having_and_belonging_to_many_relatives.should
have_and_belong_to_many(:relatives).validate(false)
end
end
def having_and_belonging_to_many_relatives(options = {})
define_model :relatives
define_model :people_relative, :id => false, :person_id => :integer,
:relative_id => :integer
define_model :person do
has_and_belongs_to_many :relatives
end
define_model :people_relative, :person_id => :integer,
:relative_id => :integer
Person.new.should_not @matcher.class_name('PersonRelatives')
end.new
end
context 'should accept an association with a false :validate option' do
before do
define_model :relatives, :adopted => :boolean
define_model :person do
has_and_belongs_to_many :relatives, :validate => false
end
define_model :people_relative, :person_id => :integer, :relative_id => :integer
end
subject { Person.new }
specify { subject.should @matcher.validate(false) }
specify { subject.should_not @matcher.validate(true) }
specify { subject.should_not @matcher.validate }
end
context 'should accept an association with a true :validate option' do
before do
define_model :relatives, :adopted => :boolean
define_model :person do
has_and_belongs_to_many :relatives, :validate => true
end
define_model :people_relative, :person_id => :integer, :relative_id => :integer
end
subject { Person.new }
specify { subject.should_not @matcher.validate(false) }
specify { subject.should @matcher.validate(true) }
specify { subject.should @matcher.validate }
end
context 'should accept an association without a :validate option' do
before do
define_model :relatives, :adopted => :boolean
define_model :person do
has_and_belongs_to_many :relatives
end
define_model :people_relative, :person_id => :integer, :relative_id => :integer
end
subject { Person.new }
specify { subject.should @matcher.validate(false) }
specify { subject.should_not @matcher.validate(true) }
specify { subject.should_not @matcher.validate }
end
end
end

View File

@ -1,185 +1,111 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveRecord::HaveDbColumnMatcher do
context "have_db_column" do
before do
@matcher = have_db_column(:nickname)
it 'accepts an existing database column' do
model(:nickname => :string).should have_db_column(:nickname)
end
it 'rejects a nonexistent database column' do
define_model(:employee).new.should_not have_db_column(:nickname)
end
context '#of_type' do
it 'accepts a column of correct type' do
model(:nickname => :string).should
have_db_column(:nickname).of_type(:string)
end
it "should accept an existing database column" do
create_table 'superheros' do |table|
table.string :nickname
end
define_model_class 'Superhero'
Superhero.new.should @matcher
it 'rejects a nonexistent database column' do
define_model(:superhero).should_not
have_db_column(:nickname).of_type(:string)
end
it "should reject a nonexistent database column" do
define_model :superhero
Superhero.new.should_not @matcher
it 'rejects a column of wrong type' do
model(:nickname => :integer).should_not
have_db_column(:nickname).of_type(:string)
end
end
context "have_db_column of type string" do
before do
@matcher = have_db_column(:nickname).of_type(:string)
context 'with precision option' do
it 'accepts a column of correct precision' do
with_table(:salary, :decimal, :precision => 5).should
have_db_column(:salary).with_options(:precision => 5)
end
it "should accept a column of correct type" do
create_table 'superheros' do |table|
table.string :nickname
end
define_model_class 'Superhero'
Superhero.new.should @matcher
end
it "should reject a nonexistent database column" do
define_model :superhero
Superhero.new.should_not @matcher
end
it "should reject a column of wrong type" do
create_table 'superheros' do |table|
table.integer :nickname
end
define_model_class 'Superhero'
Superhero.new.should_not @matcher
it 'rejects a column of wrong precision' do
with_table(:salary, :decimal, :precision => 6).should_not
have_db_column(:salary).with_options(:precision => 5)
end
end
context "have_db_column with precision option" do
before do
@matcher = have_db_column(:salary).with_options(:precision => 5)
context 'with limit option' do
it 'accepts a column of correct limit' do
with_table(:email, :string, :limit => 255).should
have_db_column(:email).with_options(:limit => 255)
end
it "should accept a column of correct precision" do
create_table 'superheros' do |table|
table.decimal :salary, :precision => 5
end
define_model_class 'Superhero'
Superhero.new.should @matcher
end
it "should reject a column of wrong precision" do
create_table 'superheros' do |table|
table.decimal :salary, :precision => 15
end
define_model_class 'Superhero'
Superhero.new.should_not @matcher
it 'rejects a column of wrong limit' do
with_table(:email, :string, :limit => 100).should_not
have_db_column(:email).with_options(:limit => 255)
end
end
context "have_db_column with limit option" do
before do
@matcher = have_db_column(:email).
of_type(:string).
with_options(:limit => 255)
context 'with default option' do
it 'accepts a column with correct default' do
with_table(:admin, :boolean, :default => false).should
have_db_column(:admin).with_options(:default => false)
end
it "should accept a column of correct limit" do
create_table 'superheros' do |table|
table.string :email, :limit => 255
end
define_model_class 'Superhero'
Superhero.new.should @matcher
end
it "should reject a column of wrong limit" do
create_table 'superheros' do |table|
table.string :email, :limit => 500
end
define_model_class 'Superhero'
Superhero.new.should_not @matcher
it 'rejects a column with wrong default' do
with_table(:admin, :boolean, :default => true).should_not
have_db_column(:admin).with_options(:default => false)
end
end
context "have_db_column with default option" do
before do
@matcher = have_db_column(:admin).
of_type(:boolean).
with_options(:default => false)
context 'with null option' do
it 'accepts a column of correct null' do
with_table(:admin, :boolean, :null => false).should
have_db_column(:admin).with_options(:null => false)
end
it "should accept a column of correct default" do
create_table 'superheros' do |table|
table.boolean :admin, :default => false
end
define_model_class 'Superhero'
Superhero.new.should @matcher
end
it "should reject a column of wrong default" do
create_table 'superheros' do |table|
table.boolean :admin, :default => true
end
define_model_class 'Superhero'
Superhero.new.should_not @matcher
it 'rejects a column of wrong null' do
with_table(:admin, :boolean, :null => true).should_not
have_db_column(:admin).with_options(:null => false)
end
end
context "have_db_column with null option" do
before do
@matcher = have_db_column(:admin).
of_type(:boolean).
with_options(:null => false)
context 'with scale option' do
it 'accepts a column of correct scale' do
with_table(:salary, :decimal, :scale => 2).should
have_db_column(:salary).with_options(:scale => 2)
end
it "should accept a column of correct null" do
create_table 'superheros' do |table|
table.boolean :admin, :null => false
end
define_model_class 'Superhero'
Superhero.new.should @matcher
end
it "should reject a column of wrong null" do
create_table 'superheros' do |table|
table.boolean :admin, :null => true
end
define_model_class 'Superhero'
Superhero.new.should_not @matcher
it 'rejects a column of wrong scale' do
with_table(:salary, :decimal, :scale => 4).should_not
have_db_column(:salary).with_options(:scale => 2)
end
end
context "have_db_column with scale option" do
before do
@matcher = have_db_column(:salary).
of_type(:decimal).
with_options(:scale => 2)
context 'with primary option' do
it 'accepts a column that is primary' do
with_table(:id, :integer, :primary => true).should
have_db_column(:id).with_options(:primary => true)
end
it "should accept a column of correct scale" do
create_table 'superheros' do |table|
table.decimal :salary, :precision => 10, :scale => 2
end
define_model_class 'Superhero'
Superhero.new.should @matcher
end
it "should reject a column of wrong scale" do
create_table 'superheros' do |table|
table.decimal :salary, :precision => 10, :scale => 4
end
define_model_class 'Superhero'
Superhero.new.should_not @matcher
it 'rejects a column that is not primary' do
with_table(:whatever, :integer, :primary => false).should_not
have_db_column(:whatever).with_options(:primary => true)
end
end
context "have_db_column with primary option" do
it "should accept a column that is primary" do
create_table 'superheros' do |table|
table.integer :id, :primary => true
end
define_model_class 'Superhero'
Superhero.new.should have_db_column(:id).with_options(:primary => true)
end
def model(options = {})
define_model(:employee, options).new
end
it "should reject a column that is not primary" do
create_table 'superheros' do |table|
table.integer :primary
end
define_model_class 'Superhero'
Superhero.new.should_not have_db_column(:primary).with_options(:primary => true)
def with_table(column_name, column_type, options)
create_table 'employees' do |table|
table.send(column_type, column_name, options)
end
define_model_class('Employee').new
end
end

View File

@ -1,105 +1,78 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveRecord::HaveDbIndexMatcher do
context "have_db_index" do
before do
@matcher = have_db_index(:age)
context 'have_db_index' do
it 'accepts an existing index' do
with_index_on(:age).should have_db_index(:age)
end
it "should accept an existing index" do
db_connection = create_table 'superheros' do |table|
table.integer :age
end
db_connection.add_index :superheros, :age
define_model_class 'Superhero'
Superhero.new.should @matcher
end
it "should reject a nonexistent index" do
define_model :superhero
Superhero.new.should_not @matcher
it 'rejects a nonexistent index' do
define_model(:employee).new.should_not have_db_index(:age)
end
end
context "have_db_index with unique option" do
before do
@matcher = have_db_index(:ssn).unique(true)
context 'have_db_index with unique option' do
it 'accepts an index of correct unique' do
with_index_on(:ssn, :unique => true).should
have_db_index(:ssn).unique(true)
end
it "should accept an index of correct unique" do
db_connection = create_table 'superheros' do |table|
table.integer :ssn
end
db_connection.add_index :superheros, :ssn, :unique => true
define_model_class 'Superhero'
Superhero.new.should @matcher
end
it "should reject an index of wrong unique" do
db_connection = create_table 'superheros' do |table|
table.integer :ssn
end
db_connection.add_index :superheros, :ssn, :unique => false
define_model_class 'Superhero'
Superhero.new.should_not @matcher
it 'rejects an index of wrong unique' do
with_index_on(:ssn, :unique => false).should_not
have_db_index(:ssn).unique(true)
end
end
context "have_db_index on multiple columns" do
before do
@matcher = have_db_index([:geocodable_type, :geocodable_id])
end
it "should accept an existing index" do
context 'have_db_index on multiple columns' do
it 'accepts an existing index' do
db_connection = create_table 'geocodings' do |table|
table.integer :geocodable_id
table.string :geocodable_type
end
db_connection.add_index :geocodings, [:geocodable_type, :geocodable_id]
define_model_class 'Geocoding'
Geocoding.new.should @matcher
define_model_class('Geocoding').new.should
have_db_index([:geocodable_type, :geocodable_id])
end
it "should reject a nonexistant index" do
db_connection = create_table 'geocodings' do |table|
it 'rejects a nonexistent index' do
create_table 'geocodings' do |table|
table.integer :geocodable_id
table.string :geocodable_type
end
define_model_class 'Geocoding'
Geocoding.new.should_not @matcher
define_model_class('Geocoding').new.should_not
have_db_index([:geocodable_type, :geocodable_id])
end
end
it "should join columns with and describing multiple columns" do
it 'join columns with and when describing multiple columns' do
have_db_index([:user_id, :post_id]).description.should =~ /on columns user_id and post_id/
end
it "should context a unique index as unique" do
it 'describes a unique index as unique' do
have_db_index(:user_id).unique(true).description.should =~ /a unique index/
end
it "should context a non-unique index as non-unique" do
it 'describes a non-unique index as non-unique' do
have_db_index(:user_id).unique(false).description.should =~ /a non-unique index/
end
it "should not context an index's uniqueness when it isn't important" do
it "does not display an index's uniqueness when it's not important" do
have_db_index(:user_id).description.should_not =~ /unique/
end
it "allows an IndexDefinition to have a truthy value for unique" do
db_connection = create_table 'superheros' do |table|
table.integer :age
end
db_connection.add_index :superheros, :age
define_model_class 'Superhero'
it 'allows an IndexDefinition to have a truthy value for unique' do
index_definition = stub('ActiveRecord::ConnectionAdapters::IndexDefinition',
:unique => 7, :name => :age)
matcher = have_db_index(:age).unique(true)
matcher.stubs(:matched_index => index_definition)
@matcher = have_db_index(:age).unique(true)
with_index_on(:age).should matcher
end
index_definition = stub("ActiveRecord::ConnectionAdapters::IndexDefinition",
:unique => 7,
:name => :age)
@matcher.stubs(:matched_index => index_definition)
Superhero.new.should @matcher
def with_index_on(column_name, index_options = {})
create_table 'employees' do |table|
table.integer column_name
end.add_index(:employees, column_name, index_options)
define_model_class('Employee').new
end
end

View File

@ -1,46 +1,41 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveRecord::HaveReadonlyAttributeMatcher do
context "an attribute that cannot be set after being saved" do
before do
define_model :example, :attr => :string do
context 'a read-only attribute' do
it 'accepts' do
with_readonly_attr.should have_readonly_attribute(:attr)
end
end
context 'an attribute that is not part of the read-only set' do
it 'rejects being read-only' do
model = define_model :example, :attr => :string, :other => :string do
attr_readonly :attr
end
@model = Example.new
end
end.new
it "should accept being read-only" do
@model.should have_readonly_attribute(:attr)
model.should_not have_readonly_attribute(:other)
end
end
context "an attribute not included in the readonly set" do
before do
define_model :example, :attr => :string, :other => :string do
attr_readonly :other
end
@model = Example.new
context 'an attribute on a class with no readonly attributes' do
it 'rejects being read-only' do
define_model(:example, :attr => :string).new.should_not
have_readonly_attribute(:attr)
end
it "should not accept being read-only" do
@model.should_not have_readonly_attribute(:attr)
end
end
context "an attribute on a class with no readonly attributes" do
before do
define_model :example, :attr => :string
@model = Example.new
end
it "should not accept being read-only" do
@model.should_not have_readonly_attribute(:attr)
end
it "should assign a failure message" do
it 'assigns a failure message' do
model = define_model(:example, :attr => :string).new
matcher = have_readonly_attribute(:attr)
matcher.matches?(@model).should == false
matcher.matches?(model)
matcher.failure_message.should_not be_nil
end
end
def with_readonly_attr
define_model :example, :attr => :string do
attr_readonly :attr
end.new
end
end

View File

@ -10,36 +10,36 @@ describe Shoulda::Matchers::ActiveRecord::QueryTheDatabaseMatcher do
end
end
it "accepts the correct number of queries when there is a single query" do
it 'accepts the correct number of queries when there is a single query' do
@parent.should query_the_database(1.times).when_calling(:count)
end
it "accepts any number of queries when no number is specified" do
it 'accepts any number of queries when no number is specified' do
@parent.should query_the_database.when_calling(:count)
end
it "rejects any number of queries when no number is specified" do
it 'rejects any number of queries when no number is specified' do
@parent.should_not query_the_database.when_calling(:to_s)
end
it "accepts the correct number of queries when there are two queries" do
it 'accepts the correct number of queries when there are two queries' do
nonsense = lambda do
@parent.create.kittens.create
end
nonsense.should query_the_database(2.times).when_calling(:call)
end
it "rejects the wrong number of queries" do
it 'rejects the wrong number of queries' do
@parent.should_not query_the_database(10.times).when_calling(:count)
end
it "accepts fewer than the specified maximum" do
it 'accepts fewer than the specified maximum' do
@parent.should query_the_database(5.times).or_less.when_calling(:count)
end
it "passes arguments to the method to examine" do
model = stub("Model", :count => nil)
model.should_not query_the_database.when_calling(:count).with("arguments")
model.should have_received(:count).with("arguments")
it 'passes arguments to the method to examine' do
model = stub('Model', :count => nil)
model.should_not query_the_database.when_calling(:count).with('arguments')
model.should have_received(:count).with('arguments')
end
end

View File

@ -1,81 +1,87 @@
require 'spec_helper'
describe Shoulda::Matchers::ActiveRecord::SerializeMatcher do
context "an attribute that should be serialized" do
let(:model) do
define_model(:example, :attr => :string) do
serialize :attr
end.new
end
it "should be serialized" do
model.should serialize(:attr)
end
it 'accepts when the attribute is serialized' do
with_serialized_attr.should serialize(:attr)
end
context "an attribute that should be serialized with a type of Hash" do
let(:model) do
define_model(:example, :attr => :string) do
serialize :attr, Hash
end.new
context 'when attribute is not serialized' do
it 'rejects' do
unserialized_model.should_not serialize(:attr)
end
it "should be serialized" do
model.should serialize(:attr).as(Hash)
end
it "should not match when using as_instance_of" do
model.should_not serialize(:attr).as_instance_of(Hash)
end
end
context "an attribute that should be serialized with a type of Array" do
let(:model) do
define_model(:example, :attr => :string, :attr2 => :string) do
serialize :attr, Array
serialize :attr2, Array
end.new
end
it "should be serialized" do
model.should serialize(:attr).as(Array)
end
end
context "an attribute that should be serialized but isn't" do
let(:model) { define_model(:example, :attr => :string).new }
it "should assign a failure message" do
it 'assigns a helpful failure message' do
matcher = serialize(:attr)
matcher.matches?(model).should == false
matcher.failure_message.should_not be_nil
matcher.matches?(unserialized_model)
matcher.failure_message.should =~ /to serialize the attribute called :attr/
end
it "should assign a failure message with 'as'" do
it 'assigns a helpful failure message when using #as' do
matcher = serialize(:attr).as(Hash)
matcher.matches?(model).should == false
matcher.failure_message.should_not be_nil
matcher.matches?(unserialized_model)
matcher.failure_message.should =~ /with a type of Hash/
end
context "a serializer that is an instance of a class" do
before do
define_class(:ExampleSerializer) do
def load(*); end
def dump(*); end
end
define_model :example, :attr => :string do
serialize :attr, ExampleSerializer.new
end
@model = Example.new
end
it 'assigns a helpful failure message when using #as_instance_of' do
matcher = serialize(:attr).as_instance_of(Hash)
it "should match when using as_instance_of" do
@model.should serialize(:attr).as_instance_of(ExampleSerializer)
end
matcher.matches?(unserialized_model)
it "should not match when using as" do
@model.should_not serialize(:attr).as(ExampleSerializer)
matcher.failure_message.should =~ /with an instance of Hash/
end
def unserialized_model
@model ||= define_model(:example, :attr => :string).new
end
end
context 'an attribute that is serialized as a specific type' do
it 'accepts when the types match' do
with_serialized_attr(Hash).should serialize(:attr).as(Hash)
end
it 'rejects when the types do not match' do
with_serialized_attr(Hash).should_not serialize(:attr).as(String)
end
it 'rejects when using as_instance_of' do
with_serialized_attr(Hash).should_not
serialize(:attr).as_instance_of(Hash)
end
end
context 'a serializer that is an instance of a class' do
it 'accepts when using #as_instance_of' do
define_serializer(:ExampleSerializer)
with_serialized_attr(ExampleSerializer.new).should
serialize(:attr).as_instance_of(ExampleSerializer)
end
it 'rejects when using #as' do
define_serializer(:ExampleSerializer)
with_serialized_attr(ExampleSerializer.new).should_not
serialize(:attr).as(ExampleSerializer)
end
end
def with_serialized_attr(type = nil)
define_model(:example, :attr => :string) do
if type
serialize :attr, type
else
serialize :attr
end
end.new
end
def define_serializer(name)
define_class(name) do
def load(*); end
def dump(*); end
end
end
end

View File

@ -3,31 +3,30 @@ require 'spec_helper'
describe Shoulda::Matchers::Independent::DelegateMatcher do
it 'supports chaining on #to' do
matcher = delegate_method(:method)
matcher.to(:another_method).should == matcher
end
it 'supports chaining on #with_arguments' do
matcher = delegate_method(:method)
matcher.with_arguments(1, 2, 3).should == matcher
end
it 'supports chaining on #as' do
matcher = delegate_method(:method)
matcher.as(:some_other_method).should == matcher
end
it 'should raise an error if no delegation target is defined' do
object = Object.new
expect {
object.should delegate_method(:name)
}.to raise_exception Shoulda::Matchers::Independent::DelegateMatcher::TargetNotDefinedError
it 'raises an error if no delegation target is defined' do
expect { Object.new.should delegate_method(:name) }.to raise_exception
described_class::TargetNotDefinedError
end
it 'should raise an error if called with #should_not' do
object = Object.new
expect {
object.should_not delegate_method(:name).to(:anyone)
}.to raise_exception Shoulda::Matchers::Independent::DelegateMatcher::InvalidDelegateMatcher
it 'raises an error if called with #should_not' do
expect { Object.new.should_not delegate_method(:name).to(:anyone) }.to
raise_exception described_class::InvalidDelegateMatcher
end
context 'given a method that does not delegate' do
@ -39,9 +38,10 @@ describe Shoulda::Matchers::Independent::DelegateMatcher do
end
end
it 'does not match' do
it 'rejects' do
post_office = PostOffice.new
matcher = delegate_method(:deliver_mail).to(:mailman)
matcher.matches?(post_office).should be_false
end
@ -66,7 +66,7 @@ describe Shoulda::Matchers::Independent::DelegateMatcher do
end
context 'given a method that delegates properly' do
before do
it 'accepts' do
define_class(:mailman)
define_class(:post_office) do
def deliver_mail
@ -76,12 +76,7 @@ describe Shoulda::Matchers::Independent::DelegateMatcher do
def mailman
Mailman.new
end
end
end
it 'matches' do
post_office = PostOffice.new
post_office.should delegate_method(:deliver_mail).to(:mailman)
end.new.should delegate_method(:deliver_mail).to(:mailman)
end
end
@ -100,17 +95,17 @@ describe Shoulda::Matchers::Independent::DelegateMatcher do
end
context 'when given the correct arguments' do
it 'matches' do
post_office = PostOffice.new
matcher = delegate_method(:deliver_mail).to(:mailman).with_arguments('221B Baker St.', :hastily => true)
post_office.should matcher
it 'accepts' do
PostOffice.new.should delegate_method(:deliver_mail).
to(:mailman).with_arguments('221B Baker St.', :hastily => true)
end
end
context 'when not given the correct arguments' do
it 'does not match' do
it 'rejects' do
post_office = PostOffice.new
matcher = delegate_method(:deliver_mail).to(:mailman).with_arguments('123 Nowhere Ln.')
matcher = delegate_method(:deliver_mail).to(:mailman).
with_arguments('123 Nowhere Ln.')
matcher.matches?(post_office).should be_false
end
@ -141,15 +136,14 @@ describe Shoulda::Matchers::Independent::DelegateMatcher do
end
context 'when given the correct method name' do
it 'matches' do
post_office = PostOffice.new
matcher = delegate_method(:deliver_mail).to(:mailman).as(:deliver_mail_and_avoid_dogs)
post_office.should matcher
it 'accepts' do
PostOffice.new.should
delegate_method(:deliver_mail).to(:mailman).as(:deliver_mail_and_avoid_dogs)
end
end
context 'when given an incorrect method name' do
it 'does not match' do
it 'rejects' do
post_office = PostOffice.new
matcher = delegate_method(:deliver_mail).to(:mailman).as(:watch_tv)
matcher.matches?(post_office).should be_false

View File

@ -20,7 +20,7 @@ Dir[File.join(PROJECT_ROOT, 'spec', 'support', '**', '*.rb')].each { |file| requ
# Run the migrations
ActiveRecord::Migration.verbose = false
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate")
ActiveRecord::Migrator.migrate(Rails.root.join('db/migrate'))
RSpec.configure do |config|
config.mock_with :mocha

View File

@ -0,0 +1,19 @@
module ActiveModelHelpers
def custom_validation(&block)
define_model(:example, :attr => :integer) do
validate :custom_validation
define_method(:custom_validation, &block)
end.new
end
def validating_format(options)
define_model :example, :attr => :string do
validates_format_of :attr, options
end.new
end
end
RSpec.configure do |c|
c.include ActiveModelHelpers
end

View File

@ -36,11 +36,11 @@ module ControllerBuilder
controller_class.view_paths = [TMP_VIEW_PATH]
define_routes do
get "examples", :to => "examples##{action}"
get 'examples', :to => "examples##{action}"
end
create_view("examples/#{action}.html.erb", "action")
create_view("examples/#{partial}.html.erb", "partial")
create_view("examples/#{action}.html.erb", 'action')
create_view("examples/#{partial}.html.erb", 'partial')
@controller = controller_class.new
@request = ActionController::TestRequest.new

View File

@ -46,13 +46,19 @@ module ModelBuilder
def define_model(name, columns = {}, &block)
class_name = name.to_s.pluralize.classify
table_name = class_name.tableize
create_table(table_name) do |table|
table_block = lambda do |table|
columns.each do |name, type|
table.column name, type
end
end
if columns.key?(:id) && columns[:id] == false
columns.delete(:id)
create_table(table_name, :id => false, &table_block)
else
create_table(table_name, &table_block)
end
define_model_class(class_name, &block)
end