1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
|
# frozen_string_literal: true
require "cases/helper"
require "models/topic"
require "models/reply"
require "models/developer"
require "models/computer"
require "models/parrot"
require "models/company"
require "models/price_estimate"
class ValidationsTest < ActiveRecord::TestCase
fixtures :topics, :developers
# 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
repair_validations(Topic)
def test_valid_uses_create_context_when_new
r = WrongReply.new
r.title = "Wrong Create"
assert_not_predicate r, :valid?
assert_predicate r.errors[:title], :any?, "A reply with a bad title should mark that attribute as invalid"
assert_equal ["is Wrong Create"], r.errors[:title], "A reply with a bad content should contain an error"
end
def test_valid_uses_update_context_when_persisted
r = WrongReply.new
r.title = "Bad"
r.content = "Good"
assert r.save, "First validation should be successful"
r.title = "Wrong Update"
assert_not r.valid?, "Second validation should fail"
assert_predicate r.errors[:title], :any?, "A reply with a bad title should mark that attribute as invalid"
assert_equal ["is Wrong Update"], r.errors[:title], "A reply with a bad content should contain an error"
end
def test_valid_using_special_context
r = WrongReply.new(title: "Valid title")
assert_not r.valid?(:special_case)
assert_equal "Invalid", r.errors[:author_name].join
r.author_name = "secret"
r.content = "Good"
assert r.valid?(:special_case)
r.author_name = nil
assert_not r.valid?(:special_case)
assert_equal "Invalid", r.errors[:author_name].join
r.author_name = "secret"
assert r.valid?(:special_case)
end
def test_invalid_using_multiple_contexts
r = WrongReply.new(title: "Wrong Create")
assert r.invalid?([:special_case, :create])
assert_equal "Invalid", r.errors[:author_name].join
assert_equal "is Wrong Create", r.errors[:title].join
end
def test_validate
r = WrongReply.new
r.validate
assert_empty r.errors[:author_name]
r.validate(:special_case)
assert_not_empty r.errors[:author_name]
r.author_name = "secret"
r.validate(:special_case)
assert_empty r.errors[:author_name]
end
def test_invalid_record_exception
assert_raise(ActiveRecord::RecordInvalid) { WrongReply.create! }
assert_raise(ActiveRecord::RecordInvalid) { WrongReply.new.save! }
r = WrongReply.new
invalid = assert_raise ActiveRecord::RecordInvalid do
r.save!
end
assert_equal r, invalid.record
end
def test_validate_with_bang
assert_raise(ActiveRecord::RecordInvalid) do
WrongReply.new.validate!
end
end
def test_validate_with_bang_and_context
assert_raise(ActiveRecord::RecordInvalid) do
WrongReply.new.validate!(:special_case)
end
r = WrongReply.new(title: "Valid title", author_name: "secret", content: "Good")
assert r.validate!(:special_case)
end
def test_exception_on_create_bang_many
assert_raise(ActiveRecord::RecordInvalid) do
WrongReply.create!([ { "title" => "OK" }, { "title" => "Wrong Create" }])
end
end
def test_exception_on_create_bang_with_block
assert_raise(ActiveRecord::RecordInvalid) do
WrongReply.create!("title" => "OK") do |r|
r.content = nil
end
end
end
def test_exception_on_create_bang_many_with_block
assert_raise(ActiveRecord::RecordInvalid) do
WrongReply.create!([{ "title" => "OK" }, { "title" => "Wrong Create" }]) do |r|
r.content = nil
end
end
end
def test_save_without_validation
reply = WrongReply.new
assert_not reply.save
assert reply.save(validate: false)
end
def test_validates_acceptance_of_with_non_existent_table
Object.const_set :IncorporealModel, Class.new(ActiveRecord::Base)
assert_nothing_raised do
IncorporealModel.validates_acceptance_of(:incorporeal_column)
end
end
def test_throw_away_typing
d = Developer.new("name" => "David", "salary" => "100,000")
assert_not_predicate d, :valid?
assert_equal 100, d.salary
assert_equal "100,000", d.salary_before_type_cast
end
def test_validates_acceptance_of_with_undefined_attribute_methods
klass = Class.new(Topic)
klass.validates_acceptance_of(:approved)
topic = klass.new(approved: true)
klass.undefine_attribute_methods
assert topic.approved
end
def test_validates_acceptance_of_as_database_column
klass = Class.new(Topic)
klass.validates_acceptance_of(:approved)
topic = klass.create("approved" => true)
assert topic["approved"]
end
def test_validators
assert_equal 1, Parrot.validators.size
assert_equal 1, Company.validators.size
assert_equal 1, Parrot.validators_on(:name).size
assert_equal 1, Company.validators_on(:name).size
end
def test_numericality_validation_with_mutation
klass = Class.new(Topic) do
attribute :wibble, :string
validates_numericality_of :wibble, only_integer: true
end
topic = klass.new(wibble: "123-4567")
topic.wibble.gsub!("-", "")
assert_predicate topic, :valid?
end
def test_numericality_validation_checks_against_raw_value
klass = Class.new(Topic) do
def self.model_name
ActiveModel::Name.new(self, nil, "Topic")
end
attribute :wibble, :decimal, scale: 2, precision: 9
validates_numericality_of :wibble, greater_than_or_equal_to: BigDecimal("97.18")
end
["97.179", 97.179, BigDecimal("97.179")].each do |raw_value|
subject = klass.new(wibble: raw_value)
assert_equal BigDecimal("97.18"), subject.wibble
assert_predicate subject, :valid?
end
["97.174", 97.174, BigDecimal("97.174")].each do |raw_value|
subject = klass.new(wibble: raw_value)
assert_equal BigDecimal("97.17"), subject.wibble
assert_not_predicate subject, :valid?
end
end
def test_numericality_validator_wont_be_affected_by_custom_getter
price_estimate = PriceEstimate.new(price: 50)
assert_equal "$50.00", price_estimate.price
assert_equal 50, price_estimate.price_before_type_cast
assert_equal 50, price_estimate.read_attribute(:price)
assert_predicate price_estimate, :price_came_from_user?
assert_predicate price_estimate, :valid?
price_estimate.save!
assert_not_predicate price_estimate, :price_came_from_user?
assert_predicate price_estimate, :valid?
end
def test_acceptance_validator_doesnt_require_db_connection
klass = Class.new(ActiveRecord::Base) do
self.table_name = "posts"
end
klass.reset_column_information
assert_no_queries do
klass.validates_acceptance_of(:foo)
end
end
end
|