2009-03-20 11:07:49 -04:00
|
|
|
# encoding: utf-8
|
|
|
|
require 'cases/helper'
|
2009-03-20 12:02:12 -04:00
|
|
|
require 'cases/tests_database'
|
2009-03-20 11:07:49 -04:00
|
|
|
|
|
|
|
require 'models/topic'
|
|
|
|
require 'models/reply'
|
|
|
|
require 'models/developer'
|
2009-08-05 12:44:44 -04:00
|
|
|
require 'models/custom_reader'
|
2009-03-20 11:07:49 -04:00
|
|
|
|
|
|
|
class ValidationsTest < ActiveModel::TestCase
|
2009-03-20 12:02:12 -04:00
|
|
|
include ActiveModel::TestsDatabase
|
2009-03-20 11:07:49 -04:00
|
|
|
|
2010-02-18 10:28:48 -05:00
|
|
|
def setup
|
|
|
|
Topic._validators.clear
|
|
|
|
end
|
|
|
|
|
2009-03-20 11:07:49 -04:00
|
|
|
# Most of the tests mess with the validations of Topic, so lets repair it all the time.
|
|
|
|
# Other classes we mess with will be dealt with in the specific tests
|
2009-12-23 07:30:58 -05:00
|
|
|
def teardown
|
|
|
|
Topic.reset_callbacks(:validate)
|
|
|
|
end
|
2009-03-20 11:07:49 -04:00
|
|
|
|
|
|
|
def test_single_field_validation
|
|
|
|
r = Reply.new
|
|
|
|
r.title = "There's no content!"
|
|
|
|
assert !r.valid?, "A reply without content shouldn't be saveable"
|
|
|
|
|
|
|
|
r.content = "Messa content!"
|
|
|
|
assert r.valid?, "A reply with content should be saveable"
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_single_attr_validation_and_error_msg
|
|
|
|
r = Reply.new
|
|
|
|
r.title = "There's no content!"
|
|
|
|
assert !r.valid?
|
2009-03-21 14:29:15 -04:00
|
|
|
assert r.errors[:content].any?, "A reply without content should mark that attribute as invalid"
|
2009-03-20 11:07:49 -04:00
|
|
|
assert_equal ["Empty"], r.errors["content"], "A reply without content should contain an error"
|
|
|
|
assert_equal 1, r.errors.count
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_double_attr_validation_and_error_msg
|
|
|
|
r = Reply.new
|
|
|
|
assert !r.valid?
|
|
|
|
|
2009-03-21 14:29:15 -04:00
|
|
|
assert r.errors[:title].any?, "A reply without title should mark that attribute as invalid"
|
2009-03-20 11:07:49 -04:00
|
|
|
assert_equal ["Empty"], r.errors["title"], "A reply without title should contain an error"
|
|
|
|
|
2009-03-21 14:29:15 -04:00
|
|
|
assert r.errors[:content].any?, "A reply without content should mark that attribute as invalid"
|
2009-03-20 11:07:49 -04:00
|
|
|
assert_equal ["Empty"], r.errors["content"], "A reply without content should contain an error"
|
|
|
|
|
|
|
|
assert_equal 2, r.errors.count
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_single_error_per_attr_iteration
|
|
|
|
r = Reply.new
|
|
|
|
r.save
|
|
|
|
|
|
|
|
errors = []
|
|
|
|
r.errors.each {|attr, messages| errors << [attr.to_s, messages] }
|
|
|
|
|
|
|
|
assert errors.include?(["title", "Empty"])
|
|
|
|
assert errors.include?(["content", "Empty"])
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_multiple_errors_per_attr_iteration_with_full_error_composition
|
|
|
|
r = Reply.new
|
|
|
|
r.title = "Wrong Create"
|
|
|
|
r.content = "Mismatch"
|
|
|
|
r.save
|
|
|
|
|
|
|
|
errors = r.errors.to_a
|
|
|
|
|
|
|
|
assert_equal "Title is Wrong Create", errors[0]
|
|
|
|
assert_equal "Title is Content Mismatch", errors[1]
|
|
|
|
assert_equal 2, r.errors.count
|
|
|
|
end
|
|
|
|
|
2009-12-31 07:44:15 -05:00
|
|
|
def test_errors_on_nested_attributes_expands_name
|
|
|
|
t = Topic.new
|
|
|
|
t.errors["replies.name"] << "can't be blank"
|
|
|
|
assert_equal ["Replies name can't be blank"], t.errors.full_messages
|
|
|
|
end
|
|
|
|
|
2009-03-20 11:07:49 -04:00
|
|
|
def test_errors_on_base
|
|
|
|
r = Reply.new
|
|
|
|
r.content = "Mismatch"
|
|
|
|
r.save
|
2009-03-21 14:29:15 -04:00
|
|
|
r.errors[:base] << "Reply is not dignifying"
|
2009-03-20 11:07:49 -04:00
|
|
|
|
|
|
|
errors = []
|
2009-03-21 14:29:15 -04:00
|
|
|
r.errors.to_a.each { |error| errors << error }
|
2009-03-20 11:07:49 -04:00
|
|
|
|
2009-03-20 13:36:22 -04:00
|
|
|
assert_equal ["Reply is not dignifying"], r.errors[:base]
|
2009-03-20 11:07:49 -04:00
|
|
|
|
|
|
|
assert errors.include?("Title Empty")
|
|
|
|
assert errors.include?("Reply is not dignifying")
|
|
|
|
assert_equal 2, r.errors.count
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_validates_each
|
|
|
|
hits = 0
|
|
|
|
Topic.validates_each(:title, :content, [:title, :content]) do |record, attr|
|
|
|
|
record.errors.add attr, 'gotcha'
|
|
|
|
hits += 1
|
|
|
|
end
|
|
|
|
t = Topic.new("title" => "valid", "content" => "whatever")
|
|
|
|
assert !t.save
|
|
|
|
assert_equal 4, hits
|
|
|
|
assert_equal %w(gotcha gotcha), t.errors[:title]
|
|
|
|
assert_equal %w(gotcha gotcha), t.errors[:content]
|
|
|
|
end
|
2009-08-05 12:44:44 -04:00
|
|
|
|
|
|
|
def test_validates_each_custom_reader
|
|
|
|
hits = 0
|
|
|
|
CustomReader.validates_each(:title, :content, [:title, :content]) do |record, attr|
|
|
|
|
record.errors.add attr, 'gotcha'
|
|
|
|
hits += 1
|
|
|
|
end
|
|
|
|
t = CustomReader.new("title" => "valid", "content" => "whatever")
|
|
|
|
assert !t.valid?
|
|
|
|
assert_equal 4, hits
|
|
|
|
assert_equal %w(gotcha gotcha), t.errors[:title]
|
|
|
|
assert_equal %w(gotcha gotcha), t.errors[:content]
|
|
|
|
end
|
2009-03-20 11:07:49 -04:00
|
|
|
|
|
|
|
def test_validate_block
|
|
|
|
Topic.validate { |topic| topic.errors.add("title", "will never be valid") }
|
|
|
|
t = Topic.create("title" => "Title", "content" => "whatever")
|
|
|
|
assert !t.valid?
|
|
|
|
assert t.errors[:title].any?
|
|
|
|
assert_equal ["will never be valid"], t.errors["title"]
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_invalid_validator
|
2009-09-08 11:10:14 -04:00
|
|
|
Topic.validate :i_dont_exist
|
|
|
|
assert_raise(NameError) { t = Topic.create }
|
2009-03-20 11:07:49 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_errors_to_xml
|
|
|
|
r = Reply.new :title => "Wrong Create"
|
|
|
|
assert !r.valid?
|
|
|
|
xml = r.errors.to_xml(:skip_instruct => true)
|
|
|
|
assert_equal "<errors>", xml.first(8)
|
|
|
|
assert xml.include?("<error>Title is Wrong Create</error>")
|
|
|
|
assert xml.include?("<error>Content Empty</error>")
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_validation_order
|
|
|
|
Topic.validates_presence_of :title
|
|
|
|
Topic.validates_length_of :title, :minimum => 2
|
|
|
|
|
|
|
|
t = Topic.new("title" => "")
|
|
|
|
assert !t.valid?
|
|
|
|
assert_equal "can't be blank", t.errors["title"].first
|
2009-03-19 01:42:08 -04:00
|
|
|
Topic.validates_presence_of :title, :author_name
|
|
|
|
Topic.validate {|topic| topic.errors.add('author_email_address', 'will never be valid')}
|
|
|
|
Topic.validates_length_of :title, :content, :minimum => 2
|
|
|
|
|
|
|
|
t = Topic.new :title => ''
|
|
|
|
assert !t.valid?
|
|
|
|
|
|
|
|
assert_equal :title, key = t.errors.keys.first
|
|
|
|
assert_equal "can't be blank", t.errors[key].first
|
|
|
|
assert_equal 'is too short (minimum is 2 characters)', t.errors[key].second
|
|
|
|
assert_equal :author_name, key = t.errors.keys.second
|
|
|
|
assert_equal "can't be blank", t.errors[key].first
|
|
|
|
assert_equal :author_email_address, key = t.errors.keys.third
|
|
|
|
assert_equal 'will never be valid', t.errors[key].first
|
|
|
|
assert_equal :content, key = t.errors.keys.fourth
|
|
|
|
assert_equal 'is too short (minimum is 2 characters)', t.errors[key].first
|
2009-03-20 11:07:49 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_invalid_should_be_the_opposite_of_valid
|
|
|
|
Topic.validates_presence_of :title
|
|
|
|
|
|
|
|
t = Topic.new
|
|
|
|
assert t.invalid?
|
2009-03-21 14:29:15 -04:00
|
|
|
assert t.errors[:title].any?
|
2009-03-20 11:07:49 -04:00
|
|
|
|
|
|
|
t.title = 'Things are going to change'
|
|
|
|
assert !t.invalid?
|
|
|
|
end
|
2009-03-20 13:36:22 -04:00
|
|
|
|
|
|
|
def test_deprecated_error_messages_on
|
|
|
|
Topic.validates_presence_of :title
|
|
|
|
|
|
|
|
t = Topic.new
|
|
|
|
assert t.invalid?
|
|
|
|
|
|
|
|
[:title, "title"].each do |attribute|
|
|
|
|
assert_deprecated { assert_equal "can't be blank", t.errors.on(attribute) }
|
|
|
|
end
|
|
|
|
|
|
|
|
Topic.validates_each(:title) do |record, attribute|
|
|
|
|
record.errors[attribute] << "invalid"
|
|
|
|
end
|
|
|
|
|
|
|
|
assert t.invalid?
|
|
|
|
|
|
|
|
[:title, "title"].each do |attribute|
|
|
|
|
assert_deprecated do
|
|
|
|
assert t.errors.on(attribute).include?("invalid")
|
|
|
|
assert t.errors.on(attribute).include?("can't be blank")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2009-03-21 14:29:15 -04:00
|
|
|
|
|
|
|
def test_deprecated_errors_on_base_and_each
|
|
|
|
t = Topic.new
|
|
|
|
assert t.valid?
|
|
|
|
|
|
|
|
assert_deprecated { t.errors.add_to_base "invalid topic" }
|
|
|
|
assert_deprecated { assert_equal "invalid topic", t.errors.on_base }
|
|
|
|
assert_deprecated { assert t.errors.invalid?(:base) }
|
|
|
|
|
|
|
|
all_errors = t.errors.to_a
|
|
|
|
assert_deprecated { assert_equal all_errors, t.errors.each_full{|err| err} }
|
|
|
|
end
|
2010-01-17 06:15:52 -05:00
|
|
|
|
|
|
|
def test_validation_with_message_as_proc
|
|
|
|
Topic.validates_presence_of(:title, :message => proc { "no blanks here".upcase })
|
|
|
|
|
|
|
|
t = Topic.new
|
|
|
|
assert !t.valid?
|
|
|
|
assert ["NO BLANKS HERE"], t.errors[:title]
|
|
|
|
end
|
2010-02-18 10:28:48 -05:00
|
|
|
|
|
|
|
def test_list_of_validators_for_model
|
|
|
|
Topic.validates_presence_of :title
|
|
|
|
Topic.validates_length_of :title, :minimum => 2
|
|
|
|
|
|
|
|
assert_equal 2, Topic.validators.count
|
|
|
|
assert_equal [:presence, :length], Topic.validators.map(&:kind)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_list_of_validators_on_an_attribute
|
|
|
|
Topic.validates_presence_of :title, :content
|
|
|
|
Topic.validates_length_of :title, :minimum => 2
|
|
|
|
|
|
|
|
assert_equal 2, Topic.validators_on(:title).count
|
|
|
|
assert_equal [:presence, :length], Topic.validators_on(:title).map(&:kind)
|
|
|
|
assert_equal 1, Topic.validators_on(:content).count
|
|
|
|
assert_equal [:presence], Topic.validators_on(:content).map(&:kind)
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_accessing_instance_of_validator_on_an_attribute
|
|
|
|
Topic.validates_length_of :title, :minimum => 10
|
|
|
|
assert_equal 10, Topic.validators_on(:title).first.options[:minimum]
|
|
|
|
end
|
2009-09-08 11:10:14 -04:00
|
|
|
end
|