diff options
Diffstat (limited to 'activemodel/test/cases')
17 files changed, 549 insertions, 73 deletions
diff --git a/activemodel/test/cases/attribute_methods_test.rb b/activemodel/test/cases/attribute_methods_test.rb index c60caf90d7..022c6716bd 100644 --- a/activemodel/test/cases/attribute_methods_test.rb +++ b/activemodel/test/cases/attribute_methods_test.rb @@ -2,9 +2,15 @@ require 'cases/helper' class ModelWithAttributes include ActiveModel::AttributeMethods - + attribute_method_suffix '' + class << self + define_method(:bar) do + 'original bar' + end + end + def attributes { :foo => 'value of foo' } end @@ -17,29 +23,110 @@ end class ModelWithAttributes2 include ActiveModel::AttributeMethods - + attribute_method_suffix '_test' end +class ModelWithAttributesWithSpaces + include ActiveModel::AttributeMethods + + attribute_method_suffix '' + + def attributes + { :'foo bar' => 'value of foo bar'} + end + +private + def attribute(name) + attributes[name.to_sym] + end +end + +class ModelWithWeirdNamesAttributes + include ActiveModel::AttributeMethods + + attribute_method_suffix '' + + class << self + define_method(:'c?d') do + 'original c?d' + end + end + + def attributes + { :'a?b' => 'value of a?b' } + end + +private + def attribute(name) + attributes[name.to_sym] + end +end + class AttributeMethodsTest < ActiveModel::TestCase test 'unrelated classes should not share attribute method matchers' do assert_not_equal ModelWithAttributes.send(:attribute_method_matchers), ModelWithAttributes2.send(:attribute_method_matchers) end + test '#define_attribute_method generates attribute method' do + ModelWithAttributes.define_attribute_method(:foo) + + assert_respond_to ModelWithAttributes.new, :foo + assert_equal "value of foo", ModelWithAttributes.new.foo + end + + test '#define_attribute_method generates attribute method with invalid identifier characters' do + ModelWithWeirdNamesAttributes.define_attribute_method(:'a?b') + ModelWithWeirdNamesAttributes.define_attribute_method(:'a?b') + + assert_respond_to ModelWithWeirdNamesAttributes.new, :'a?b' + assert_equal "value of a?b", ModelWithWeirdNamesAttributes.new.send('a?b') + end + test '#define_attribute_methods generates attribute methods' do ModelWithAttributes.define_attribute_methods([:foo]) - assert ModelWithAttributes.attribute_methods_generated? assert_respond_to ModelWithAttributes.new, :foo assert_equal "value of foo", ModelWithAttributes.new.foo end + test '#define_attribute_methods generates attribute methods with spaces in their names' do + ModelWithAttributesWithSpaces.define_attribute_methods([:'foo bar']) + + assert_respond_to ModelWithAttributesWithSpaces.new, :'foo bar' + assert_equal "value of foo bar", ModelWithAttributesWithSpaces.new.send(:'foo bar') + end + + test '#define_attr_method generates attribute method' do + ModelWithAttributes.define_attr_method(:bar, 'bar') + + assert_respond_to ModelWithAttributes, :bar + assert_equal "original bar", ModelWithAttributes.original_bar + assert_equal "bar", ModelWithAttributes.bar + ModelWithAttributes.define_attr_method(:bar) + assert !ModelWithAttributes.bar + end + + test '#define_attr_method generates attribute method with invalid identifier characters' do + ModelWithWeirdNamesAttributes.define_attr_method(:'c?d', 'c?d') + + assert_respond_to ModelWithWeirdNamesAttributes, :'c?d' + assert_equal "original c?d", ModelWithWeirdNamesAttributes.send('original_c?d') + assert_equal "c?d", ModelWithWeirdNamesAttributes.send('c?d') + end + + test '#alias_attribute works with attributes with spaces in their names' do + ModelWithAttributesWithSpaces.define_attribute_methods([:'foo bar']) + ModelWithAttributesWithSpaces.alias_attribute(:'foo_bar', :'foo bar') + + assert_equal "value of foo bar", ModelWithAttributesWithSpaces.new.foo_bar + end + test '#undefine_attribute_methods removes attribute methods' do ModelWithAttributes.define_attribute_methods([:foo]) ModelWithAttributes.undefine_attribute_methods - assert !ModelWithAttributes.attribute_methods_generated? assert !ModelWithAttributes.new.respond_to?(:foo) assert_raises(NoMethodError) { ModelWithAttributes.new.foo } end diff --git a/activemodel/test/cases/callbacks_test.rb b/activemodel/test/cases/callbacks_test.rb index 9675b5d450..086e7266ff 100644 --- a/activemodel/test/cases/callbacks_test.rb +++ b/activemodel/test/cases/callbacks_test.rb @@ -16,6 +16,8 @@ class CallbacksTest < ActiveModel::TestCase define_model_callbacks :create define_model_callbacks :initialize, :only => :after + define_model_callbacks :multiple, :only => [:before, :around] + define_model_callbacks :empty, :only => [] before_create :before_create around_create CallbackValidator.new @@ -35,7 +37,7 @@ class CallbacksTest < ActiveModel::TestCase end def create - _run_create_callbacks do + run_callbacks :create do @callbacks << :create @valid end @@ -67,4 +69,46 @@ class CallbacksTest < ActiveModel::TestCase assert !ModelCallbacks.respond_to?(:around_initialize) assert_respond_to ModelCallbacks, :after_initialize end + + test "only selects which types of callbacks should be created from an array list" do + assert_respond_to ModelCallbacks, :before_multiple + assert_respond_to ModelCallbacks, :around_multiple + assert !ModelCallbacks.respond_to?(:after_multiple) + end + + test "no callbacks should be created" do + assert !ModelCallbacks.respond_to?(:before_empty) + assert !ModelCallbacks.respond_to?(:around_empty) + assert !ModelCallbacks.respond_to?(:after_empty) + end + + class Violin + attr_reader :history + def initialize + @history = [] + end + extend ActiveModel::Callbacks + define_model_callbacks :create + def callback1; self.history << 'callback1'; end + def callback2; self.history << 'callback2'; end + def create + run_callbacks(:create) {} + self + end + end + class Violin1 < Violin + after_create :callback1, :callback2 + end + class Violin2 < Violin + after_create :callback1 + after_create :callback2 + end + + test "after_create callbacks with both callbacks declared in one line" do + assert_equal ["callback1", "callback2"], Violin1.new.create.history + end + test "after_create callbacks with both callbacks declared in differnt lines" do + assert_equal ["callback1", "callback2"], Violin2.new.create.history + end + end diff --git a/activemodel/test/cases/errors_test.rb b/activemodel/test/cases/errors_test.rb index 79b45bb298..a24cac40ad 100644 --- a/activemodel/test/cases/errors_test.rb +++ b/activemodel/test/cases/errors_test.rb @@ -25,7 +25,19 @@ class ErrorsTest < ActiveModel::TestCase def self.lookup_ancestors [self] end + end + + def test_include? + errors = ActiveModel::Errors.new(self) + errors[:foo] = 'omg' + assert errors.include?(:foo), 'errors should include :foo' + end + test "should return true if no errors" do + person = Person.new + person.errors[:foo] + assert person.errors.empty? + assert person.errors.blank? end test "method validate! should work" do @@ -62,4 +74,9 @@ class ErrorsTest < ActiveModel::TestCase end + test 'to_hash should return an ordered hash' do + person = Person.new + person.errors.add(:name, "can not be blank") + assert_instance_of ActiveSupport::OrderedHash, person.errors.to_hash + end end diff --git a/activemodel/test/cases/helper.rb b/activemodel/test/cases/helper.rb index a32f11484a..01f0158678 100644 --- a/activemodel/test/cases/helper.rb +++ b/activemodel/test/cases/helper.rb @@ -6,16 +6,9 @@ $:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) require 'config' require 'active_model' require 'active_support/core_ext/string/access' -require 'active_support/core_ext/hash/except' # Show backtraces for deprecated behavior for quicker cleanup. ActiveSupport::Deprecation.debug = true require 'rubygems' require 'test/unit' - -begin - require 'ruby-debug' - Debugger.start -rescue LoadError -end diff --git a/activemodel/test/cases/mass_assignment_security_test.rb b/activemodel/test/cases/mass_assignment_security_test.rb index c25b0fdf00..f84e55e8d9 100644 --- a/activemodel/test/cases/mass_assignment_security_test.rb +++ b/activemodel/test/cases/mass_assignment_security_test.rb @@ -25,13 +25,13 @@ class MassAssignmentSecurityTest < ActiveModel::TestCase end def test_mass_assignment_protection_inheritance - assert LoosePerson.accessible_attributes.blank? + assert_blank LoosePerson.accessible_attributes assert_equal Set.new([ 'credit_rating', 'administrator']), LoosePerson.protected_attributes - assert LooseDescendant.accessible_attributes.blank? + assert_blank LooseDescendant.accessible_attributes assert_equal Set.new([ 'credit_rating', 'administrator', 'phone_number']), LooseDescendant.protected_attributes - assert LooseDescendantSecond.accessible_attributes.blank? + assert_blank LooseDescendantSecond.accessible_attributes assert_equal Set.new([ 'credit_rating', 'administrator', 'phone_number', 'name']), LooseDescendantSecond.protected_attributes, 'Running attr_protected twice in one class should merge the protections' diff --git a/activemodel/test/cases/naming_test.rb b/activemodel/test/cases/naming_test.rb index 5a8bff378a..a7dde2c433 100644 --- a/activemodel/test/cases/naming_test.rb +++ b/activemodel/test/cases/naming_test.rb @@ -2,6 +2,7 @@ require 'cases/helper' require 'models/contact' require 'models/sheep' require 'models/track_back' +require 'models/blog_post' class NamingTest < ActiveModel::TestCase def setup @@ -27,6 +28,90 @@ class NamingTest < ActiveModel::TestCase def test_partial_path assert_equal 'post/track_backs/track_back', @model_name.partial_path end + + def test_human + assert_equal 'Track back', @model_name.human + end +end + +class NamingWithNamespacedModelInIsolatedNamespaceTest < ActiveModel::TestCase + def setup + @model_name = ActiveModel::Name.new(Blog::Post, Blog) + end + + def test_singular + assert_equal 'blog_post', @model_name.singular + end + + def test_plural + assert_equal 'blog_posts', @model_name.plural + end + + def test_element + assert_equal 'post', @model_name.element + end + + def test_collection + assert_equal 'blog/posts', @model_name.collection + end + + def test_partial_path + assert_equal 'blog/posts/post', @model_name.partial_path + end + + def test_human + assert_equal 'Post', @model_name.human + end + + def test_route_key + assert_equal 'posts', @model_name.route_key + end + + def test_param_key + assert_equal 'post', @model_name.param_key + end + + def test_recognizing_namespace + assert_equal 'Post', Blog::Post.model_name.instance_variable_get("@unnamespaced") + end +end + +class NamingWithNamespacedModelInSharedNamespaceTest < ActiveModel::TestCase + def setup + @model_name = ActiveModel::Name.new(Blog::Post) + end + + def test_singular + assert_equal 'blog_post', @model_name.singular + end + + def test_plural + assert_equal 'blog_posts', @model_name.plural + end + + def test_element + assert_equal 'post', @model_name.element + end + + def test_collection + assert_equal 'blog/posts', @model_name.collection + end + + def test_partial_path + assert_equal 'blog/posts/post', @model_name.partial_path + end + + def test_human + assert_equal 'Post', @model_name.human + end + + def test_route_key + assert_equal 'blog_posts', @model_name.route_key + end + + def test_param_key + assert_equal 'blog_post', @model_name.param_key + end end class NamingHelpersTest < Test::Unit::TestCase @@ -36,6 +121,12 @@ class NamingHelpersTest < Test::Unit::TestCase @singular = 'contact' @plural = 'contacts' @uncountable = Sheep + @route_key = 'contacts' + @param_key = 'contact' + end + + def test_to_model_called_on_record + assert_equal 'post_named_track_backs', plural(Post::TrackBack.new) end def test_singular @@ -54,6 +145,22 @@ class NamingHelpersTest < Test::Unit::TestCase assert_equal @plural, plural(@klass) end + def test_route_key + assert_equal @route_key, route_key(@record) + end + + def test_route_key_for_class + assert_equal @route_key, route_key(@klass) + end + + def test_param_key + assert_equal @param_key, param_key(@record) + end + + def test_param_key_for_class + assert_equal @param_key, param_key(@klass) + end + def test_uncountable assert uncountable?(@uncountable), "Expected 'sheep' to be uncoutable" assert !uncountable?(@klass), "Expected 'contact' to be countable" diff --git a/activemodel/test/cases/secure_password_test.rb b/activemodel/test/cases/secure_password_test.rb new file mode 100644 index 0000000000..4a47a7a226 --- /dev/null +++ b/activemodel/test/cases/secure_password_test.rb @@ -0,0 +1,45 @@ +require 'cases/helper' +require 'models/user' +require 'models/visitor' +require 'models/administrator' + +class SecurePasswordTest < ActiveModel::TestCase + + setup do + @user = User.new + end + + test "password must be present" do + assert !@user.valid? + assert_equal 1, @user.errors.size + end + + test "password must match confirmation" do + @user.password = "thiswillberight" + @user.password_confirmation = "wrong" + + assert !@user.valid? + + @user.password_confirmation = "thiswillberight" + + assert @user.valid? + end + + test "authenticate" do + @user.password = "secret" + + assert !@user.authenticate("wrong") + assert @user.authenticate("secret") + end + + test "visitor#password_digest should be protected against mass assignment" do + assert Visitor.active_authorizer.kind_of?(ActiveModel::MassAssignmentSecurity::BlackList) + assert Visitor.active_authorizer.include?(:password_digest) + end + + test "Administrator's mass_assignment_authorizer should be WhiteList" do + assert Administrator.active_authorizer.kind_of?(ActiveModel::MassAssignmentSecurity::WhiteList) + assert !Administrator.active_authorizer.include?(:password_digest) + assert Administrator.active_authorizer.include?(:name) + end +end diff --git a/activemodel/test/cases/serialization_test.rb b/activemodel/test/cases/serialization_test.rb new file mode 100644 index 0000000000..8cc1ccb1e7 --- /dev/null +++ b/activemodel/test/cases/serialization_test.rb @@ -0,0 +1,45 @@ +require "cases/helper" + +class SerializationTest < ActiveModel::TestCase + class User + include ActiveModel::Serialization + + attr_accessor :name, :email, :gender + + def attributes + @attributes ||= {'name' => 'nil', 'email' => 'nil', 'gender' => 'nil'} + end + + def foo + 'i_am_foo' + end + end + + setup do + @user = User.new + @user.name = 'David' + @user.email = 'david@example.com' + @user.gender = 'male' + end + + def test_method_serializable_hash_should_work + expected = {"name"=>"David", "gender"=>"male", "email"=>"david@example.com"} + assert_equal expected , @user.serializable_hash + end + + def test_method_serializable_hash_should_work_with_only_option + expected = {"name"=>"David"} + assert_equal expected , @user.serializable_hash(:only => [:name]) + end + + def test_method_serializable_hash_should_work_with_except_option + expected = {"gender"=>"male", "email"=>"david@example.com"} + assert_equal expected , @user.serializable_hash(:except => [:name]) + end + + def test_method_serializable_hash_should_work_with_methods_option + expected = {"name"=>"David", "gender"=>"male", :foo=>"i_am_foo", "email"=>"david@example.com"} + assert_equal expected , @user.serializable_hash(:methods => [:foo]) + end + +end diff --git a/activemodel/test/cases/serializeration/json_serialization_test.rb b/activemodel/test/cases/serializeration/json_serialization_test.rb index 1ac991a8f1..500a5c575f 100644 --- a/activemodel/test/cases/serializeration/json_serialization_test.rb +++ b/activemodel/test/cases/serializeration/json_serialization_test.rb @@ -1,10 +1,12 @@ require 'cases/helper' require 'models/contact' +require 'models/automobile' require 'active_support/core_ext/object/instance_variables' class Contact extend ActiveModel::Naming include ActiveModel::Serializers::JSON + include ActiveModel::Validations def attributes instance_values @@ -104,16 +106,43 @@ class JsonSerializationTest < ActiveModel::TestCase end test "should return OrderedHash for errors" do - car = Automobile.new - - # run the validation - car.valid? - + contact = Contact.new + contact.errors.add :name, "can't be blank" + contact.errors.add :name, "is too short (minimum is 2 characters)" + contact.errors.add :age, "must be 16 or over" + hash = ActiveSupport::OrderedHash.new - hash[:make] = "can't be blank" - hash[:model] = "is too short (minimum is 2 characters)" - assert_equal hash.to_json, car.errors.to_json + hash[:name] = ["can't be blank", "is too short (minimum is 2 characters)"] + hash[:age] = ["must be 16 or over"] + assert_equal hash.to_json, contact.errors.to_json + end + + test "serializable_hash should not modify options passed in argument" do + options = { :except => :name } + @contact.serializable_hash(options) + + assert_nil options[:only] + assert_equal :name, options[:except] + end + + test "as_json should return a hash" do + json = @contact.as_json + + assert_kind_of Hash, json + assert_kind_of Hash, json['contact'] + %w(name age created_at awesome preferences).each do |field| + assert_equal @contact.send(field), json['contact'][field] + end end - - + + test "custom as_json should be honored when generating json" do + def @contact.as_json(options); { :name => name, :created_at => created_at }; end + json = @contact.to_json + + assert_match %r{"name":"Konata Izumi"}, json + assert_match %r{"created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}}, json + assert_no_match %r{"awesome":}, json + assert_no_match %r{"preferences":}, json + end + end diff --git a/activemodel/test/cases/serializeration/xml_serialization_test.rb b/activemodel/test/cases/serializeration/xml_serialization_test.rb index ff786658b7..b6a2f88667 100644 --- a/activemodel/test/cases/serializeration/xml_serialization_test.rb +++ b/activemodel/test/cases/serializeration/xml_serialization_test.rb @@ -70,6 +70,13 @@ class XmlSerializationTest < ActiveModel::TestCase assert_match %r{<CreatedAt}, @xml end + test "should allow lower-camelized tags" do + @xml = @contact.to_xml :root => 'xml_contact', :camelize => :lower + assert_match %r{^<xmlContact>}, @xml + assert_match %r{</xmlContact>$}, @xml + assert_match %r{<createdAt}, @xml + end + test "should allow skipped types" do @xml = @contact.to_xml :skip_types => true assert_match %r{<age>25</age>}, @xml @@ -107,7 +114,7 @@ class XmlSerializationTest < ActiveModel::TestCase end test "should serialize yaml" do - assert_match %r{<preferences type=\"yaml\">--- !ruby/struct:Customer \nname: John\n</preferences>}, @contact.to_xml + assert_match %r{<preferences type=\"yaml\">--- !ruby/struct:Customer(\s*)\nname: John\n</preferences>}, @contact.to_xml end test "should call proc on object" do diff --git a/activemodel/test/cases/translation_test.rb b/activemodel/test/cases/translation_test.rb index e25d308ca1..1b1d972d5c 100644 --- a/activemodel/test/cases/translation_test.rb +++ b/activemodel/test/cases/translation_test.rb @@ -6,7 +6,7 @@ class ActiveModelI18nTests < ActiveModel::TestCase def setup I18n.backend = I18n::Backend::Simple.new end - + def test_translated_model_attributes I18n.backend.store_translations 'en', :activemodel => {:attributes => {:person => {:name => 'person name attribute'} } } assert_equal 'person name attribute', Person.human_attribute_name('name') @@ -16,7 +16,24 @@ class ActiveModelI18nTests < ActiveModel::TestCase I18n.backend.store_translations 'en', :attributes => { :name => 'name default attribute' } assert_equal 'name default attribute', Person.human_attribute_name('name') end - + + def test_translated_model_attributes_using_default_option + assert_equal 'name default attribute', Person.human_attribute_name('name', :default => "name default attribute") + end + + def test_translated_model_attributes_using_default_option_as_symbol + I18n.backend.store_translations 'en', :default_name => 'name default attribute' + assert_equal 'name default attribute', Person.human_attribute_name('name', :default => :default_name) + end + + def test_translated_model_attributes_falling_back_to_default + assert_equal 'Name', Person.human_attribute_name('name') + end + + def test_translated_model_attributes_using_default_option_as_symbol_and_falling_back_to_default + assert_equal 'Name', Person.human_attribute_name('name', :default => :default_name) + end + def test_translated_model_attributes_with_symbols I18n.backend.store_translations 'en', :activemodel => {:attributes => {:person => {:name => 'person name attribute'} } } assert_equal 'person name attribute', Person.human_attribute_name(:name) @@ -32,6 +49,13 @@ class ActiveModelI18nTests < ActiveModel::TestCase assert_equal 'person name attribute', Child.human_attribute_name('name') end + def test_translated_model_attributes_with_attribute_matching_namespaced_model_name + I18n.backend.store_translations 'en', :activemodel => {:attributes => {:person => {:gender => 'person gender'}, :"person/gender" => {:attribute => 'person gender attribute'}}} + + assert_equal 'person gender', Person.human_attribute_name('gender') + assert_equal 'person gender attribute', Person::Gender.human_attribute_name('attribute') + end + def test_translated_model_names I18n.backend.store_translations 'en', :activemodel => {:models => {:person => 'person model'} } assert_equal 'person model', Person.model_name.human @@ -46,5 +70,11 @@ class ActiveModelI18nTests < ActiveModel::TestCase I18n.backend.store_translations 'en', :activemodel => {:models => {:person => 'person model'} } assert_equal 'person model', Child.model_name.human end + + def test_human_does_not_modify_options + options = {:default => 'person model'} + Person.model_name.human(options) + assert_equal({:default => 'person model'}, options) + end end diff --git a/activemodel/test/cases/validations/inclusion_validation_test.rb b/activemodel/test/cases/validations/inclusion_validation_test.rb index 0716b4f087..62f2ec785d 100644 --- a/activemodel/test/cases/validations/inclusion_validation_test.rb +++ b/activemodel/test/cases/validations/inclusion_validation_test.rb @@ -10,6 +10,15 @@ class InclusionValidationTest < ActiveModel::TestCase Topic.reset_callbacks(:validate) end + def test_validates_inclusion_of_range + Topic.validates_inclusion_of( :title, :in => 'aaa'..'bbb' ) + assert Topic.new("title" => "bbc", "content" => "abc").invalid? + assert Topic.new("title" => "aa", "content" => "abc").invalid? + assert Topic.new("title" => "aaa", "content" => "abc").valid? + assert Topic.new("title" => "abc", "content" => "abc").valid? + assert Topic.new("title" => "bbb", "content" => "abc").valid? + end + def test_validates_inclusion_of Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ) ) diff --git a/activemodel/test/cases/validations/length_validation_test.rb b/activemodel/test/cases/validations/length_validation_test.rb index 1e6180a938..f02514639b 100644 --- a/activemodel/test/cases/validations/length_validation_test.rb +++ b/activemodel/test/cases/validations/length_validation_test.rb @@ -342,6 +342,17 @@ class LengthValidationTest < ActiveModel::TestCase assert_equal ["Your essay must be at least 5 words."], t.errors[:content] end + def test_validates_length_of_for_fixnum + Topic.validates_length_of(:approved, :is => 4) + + t = Topic.new("title" => "uhohuhoh", "content" => "whatever", :approved => 1) + assert t.invalid? + assert t.errors[:approved].any? + + t = Topic.new("title" => "uhohuhoh", "content" => "whatever", :approved => 1234) + assert t.valid? + end + def test_validates_length_of_for_ruby_class Person.validates_length_of :karma, :minimum => 5 diff --git a/activemodel/test/cases/validations/numericality_validation_test.rb b/activemodel/test/cases/validations/numericality_validation_test.rb index e1d7d40c47..08f6169ca5 100644 --- a/activemodel/test/cases/validations/numericality_validation_test.rb +++ b/activemodel/test/cases/validations/numericality_validation_test.rb @@ -14,7 +14,7 @@ class NumericalityValidationTest < ActiveModel::TestCase NIL = [nil] BLANK = ["", " ", " \t \r \n"] - BIGDECIMAL_STRINGS = %w(12345678901234567890.1234567890) # 30 significent digits + BIGDECIMAL_STRINGS = %w(12345678901234567890.1234567890) # 30 significant digits FLOAT_STRINGS = %w(0.0 +0.0 -0.0 10.0 10.5 -10.5 -0.0001 -090.1 90.1e1 -90.1e5 -90.1e-5 90e-5) INTEGER_STRINGS = %w(0 +0 -0 10 +10 -10 0090 -090) FLOATS = [0.0, 10.0, 10.5, -10.5, -0.0001] + FLOAT_STRINGS diff --git a/activemodel/test/cases/validations/validates_test.rb b/activemodel/test/cases/validations/validates_test.rb index b85e491a9c..779f6c8448 100644 --- a/activemodel/test/cases/validations/validates_test.rb +++ b/activemodel/test/cases/validations/validates_test.rb @@ -1,8 +1,10 @@ # encoding: utf-8 require 'cases/helper' require 'models/person' +require 'models/topic' require 'models/person_with_validator' require 'validators/email_validator' +require 'validators/namespace/email_validator' class ValidatesTest < ActiveModel::TestCase setup :reset_callbacks @@ -10,6 +12,7 @@ class ValidatesTest < ActiveModel::TestCase def reset_callbacks Person.reset_callbacks(:validate) + Topic.reset_callbacks(:validate) PersonWithValidator.reset_callbacks(:validate) end @@ -20,13 +23,24 @@ class ValidatesTest < ActiveModel::TestCase assert_equal ['is not a number'], person.errors[:title] end + def test_validates_with_attribute_specified_as_string + Person.validates "title", :numericality => true + person = Person.new + person.valid? + assert_equal ['is not a number'], person.errors[:title] + + person = Person.new + person.title = 123 + assert person.valid? + end + def test_validates_with_built_in_validation_and_options Person.validates :salary, :numericality => { :message => 'my custom message' } person = Person.new person.valid? assert_equal ['my custom message'], person.errors[:salary] end - + def test_validates_with_validator_class Person.validates :karma, :email => true person = Person.new @@ -34,6 +48,13 @@ class ValidatesTest < ActiveModel::TestCase assert_equal ['is not an email'], person.errors[:karma] end + def test_validates_with_namespaced_validator_class + Person.validates :karma, :'namespace/email' => true + person = Person.new + person.valid? + assert_equal ['is not an email'], person.errors[:karma] + end + def test_validates_with_if_as_local_conditions Person.validates :karma, :presence => true, :email => { :unless => :condition_is_true } person = Person.new @@ -93,22 +114,40 @@ class ValidatesTest < ActiveModel::TestCase person.valid? assert_equal ['my custom message'], person.errors[:karma] end - + def test_validates_with_unknown_validator assert_raise(ArgumentError) { Person.validates :karma, :unknown => true } end - + def test_validates_with_included_validator PersonWithValidator.validates :title, :presence => true person = PersonWithValidator.new person.valid? assert_equal ['Local validator'], person.errors[:title] end - + def test_validates_with_included_validator_and_options PersonWithValidator.validates :title, :presence => { :custom => ' please' } person = PersonWithValidator.new person.valid? assert_equal ['Local validator please'], person.errors[:title] end + + def test_validates_with_included_validator_and_wildcard_shortcut + # Shortcut for PersonWithValidator.validates :title, :like => { :with => "Mr." } + PersonWithValidator.validates :title, :like => "Mr." + person = PersonWithValidator.new + person.title = "Ms. Pacman" + person.valid? + assert_equal ['does not appear to be like Mr.'], person.errors[:title] + end + + def test_defining_extra_default_keys_for_validates + Topic.validates :title, :confirmation => true, :message => 'Y U NO CONFIRM' + topic = Topic.new + topic.title = "What's happening" + topic.title_confirmation = "Not this" + assert !topic.valid? + assert_equal ['Y U NO CONFIRM'], topic.errors[:title] + end end diff --git a/activemodel/test/cases/validations/with_validation_test.rb b/activemodel/test/cases/validations/with_validation_test.rb index 6d825cd316..07c1bd0533 100644 --- a/activemodel/test/cases/validations/with_validation_test.rb +++ b/activemodel/test/cases/validations/with_validation_test.rb @@ -171,4 +171,25 @@ class ValidatesWithTest < ActiveModel::TestCase assert topic.errors[:title].empty? assert topic.errors[:content].empty? end + + test "validates_with can validate with an instance method" do + Topic.validates :title, :with => :my_validation + + topic = Topic.new :title => "foo" + assert topic.valid? + assert topic.errors[:title].empty? + + topic = Topic.new + assert !topic.valid? + assert_equal ['is missing'], topic.errors[:title] + end + + test "optionally pass in the attribute being validated when validating with an instance method" do + Topic.validates :title, :content, :with => :my_validation_with_arg + + topic = Topic.new :title => "foo" + assert !topic.valid? + assert topic.errors[:title].empty? + assert_equal ['is missing'], topic.errors[:content] + end end diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb index 8d6bdeb6a5..2f36195627 100644 --- a/activemodel/test/cases/validations_test.rb +++ b/activemodel/test/cases/validations_test.rb @@ -25,9 +25,11 @@ class ValidationsTest < ActiveModel::TestCase r = Reply.new r.title = "There's no content!" assert r.invalid?, "A reply without content shouldn't be saveable" + assert r.after_validation_performed, "after_validation callback should be called" r.content = "Messa content!" assert r.valid?, "A reply with content should be saveable" + assert r.after_validation_performed, "after_validation callback should be called" end def test_single_attr_validation_and_error_msg @@ -146,6 +148,14 @@ class ValidationsTest < ActiveModel::TestCase end def test_validate_block + Topic.validate { errors.add("title", "will never be valid") } + t = Topic.new("title" => "Title", "content" => "whatever") + assert t.invalid? + assert t.errors[:title].any? + assert_equal ["will never be valid"], t.errors["title"] + end + + def test_validate_block_with_params Topic.validate { |topic| topic.errors.add("title", "will never be valid") } t = Topic.new("title" => "Title", "content" => "whatever") assert t.invalid? @@ -170,10 +180,10 @@ class ValidationsTest < ActiveModel::TestCase assert_match %r{<errors>}, xml assert_match %r{<error>Title can't be blank</error>}, xml assert_match %r{<error>Content can't be blank</error>}, xml - + hash = ActiveSupport::OrderedHash.new - hash[:title] = "can't be blank" - hash[:content] = "can't be blank" + hash[:title] = ["can't be blank"] + hash[:content] = ["can't be blank"] assert_equal t.errors.to_json, hash.to_json end @@ -185,7 +195,7 @@ class ValidationsTest < ActiveModel::TestCase assert t.invalid? assert_equal "can't be blank", t.errors["title"].first Topic.validates_presence_of :title, :author_name - Topic.validate {|topic| topic.errors.add('author_email_address', 'will never be valid')} + Topic.validate {errors.add('author_email_address', 'will never be valid')} Topic.validates_length_of :title, :content, :minimum => 2 t = Topic.new :title => '' @@ -213,42 +223,6 @@ class ValidationsTest < ActiveModel::TestCase assert !t.invalid? end - 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 - - 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 - def test_validation_with_message_as_proc Topic.validates_presence_of(:title, :message => proc { "no blanks here".upcase }) @@ -280,6 +254,24 @@ class ValidationsTest < ActiveModel::TestCase assert_equal 10, Topic.validators_on(:title).first.options[:minimum] end + def test_list_of_validators_on_multiple_attributes + Topic.validates :title, :length => { :minimum => 10 } + Topic.validates :author_name, :presence => true, :format => /a/ + + validators = Topic.validators_on(:title, :author_name) + + assert_equal [ + ActiveModel::Validations::FormatValidator, + ActiveModel::Validations::LengthValidator, + ActiveModel::Validations::PresenceValidator + ], validators.map { |v| v.class }.sort_by { |c| c.to_s } + end + + def test_list_of_validators_will_be_empty_when_empty + Topic.validates :title, :length => { :minimum => 10 } + assert_equal [], Topic.validators_on(:author_name) + end + def test_validations_on_the_instance_level auto = Automobile.new |