/activesupport/test/core_ext/object_and_class_ext_test.rb
Ruby | 275 lines | 225 code | 49 blank | 1 comment | 1 complexity | 6d23ddb686b476b0a0c2faaaeda3aed9 MD5 | raw file
- require 'abstract_unit'
- require 'active_support/core_ext/object'
- require 'active_support/core_ext/class/removal'
- require 'active_support/core/time'
- class ClassA; end
- class ClassB < ClassA; end
- class ClassC < ClassB; end
- class ClassD < ClassA; end
- class ClassI; end
- class ClassJ < ClassI; end
- class ClassK
- end
- module Nested
- class << self
- def on_const_missing(&callback)
- @on_const_missing = callback
- end
- private
- def const_missing(mod_id)
- @on_const_missing[mod_id] if @on_const_missing
- super
- end
- end
- class ClassL < ClassK
- end
- end
- module Bar
- def bar; end
- end
- module Baz
- def baz; end
- end
- class Foo
- include Bar
- end
- class ClassExtTest < Test::Unit::TestCase
- def test_methods
- assert defined?(ClassB)
- assert defined?(ClassC)
- assert defined?(ClassD)
- ClassA.remove_subclasses
- assert !defined?(ClassB)
- assert !defined?(ClassC)
- assert !defined?(ClassD)
- end
- def test_subclasses_of
- cj = ClassJ
- assert_equal [ClassJ], Object.subclasses_of(ClassI)
- ClassI.remove_subclasses
- assert_equal [], Object.subclasses_of(ClassI)
- ensure
- Object.const_set :ClassJ, cj
- end
- def test_subclasses_of_should_find_nested_classes
- assert Object.subclasses_of(ClassK).include?(Nested::ClassL)
- end
- def test_subclasses_of_should_not_return_removed_classes
- # First create the removed class
- old_class = Nested.class_eval { remove_const :ClassL }
- new_class = Class.new(ClassK)
- Nested.const_set :ClassL, new_class
- assert_equal "Nested::ClassL", new_class.name # Sanity check
- subclasses = Object.subclasses_of(ClassK)
- assert subclasses.include?(new_class)
- assert ! subclasses.include?(old_class)
- ensure
- Nested.const_set :ClassL, old_class unless defined?(Nested::ClassL)
- end
-
- def test_subclasses_of_should_not_trigger_const_missing
- const_missing = false
- Nested.on_const_missing { const_missing = true }
-
- subclasses = Object.subclasses_of ClassK
- assert !const_missing
- assert_equal [ Nested::ClassL ], subclasses
-
- removed = Nested.class_eval { remove_const :ClassL } # keep it in memory
- subclasses = Object.subclasses_of ClassK
- assert !const_missing
- assert subclasses.empty?
- ensure
- Nested.const_set :ClassL, removed unless defined?(Nested::ClassL)
- end
-
- def test_subclasses_of_with_multiple_roots
- classes = Object.subclasses_of(ClassI, ClassK)
- assert_equal %w(ClassJ Nested::ClassL), classes.collect(&:to_s).sort
- end
- def test_subclasses_of_doesnt_find_anonymous_classes
- assert_equal [], Object.subclasses_of(Foo)
- bar = Class.new(Foo)
- assert_nothing_raised do
- assert_equal [bar], Object.subclasses_of(Foo)
- end
- end
- end
- class ObjectTests < Test::Unit::TestCase
- def test_extended_by
- foo = Foo.new
- assert foo.extended_by.include?(Bar)
- foo.extend(Baz)
- assert(([Bar, Baz] - foo.extended_by).empty?, "Expected Bar, Baz in #{foo.extended_by.inspect}")
- end
- def test_extend_with_included_modules_from
- foo, object = Foo.new, Object.new
- assert !object.respond_to?(:bar)
- assert !object.respond_to?(:baz)
- object.extend_with_included_modules_from(foo)
- assert object.respond_to?(:bar)
- assert !object.respond_to?(:baz)
- foo.extend(Baz)
- object.extend_with_included_modules_from(foo)
- assert object.respond_to?(:bar)
- assert object.respond_to?(:baz)
- end
- class DuckTime
- def acts_like_time?
- true
- end
- end
- def test_duck_typing
- object = Object.new
- time = Time.now
- date = Date.today
- dt = DateTime.new
- duck = DuckTime.new
- assert !object.acts_like?(:time)
- assert !object.acts_like?(:date)
- assert time.acts_like?(:time)
- assert !time.acts_like?(:date)
- assert !date.acts_like?(:time)
- assert date.acts_like?(:date)
- assert dt.acts_like?(:time)
- assert dt.acts_like?(:date)
- assert duck.acts_like?(:time)
- assert !duck.acts_like?(:date)
- end
- def test_metaclass
- string = "Hello"
- string.metaclass.instance_eval do
- define_method(:foo) { "bar" }
- end
- assert_equal "bar", string.foo
- end
- end
- class ObjectInstanceVariableTest < Test::Unit::TestCase
- def setup
- @source, @dest = Object.new, Object.new
- @source.instance_variable_set(:@bar, 'bar')
- @source.instance_variable_set(:@baz, 'baz')
- end
- def test_instance_variable_names
- assert_equal %w(@bar @baz), @source.instance_variable_names.sort
- end
- def test_instance_variable_defined
- assert @source.instance_variable_defined?('@bar')
- assert @source.instance_variable_defined?(:@bar)
- assert !@source.instance_variable_defined?(:@foo)
- assert !@source.instance_variable_defined?('@foo')
- end
- def test_copy_instance_variables_from_without_explicit_excludes
- assert_equal [], @dest.instance_variables
- @dest.copy_instance_variables_from(@source)
- assert_equal %w(@bar @baz), @dest.instance_variables.sort.map(&:to_s)
- %w(@bar @baz).each do |name|
- assert_equal @source.instance_variable_get(name).object_id,
- @dest.instance_variable_get(name).object_id
- end
- end
- def test_copy_instance_variables_from_with_explicit_excludes
- @dest.copy_instance_variables_from(@source, ['@baz'])
- assert !@dest.instance_variable_defined?('@baz')
- assert_equal 'bar', @dest.instance_variable_get('@bar')
- end
- def test_copy_instance_variables_automatically_excludes_protected_instance_variables
- @source.instance_variable_set(:@quux, 'quux')
- class << @source
- def protected_instance_variables
- ['@bar', :@quux]
- end
- end
- @dest.copy_instance_variables_from(@source)
- assert !@dest.instance_variable_defined?('@bar')
- assert !@dest.instance_variable_defined?('@quux')
- assert_equal 'baz', @dest.instance_variable_get('@baz')
- end
- def test_instance_values
- object = Object.new
- object.instance_variable_set :@a, 1
- object.instance_variable_set :@b, 2
- assert_equal({'a' => 1, 'b' => 2}, object.instance_values)
- end
- def test_instance_exec_passes_arguments_to_block
- assert_equal %w(hello goodbye), 'hello'.instance_exec('goodbye') { |v| [self, v] }
- end
- def test_instance_exec_with_frozen_obj
- assert_equal %w(olleh goodbye), 'hello'.freeze.instance_exec('goodbye') { |v| [reverse, v] }
- end
- def test_instance_exec_nested
- assert_equal %w(goodbye olleh bar), 'hello'.instance_exec('goodbye') { |arg|
- [arg] + instance_exec('bar') { |v| [reverse, v] } }
- end
- end
- class ObjectTryTest < Test::Unit::TestCase
- def setup
- @string = "Hello"
- end
- def test_nonexisting_method
- method = :undefined_method
- assert !@string.respond_to?(method)
- assert_raise(NoMethodError) { @string.try(method) }
- end
-
- def test_valid_method
- assert_equal 5, @string.try(:size)
- end
- def test_argument_forwarding
- assert_equal 'Hey', @string.try(:sub, 'llo', 'y')
- end
- def test_block_forwarding
- assert_equal 'Hey', @string.try(:sub, 'llo') { |match| 'y' }
- end
- def test_nil_to_type
- assert_nil nil.try(:to_s)
- assert_nil nil.try(:to_i)
- end
- def test_false_try
- assert_equal 'false', false.try(:to_s)
- end
- end