summaryrefslogtreecommitdiff
path: root/spec/ruby/core/module/include_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/module/include_spec.rb')
-rw-r--r--spec/ruby/core/module/include_spec.rb432
1 files changed, 395 insertions, 37 deletions
diff --git a/spec/ruby/core/module/include_spec.rb b/spec/ruby/core/module/include_spec.rb
index 2a31afa59a..b6201550e4 100644
--- a/spec/ruby/core/module/include_spec.rb
+++ b/spec/ruby/core/module/include_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "Module#include" do
it "is a public method" do
- Module.should have_public_instance_method(:include, false)
+ Module.public_instance_methods(false).should.include?(:include)
end
it "calls #append_features(self) in reversed order on each module" do
@@ -33,24 +33,40 @@ describe "Module#include" do
end
it "adds all ancestor modules when a previously included module is included again" do
- ModuleSpecs::MultipleIncludes.ancestors.should include(ModuleSpecs::MA, ModuleSpecs::MB)
+ ModuleSpecs::MultipleIncludes.ancestors.to_set.should >= Set[ModuleSpecs::MA, ModuleSpecs::MB]
ModuleSpecs::MB.include(ModuleSpecs::MC)
ModuleSpecs::MultipleIncludes.include(ModuleSpecs::MB)
- ModuleSpecs::MultipleIncludes.ancestors.should include(ModuleSpecs::MA, ModuleSpecs::MB, ModuleSpecs::MC)
+ ModuleSpecs::MultipleIncludes.ancestors.to_set.should >= Set[ModuleSpecs::MA, ModuleSpecs::MB, ModuleSpecs::MC]
end
it "raises a TypeError when the argument is not a Module" do
- lambda { ModuleSpecs::Basic.include(Class.new) }.should raise_error(TypeError)
+ -> { ModuleSpecs::Basic.include(Class.new) }.should.raise(TypeError)
end
it "does not raise a TypeError when the argument is an instance of a subclass of Module" do
- lambda { ModuleSpecs::SubclassSpec.include(ModuleSpecs::Subclass.new) }.should_not raise_error(TypeError)
+ class ModuleSpecs::SubclassSpec::AClass
+ end
+ -> { ModuleSpecs::SubclassSpec::AClass.include(ModuleSpecs::Subclass.new) }.should_not.raise(TypeError)
+ ensure
+ ModuleSpecs::SubclassSpec.send(:remove_const, :AClass)
+ end
+
+ it "raises a TypeError when the argument is a refinement" do
+ refinement = nil
+
+ Module.new do
+ refine String do
+ refinement = self
+ end
+ end
+
+ -> { ModuleSpecs::Basic.include(refinement) }.should.raise(TypeError, "Cannot include refinement")
end
it "imports constants to modules and classes" do
- ModuleSpecs::A.constants.should include(:CONSTANT_A)
- ModuleSpecs::B.constants.should include(:CONSTANT_A, :CONSTANT_B)
- ModuleSpecs::C.constants.should include(:CONSTANT_A, :CONSTANT_B)
+ ModuleSpecs::A.constants.should.include?(:CONSTANT_A)
+ ModuleSpecs::B.constants.to_set.should >= Set[:CONSTANT_A, :CONSTANT_B]
+ ModuleSpecs::C.constants.to_set.should >= Set[:CONSTANT_A, :CONSTANT_B]
end
it "shadows constants from ancestors" do
@@ -68,9 +84,9 @@ describe "Module#include" do
end
it "imports instance methods to modules and classes" do
- ModuleSpecs::A.instance_methods.should include(:ma)
- ModuleSpecs::B.instance_methods.should include(:ma,:mb)
- ModuleSpecs::C.instance_methods.should include(:ma,:mb)
+ ModuleSpecs::A.instance_methods.should.include?(:ma)
+ ModuleSpecs::B.instance_methods.to_set.should >= Set[:ma,:mb]
+ ModuleSpecs::C.instance_methods.to_set.should >= Set[:ma,:mb]
end
it "does not import methods to modules and classes" do
@@ -104,9 +120,9 @@ describe "Module#include" do
class A; include M; end
class B < A; include M; end
- all = [A,B,M]
+ all = [A, B, M]
- (B.ancestors & all).should == [B, A, M]
+ (B.ancestors.filter { |a| all.include?(a) }).should == [B, A, M]
end
end
@@ -130,7 +146,7 @@ describe "Module#include" do
anc = B.ancestors
[B, U, V, W, A, X].each do |i|
- anc.include?(i).should be_true
+ anc.include?(i).should == true
end
class B; include V; end
@@ -138,7 +154,7 @@ describe "Module#include" do
# the only new module is Y, it is added after U since it follows U in V mixin list:
anc = B.ancestors
[B, U, Y, V, W, A, X].each do |i|
- anc.include?(i).should be_true
+ anc.include?(i).should == true
end
end
end
@@ -158,31 +174,19 @@ describe "Module#include" do
end
it "detects cyclic includes" do
- lambda {
+ -> {
module ModuleSpecs::M
include ModuleSpecs::M
end
- }.should raise_error(ArgumentError)
- end
-
- ruby_version_is ''...'2.4' do
- it "accepts no-arguments" do
- lambda {
- Module.new do
- include
- end
- }.should_not raise_error
- end
+ }.should.raise(ArgumentError)
end
- ruby_version_is '2.4' do
- it "doesn't accept no-arguments" do
- lambda {
- Module.new do
- include
- end
- }.should raise_error(ArgumentError)
- end
+ it "doesn't accept no-arguments" do
+ -> {
+ Module.new do
+ include
+ end
+ }.should.raise(ArgumentError)
end
it "returns the class it's included into" do
@@ -246,6 +250,360 @@ describe "Module#include" do
remove_const :C
end
end
+
+ it "updates the method when an included module is updated" do
+ a_class = Class.new do
+ def foo
+ 'a'
+ end
+ end
+
+ m_module = Module.new
+
+ b_class = Class.new(a_class) do
+ include m_module
+ end
+
+ b = b_class.new
+
+ foo = -> { b.foo }
+
+ foo.call.should == 'a'
+
+ m_module.module_eval do
+ def foo
+ 'm'
+ end
+ end
+
+ foo.call.should == 'm'
+ end
+
+
+ it "updates the method when a module included after a call is later updated" do
+ m_module = Module.new
+ a_class = Class.new do
+ def foo
+ 'a'
+ end
+ end
+ b_class = Class.new(a_class)
+ b = b_class.new
+ foo = -> { b.foo }
+ foo.call.should == 'a'
+
+ b_class.include m_module
+ foo.call.should == 'a'
+
+ m_module.module_eval do
+ def foo
+ "m"
+ end
+ end
+ foo.call.should == 'm'
+ end
+
+ it "updates the method when a nested included module is updated" do
+ a_class = Class.new do
+ def foo
+ 'a'
+ end
+ end
+
+ n_module = Module.new
+
+ m_module = Module.new do
+ include n_module
+ end
+
+ b_class = Class.new(a_class) do
+ include m_module
+ end
+
+ b = b_class.new
+
+ foo = -> { b.foo }
+
+ foo.call.should == 'a'
+
+ n_module.module_eval do
+ def foo
+ 'n'
+ end
+ end
+
+ foo.call.should == 'n'
+ end
+
+ it "updates the method when a new module is included" do
+ a_class = Class.new do
+ def foo
+ 'a'
+ end
+ end
+
+ m_module = Module.new do
+ def foo
+ 'm'
+ end
+ end
+
+ b_class = Class.new(a_class)
+ b = b_class.new
+
+ foo = -> { b.foo }
+
+ foo.call.should == 'a'
+
+ b_class.class_eval do
+ include m_module
+ end
+
+ foo.call.should == 'm'
+ end
+
+ it "updates the method when a new module with nested module is included" do
+ a_class = Class.new do
+ def foo
+ 'a'
+ end
+ end
+
+ n_module = Module.new do
+ def foo
+ 'n'
+ end
+ end
+
+ m_module = Module.new do
+ include n_module
+ end
+
+ b_class = Class.new(a_class)
+ b = b_class.new
+
+ foo = -> { b.foo }
+
+ foo.call.should == 'a'
+
+ b_class.class_eval do
+ include m_module
+ end
+
+ foo.call.should == 'n'
+ end
+
+ it "updates the constant when an included module is updated" do
+ module ModuleSpecs::ConstUpdated
+ module A
+ FOO = 'a'
+ end
+
+ module M
+ end
+
+ module B
+ include A
+ include M
+ def self.foo
+ FOO
+ end
+ end
+
+ B.foo.should == 'a'
+
+ M.const_set(:FOO, 'm')
+ B.foo.should == 'm'
+ end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdated)
+ end
+
+ it "updates the constant when a module included after a call is later updated" do
+ module ModuleSpecs::ConstLaterUpdated
+ module A
+ FOO = 'a'
+ end
+
+ module B
+ include A
+ def self.foo
+ FOO
+ end
+ end
+
+ B.foo.should == 'a'
+
+ module M
+ end
+ B.include M
+
+ B.foo.should == 'a'
+
+ M.const_set(:FOO, 'm')
+ B.foo.should == 'm'
+ end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstLaterUpdated)
+ end
+
+ it "updates the constant when a module included in another module after a call is later updated" do
+ module ModuleSpecs::ConstModuleLaterUpdated
+ module A
+ FOO = 'a'
+ end
+
+ module B
+ include A
+ def self.foo
+ FOO
+ end
+ end
+
+ B.foo.should == 'a'
+
+ module M
+ end
+ B.include M
+
+ B.foo.should == 'a'
+
+ M.const_set(:FOO, 'm')
+ B.foo.should == 'm'
+ end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstModuleLaterUpdated)
+ end
+
+ it "updates the constant when a nested included module is updated" do
+ module ModuleSpecs::ConstUpdatedNestedIncludeUpdated
+ module A
+ FOO = 'a'
+ end
+
+ module N
+ end
+
+ module M
+ include N
+ end
+
+ module B
+ include A
+ include M
+ def self.foo
+ FOO
+ end
+ end
+
+ B.foo.should == 'a'
+
+ N.const_set(:FOO, 'n')
+ B.foo.should == 'n'
+ end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedNestedIncludeUpdated)
+ end
+
+ it "updates the constant when a new module is included" do
+ module ModuleSpecs::ConstUpdatedNewInclude
+ module A
+ FOO = 'a'
+ end
+
+ module M
+ FOO = 'm'
+ end
+
+ module B
+ include A
+ def self.foo
+ FOO
+ end
+ end
+
+ B.foo.should == 'a'
+
+ B.include(M)
+ B.foo.should == 'm'
+ end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedNewInclude)
+ end
+
+ it "updates the constant when a new module with nested module is included" do
+ module ModuleSpecs::ConstUpdatedNestedIncluded
+ module A
+ FOO = 'a'
+ end
+
+ module N
+ FOO = 'n'
+ end
+
+ module M
+ include N
+ end
+
+ module B
+ include A
+ def self.foo
+ FOO
+ end
+ end
+
+ B.foo.should == 'a'
+
+ B.include M
+ B.foo.should == 'n'
+ end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedNestedIncluded)
+ end
+
+ it "overrides a previous super method call" do
+ c1 = Class.new do
+ def foo
+ [:c1]
+ end
+ end
+ c2 = Class.new(c1) do
+ def foo
+ [:c2] + super
+ end
+ end
+ c2.new.foo.should == [:c2, :c1]
+ m = Module.new do
+ def foo
+ [:m1]
+ end
+ end
+ c2.include(m)
+ c2.new.foo.should == [:c2, :m1]
+ end
+
+ it "update a module when a nested module is updated and includes a module on its own" do
+ m1 = Module.new
+ m2 = Module.new do
+ def m2; [:m2]; end
+ end
+ m3 = Module.new do
+ def m3; [:m3]; end
+ end
+ m4 = Module.new do
+ def m4; [:m4]; end
+ end
+ c = Class.new
+
+ c.include(m1)
+ m1.include(m2)
+ m2.include(m3)
+ m3.include(m4)
+
+ c.new.m2.should == [:m2]
+ c.new.m3.should == [:m3]
+ c.new.m4.should == [:m4]
+ end
end
describe "Module#include?" do
@@ -264,7 +622,7 @@ describe "Module#include?" do
end
it "raises a TypeError when no module was given" do
- lambda { ModuleSpecs::Child.include?("Test") }.should raise_error(TypeError)
- lambda { ModuleSpecs::Child.include?(ModuleSpecs::Parent) }.should raise_error(TypeError)
+ -> { ModuleSpecs::Child.include?("Test") }.should.raise(TypeError)
+ -> { ModuleSpecs::Child.include?(ModuleSpecs::Parent) }.should.raise(TypeError)
end
end