require File.join(File.dirname(__FILE__), "test_helper") class ValidationsTest < Test::Unit::TestCase class Event < Ohm::Model attribute :name attribute :place attribute :capacity index :name index :place def validate assert_format(:name, /^\w+$/) end end context "A new model with validations" do setup do @event = Event.new end context "That must have a present name" do should "not be created if the name is never assigned" do @event.create assert @event.new? end should "not be created if the name assigned is empty" do @event.name = "" @event.create assert @event.new? end should "be created if the name assigned is not empty" do @event.name = "hello" @event.create assert_not_nil @event.id end context "And must have a name with only \w+" do should "not be created if the name doesn't match /^\w+$/" do @event.name = "hello-world" @event.create assert @event.new? end end end context "That must have a numeric attribute :capacity" do should "fail when the value is nil" do def @event.validate assert_numeric :capacity end @event.name = "foo" @event.place = "bar" @event.create assert @event.new? assert_equal [[:capacity, :not_numeric]], @event.errors end should "fail when the value is not numeric" do def @event.validate assert_numeric :capacity end @event.name = "foo" @event.place = "bar" @event.capacity = "baz" @event.create assert @event.new? assert_equal [[:capacity, :not_numeric]], @event.errors end should "succeed when the value is numeric" do def @event.validate assert_numeric :capacity end @event.name = "foo" @event.place = "bar" @event.capacity = 42 @event.create assert_not_nil @event.id end end context "That must have a unique name" do should "fail when the value already exists" do def @event.validate assert_unique :name end Event.create(:name => "foo") @event.name = "foo" @event.create assert @event.new? assert_equal [[:name, :not_unique]], @event.errors end end context "That must have a unique name scoped by place" do should "fail when the value already exists for a scoped attribute" do def @event.validate assert_unique [:name, :place] end Event.create(:name => "foo", :place => "bar") @event.name = "foo" @event.place = "bar" @event.create assert @event.new? assert_equal [[[:name, :place], :not_unique]], @event.errors @event.place = "baz" @event.create assert @event.valid? end end context "That defines a unique validation on a non indexed attribute" do should "raise ArgumentError" do def @event.validate assert_unique :capacity end assert_raises(Ohm::Model::IndexNotFound) do @event.valid? end end end end context "An existing model with a valid name" do setup do @event = Event.create(:name => "original") end context "That has the name changed" do should "not be saved if the new name is nil" do @event.name = nil @event.save assert_equal false, @event.valid? assert_equal "original", Event[@event.id].name end should "not be saved if the name assigned is empty" do @event.name = "" @event.save assert_equal false, @event.valid? assert_equal "original", Event[@event.id].name end should "be saved if the name assigned is not empty" do @event.name = "hello" @event.save assert @event.valid? assert_equal "hello", Event[@event.id].name end end end context "Validations module" do class Validatable attr_accessor :name include Ohm::Validations end setup do @target = Validatable.new end context "assert" do should "add errors to a collection" do def @target.validate assert(false, "Something bad") end @target.validate assert_equal ["Something bad"], @target.errors end should "allow for nested validations" do def @target.validate if assert(true, "No error") assert(false, "Chained error") end if assert(false, "Parent error") assert(false, "No chained error") end end @target.validate assert_equal ["Chained error", "Parent error"], @target.errors end end context "assert_present" do setup do def @target.validate assert_present(:name) end end should "fail when the attribute is nil" do @target.validate assert_equal [[:name, :not_present]], @target.errors end should "fail when the attribute is empty" do @target.name = "" @target.validate assert_equal [[:name, :not_present]], @target.errors end end end end