1
0
Fork 0
mirror of https://github.com/thoughtbot/shoulda-matchers.git synced 2022-11-09 12:01:38 -05:00

Enhanced assert_good/bad_value assertions in preparation for stateful AR validations

This commit is contained in:
Ryan McGeary 2008-07-31 00:04:05 -04:00
parent abc3aa73a4
commit 5196f3a98f
5 changed files with 93 additions and 6 deletions

View file

@ -182,9 +182,20 @@ module ThoughtBot # :nodoc:
# <tt>value</tt> by making sure the <tt>error_message_to_avoid</tt> is not
# contained within the list of errors for that attribute.
#
# assert_good_value(User.new, :email, "user@example.com") #=> passes
# assert_good_value(User.new, :ssn, "123456789", /length/) #=> passes
def assert_good_value(object, attribute, value, error_message_to_avoid = //)
# assert_good_value(User.new, :email, "user@example.com")
# assert_good_value(User.new, :ssn, "123456789", /length/)
#
# If a class is passed as the first argument, a new object will be
# instantiated before the assertion. If an instance variable exists with
# the same name as the class (underscored), that object will be used
# instead.
#
# assert_good_value(User, :email, "user@example.com")
#
# @product = Product.new(:tangible => false)
# assert_good_value(Product, :price, "0")
def assert_good_value(object_or_klass, attribute, value, error_message_to_avoid = //)
object = get_instance_of(object_or_klass)
object.send("#{attribute}=", value)
object.valid?
assert_does_not_contain(object.errors.on(attribute), error_message_to_avoid, "when set to #{value.inspect}")
@ -194,9 +205,20 @@ module ThoughtBot # :nodoc:
# <tt>value</tt> by making sure the <tt>error_message_to_expect</tt> is
# contained within the list of errors for that attribute.
#
# assert_bad_value(User.new, :email, "invalid") #=> passes
# assert_bad_value(User.new, :ssn, "123", /length/) #=> passes
def assert_bad_value(object, attribute, value, error_message_to_expect = /invalid/)
# assert_bad_value(User.new, :email, "invalid")
# assert_bad_value(User.new, :ssn, "123", /length/)
#
# If a class is passed as the first argument, a new object will be
# instantiated before the assertion. If an instance variable exists with
# the same name as the class (underscored), that object will be used
# instead.
#
# assert_bad_value(User, :email, "invalid")
#
# @product = Product.new(:tangible => true)
# assert_bad_value(Product, :price, "0")
def assert_bad_value(object_or_klass, attribute, value, error_message_to_expect = /invalid/)
object = get_instance_of(object_or_klass)
object.send("#{attribute}=", value)
assert !object.valid?, "#{object.class} allowed #{value.inspect} as a value for #{attribute}"
assert object.errors.on(attribute), "There are no errors on #{attribute} after being set to #{value.inspect}"
@ -206,6 +228,17 @@ module ThoughtBot # :nodoc:
def pretty_error_messages(obj)
obj.errors.map { |a, m| "#{a} #{m} (#{obj.send(a).inspect})" }
end
private
def get_instance_of(object_or_klass)
if object_or_klass.is_a?(Class)
klass = object_or_klass
instance_variable_get("@#{klass.to_s.underscore}") || klass.new
else
object_or_klass
end
end
end
end
end

0
test/fixtures/products.yml vendored Normal file
View file

View file

@ -129,6 +129,20 @@ class HelpersTest < Test::Unit::TestCase # :nodoc:
assert_good_value User.new, :ssn, "x", /length/
end
end
should "accept a class as the first argument" do
assert_good_value User, :email, "good@example.com"
end
context "with an instance variable" do
setup do
@product = Product.new(:tangible => true)
end
should "use that instance variable" do
assert_good_value Product, :price, "9999", /included/
end
end
end
context "assert_bad_value" do
@ -151,5 +165,19 @@ class HelpersTest < Test::Unit::TestCase # :nodoc:
assert_bad_value User.new, :ssn, "xxxxxxxxx", /length/
end
end
should "accept a class as the first argument" do
assert_bad_value User, :email, "bad"
end
context "with an instance variable" do
setup do
@product = Product.new(:tangible => true)
end
should "use that instance variable" do
assert_bad_value Product, :price, "0", /included/
end
end
end
end

View file

@ -0,0 +1,9 @@
class Product < ActiveRecord::Base
validates_presence_of :title, :price
validates_inclusion_of :price, :in => 0..99, :unless => :tangible
validates_inclusion_of :price, :in => 1..9999, :if => :tangible
validates_inclusion_of :weight, :in => 1..100, :if => :tangible
validates_format_of :size, :with => /.+x.+x.+/, :if => :tangible
validates_length_of :size, :in => 5..20, :if => :tangible
end

View file

@ -0,0 +1,17 @@
class CreateProducts < ActiveRecord::Migration
def self.up
create_table :products do |t|
t.string :title
t.integer :price
t.integer :weight
t.string :size
t.boolean :tangible
t.timestamps
end
end
def self.down
drop_table :products
end
end