diff options
Diffstat (limited to 'spec/rubyspec/core/module/prepend_spec.rb')
-rw-r--r-- | spec/rubyspec/core/module/prepend_spec.rb | 361 |
1 files changed, 0 insertions, 361 deletions
diff --git a/spec/rubyspec/core/module/prepend_spec.rb b/spec/rubyspec/core/module/prepend_spec.rb deleted file mode 100644 index c0cce616a2..0000000000 --- a/spec/rubyspec/core/module/prepend_spec.rb +++ /dev/null @@ -1,361 +0,0 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) - -describe "Module#prepend" do - it "is a public method" do - Module.should have_public_instance_method(:prepend, false) - end - - it "does not affect the superclass" do - Class.new { prepend Module.new }.superclass.should == Object - end - - it "calls #prepend_features(self) in reversed order on each module" do - ScratchPad.record [] - - m = Module.new do - def self.prepend_features(mod) - ScratchPad << [ self, mod ] - end - end - - m2 = Module.new do - def self.prepend_features(mod) - ScratchPad << [ self, mod ] - end - end - - m3 = Module.new do - def self.prepend_features(mod) - ScratchPad << [ self, mod ] - end - end - - c = Class.new { prepend(m, m2, m3) } - - ScratchPad.recorded.should == [ [ m3, c], [ m2, c ], [ m, c ] ] - end - - it "raises a TypeError when the argument is not a Module" do - lambda { ModuleSpecs::Basic.prepend(Class.new) }.should raise_error(TypeError) - end - - it "does not raise a TypeError when the argument is an instance of a subclass of Module" do - lambda { ModuleSpecs::SubclassSpec.prepend(ModuleSpecs::Subclass.new) }.should_not raise_error(TypeError) - end - - it "imports constants" do - m1 = Module.new - m1::MY_CONSTANT = 1 - m2 = Module.new { prepend(m1) } - m2.constants.should include(:MY_CONSTANT) - end - - it "imports instance methods" do - Module.new { prepend ModuleSpecs::A }.instance_methods.should include(:ma) - end - - it "does not import methods to modules and classes" do - Module.new { prepend ModuleSpecs::A }.methods.should_not include(:ma) - end - - it "allows wrapping methods" do - m = Module.new { def calc(x) super + 3 end } - c = Class.new { def calc(x) x*2 end } - c.prepend(m) - c.new.calc(1).should == 5 - end - - it "also prepends included modules" do - a = Module.new { def calc(x) x end } - b = Module.new { include a } - c = Class.new { prepend b } - c.new.calc(1).should == 1 - end - - it "prepends multiple modules in the right order" do - m1 = Module.new { def chain; super << :m1; end } - m2 = Module.new { def chain; super << :m2; end; prepend(m1) } - c = Class.new { def chain; [:c]; end; prepend(m2) } - c.new.chain.should == [:c, :m2, :m1] - end - - it "includes prepended modules in ancestors" do - m = Module.new - Class.new { prepend(m) }.ancestors.should include(m) - end - - it "reports the prepended module as the method owner" do - m = Module.new { def meth; end } - c = Class.new { def meth; end; prepend(m) } - c.new.method(:meth).owner.should == m - end - - it "reports the prepended module as the unbound method owner" do - m = Module.new { def meth; end } - c = Class.new { def meth; end; prepend(m) } - c.instance_method(:meth).owner.should == m - c.public_instance_method(:meth).owner.should == m - end - - it "causes the prepended module's method to be aliased by alias_method" do - m = Module.new { def meth; :m end } - c = Class.new { def meth; :c end; prepend(m); alias_method :alias, :meth } - c.new.alias.should == :m - end - - it "sees an instance of a prepended class as kind of the prepended module" do - m = Module.new - c = Class.new { prepend(m) } - c.new.should be_kind_of(m) - end - - it "keeps the module in the chain when dupping the class" do - m = Module.new - c = Class.new { prepend(m) } - c.dup.new.should be_kind_of(m) - end - - it "keeps the module in the chain when dupping an intermediate module" do - m1 = Module.new { def calc(x) x end } - m2 = Module.new { prepend(m1) } - c1 = Class.new { prepend(m2) } - m2dup = m2.dup - m2dup.ancestors.should == [m2dup,m1,m2] - c2 = Class.new { prepend(m2dup) } - c1.ancestors[0,3].should == [m1,m2,c1] - c1.new.should be_kind_of(m1) - c2.ancestors[0,4].should == [m2dup,m1,m2,c2] - c2.new.should be_kind_of(m1) - end - - it "depends on prepend_features to add the module" do - m = Module.new { def self.prepend_features(mod) end } - Class.new { prepend(m) }.ancestors.should_not include(m) - end - - it "adds the module in the subclass chains" do - parent = Class.new { def chain; [:parent]; end } - child = Class.new(parent) { def chain; super << :child; end } - mod = Module.new { def chain; super << :mod; end } - parent.prepend(mod) - parent.ancestors[0,2].should == [mod, parent] - child.ancestors[0,3].should == [child, mod, parent] - - parent.new.chain.should == [:parent, :mod] - child.new.chain.should == [:parent, :mod, :child] - end - - it "inserts a later prepended module into the chain" do - m1 = Module.new { def chain; super << :m1; end } - m2 = Module.new { def chain; super << :m2; end } - c1 = Class.new { def chain; [:c1]; end; prepend m1 } - c2 = Class.new(c1) { def chain; super << :c2; end } - c2.new.chain.should == [:c1, :m1, :c2] - c1.prepend(m2) - c2.new.chain.should == [:c1, :m1, :m2, :c2] - end - - it "works with subclasses" do - m = Module.new do - def chain - super << :module - end - end - - c = Class.new do - prepend m - def chain - [:class] - end - end - - s = Class.new(c) do - def chain - super << :subclass - end - end - - s.new.chain.should == [:class, :module, :subclass] - end - - it "throws a NoMethodError when there is no more superclass" do - m = Module.new do - def chain - super << :module - end - end - - c = Class.new do - prepend m - def chain - super << :class - end - end - lambda { c.new.chain }.should raise_error(NoMethodError) - end - - it "calls prepended after prepend_features" do - ScratchPad.record [] - - m = Module.new do - def self.prepend_features(klass) - ScratchPad << [:prepend_features, klass] - end - def self.prepended(klass) - ScratchPad << [:prepended, klass] - end - end - - c = Class.new { prepend(m) } - ScratchPad.recorded.should == [[:prepend_features, c], [:prepended, c]] - end - - it "detects cyclic prepends" do - lambda { - module ModuleSpecs::P - prepend ModuleSpecs::P - end - }.should raise_error(ArgumentError) - end - - ruby_version_is ''...'2.4' do - it "accepts no-arguments" do - lambda { - Module.new do - prepend - end - }.should_not raise_error - end - end - - ruby_version_is '2.4' do - it "doesn't accept no-arguments" do - lambda { - Module.new do - prepend - end - }.should raise_error(ArgumentError) - end - end - - it "returns the class it's included into" do - m = Module.new - r = nil - c = Class.new { r = prepend m } - r.should == c - end - - it "clears any caches" do - module ModuleSpecs::M3 - module PM1 - def foo - :m1 - end - end - - module PM2 - def foo - :m2 - end - end - - klass = Class.new do - prepend PM1 - - def get - foo - end - end - - o = klass.new - o.get.should == :m1 - - klass.class_eval do - prepend PM2 - end - - o.get.should == :m2 - end - end - - it "supports super when the module is prepended into a singleton class" do - ScratchPad.record [] - - mod = Module.new do - def self.inherited(base) - super - end - end - - module_with_singleton_class_prepend = Module.new do - singleton_class.prepend(mod) - end - - klass = Class.new(ModuleSpecs::RecordIncludedModules) do - include module_with_singleton_class_prepend - end - - ScratchPad.recorded.should == klass - end - - it "supports super when the module is prepended into a singleton class with a class super" do - ScratchPad.record [] - - base_class = Class.new(ModuleSpecs::RecordIncludedModules) do - def self.inherited(base) - super - end - end - - prepended_module = Module.new - base_class.singleton_class.prepend(prepended_module) - - child_class = Class.new(base_class) - ScratchPad.recorded.should == child_class - end - - it "does not interfere with a define_method super in the original class" do - base_class = Class.new do - def foo(ary) - ary << 1 - end - end - - child_class = Class.new(base_class) do - define_method :foo do |ary| - ary << 2 - super(ary) - end - end - - prep_mod = Module.new do - def foo(ary) - ary << 3 - super(ary) - end - end - - child_class.prepend(prep_mod) - - ary = [] - child_class.new.foo(ary) - ary.should == [3, 2, 1] - end - - describe "called on a module" do - describe "included into a class" - it "does not obscure the module's methods from reflective access" do - mod = Module.new do - def foo; end - end - cls = Class.new do - include mod - end - pre = Module.new - mod.prepend pre - - cls.instance_methods.should include(:foo) - end - end -end |