Files
prism/test/test_orm_validations_extended.rb

106 lines
3.6 KiB
Ruby

require 'minitest/autorun'
require 'prism'
require 'tmpdir'
class OrmValidationsExtendedTest < Minitest::Test
def setup
@dir = Dir.mktmpdir('prism-validation-ext-store')
@store = Prism::Orm::Store.new(File.join(@dir, 'test.pstore'))
@store.create_table(:products, %w[id name price quantity status])
@product_class = Class.new(Prism::Orm::Model) do
table_name :products
validates_numericality_of :price, greater_than: 0
validates_numericality_of :quantity, only_integer: true, greater_than_or_equal_to: 0
validates_inclusion_of :status, in: %w[draft published archived]
validate :name_must_not_be_shouting
def name_must_not_be_shouting
return unless name && name == name.upcase && name.match?(/[A-Z]/)
errors.add(:name, 'must not be all caps')
end
end
@product_class.store = @store
Object.const_set(:Product, @product_class)
end
def teardown
FileUtils.remove_entry(@dir)
Object.send(:remove_const, :Product) if Object.const_defined?(:Product)
end
def test_numericality_rejects_non_numbers
product = Product.new(name: 'widget', price: 'free', quantity: 1, status: 'draft')
refute product.valid?
assert_includes product.errors[:price], 'is not a number'
end
def test_numericality_enforces_greater_than
product = Product.new(name: 'widget', price: 0, quantity: 1, status: 'draft')
refute product.valid?
assert_includes product.errors[:price], 'must be greater than 0'
end
def test_numericality_only_integer
product = Product.new(name: 'widget', price: 5, quantity: 1.5, status: 'draft')
refute product.valid?
assert_includes product.errors[:quantity], 'must be an integer'
end
def test_numericality_passes_for_valid_number
product = Product.new(name: 'widget', price: 9.99, quantity: 3, status: 'draft')
assert product.valid?, product.errors.full_messages.join(', ')
end
def test_inclusion_rejects_value_outside_set
product = Product.new(name: 'widget', price: 1, quantity: 1, status: 'deleted')
refute product.valid?
assert_includes product.errors[:status], 'is not included in the list'
end
def test_inclusion_accepts_value_in_set
product = Product.new(name: 'widget', price: 1, quantity: 1, status: 'published')
assert product.valid?, product.errors.full_messages.join(', ')
end
def test_exclusion_rejects_reserved_values
klass = Class.new(Prism::Orm::Model) do
table_name :products
validates_exclusion_of :name, in: %w[admin root]
end
klass.store = @store
reserved = klass.new(name: 'admin')
refute reserved.valid?
assert_includes reserved.errors[:name], 'is reserved'
end
def test_custom_validator_method_adds_error
product = Product.new(name: 'SHOUT', price: 1, quantity: 1, status: 'draft')
refute product.valid?
assert_includes product.errors[:name], 'must not be all caps'
end
def test_custom_validator_block
klass = Class.new(Prism::Orm::Model) do
table_name :products
validate { errors.add(:base, 'always invalid') if name == 'reject-me' }
end
klass.store = @store
record = klass.new(name: 'reject-me')
refute record.valid?
assert_includes record.errors[:base], 'always invalid'
end
def test_custom_message_on_numericality
klass = Class.new(Prism::Orm::Model) do
table_name :products
validates_numericality_of :price, greater_than: 0, message: 'needs a positive price'
end
klass.store = @store
record = klass.new(name: 'x', price: -1)
refute record.valid?
assert_includes record.errors[:price], 'needs a positive price'
end
end