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:
parent
abc3aa73a4
commit
5196f3a98f
5 changed files with 93 additions and 6 deletions
|
@ -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
0
test/fixtures/products.yml
vendored
Normal 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
|
||||
|
|
9
test/rails_root/app/models/product.rb
Normal file
9
test/rails_root/app/models/product.rb
Normal 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
|
17
test/rails_root/db/migrate/009_create_products.rb
Normal file
17
test/rails_root/db/migrate/009_create_products.rb
Normal 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
|
Loading…
Add table
Reference in a new issue