Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

add specs for Module#prepend #141

Closed
wants to merge 2 commits into from

4 participants

@rkh

No description provided.

@rkh

Most of this is copied over from the include specs and adjusted accordingly.

@brixen
Owner

Could you use ScratchPad instead of the global variable accumulator for tracking side effects?

@nobu

bad test.
Actually, prepend imports constants.

@rkh

@nobu It does? The tests all passed for me at r36240.

@brixen Will do, just copied over what the include tests do.

@rkh

Using ScratchPad now. All tests pass for me on r36257. @nobu is the current behavior concerning constants is a bug? Should I just remove that test for now?

@saturnflyer saturnflyer referenced this pull request from a commit in saturnflyer/rubyspec
@dbussink dbussink Add specs for Module#prepend
Based on the Rubyspec pull request submitted by rkh:

rubyspec#141

This fixes a typo and adds a few additional specs for behavior that
should be verified.
4fcaba7
@henrikhodne henrikhodne referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
@YorickPeterse

Closing this as current RubySpec already covers these specs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 27, 2012
  1. @rkh

    add specs for Module#prepend

    rkh authored
Commits on Jun 30, 2012
  1. @rkh

    use ScratchPad

    rkh authored
This page is out of date. Refresh to see the latest.
View
3  core/module/fixtures/classes.rb
@@ -365,6 +365,9 @@ module CyclicAppendB
include CyclicAppendA
end
+ module CyclicPrepend
+ end
+
module ExtendObject
C = :test
def test_method
View
28 core/module/prepend_features_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+ruby_version_is "2.0" do
+ describe "Module#append_features" do
+ it "gets called when self is included in another module/class" do
+ ScratchPad.record []
+
+ m = Module.new do
+ def self.prepend_features(mod)
+ ScratchPad << mod
+ end
+ end
+
+ c = Class.new do
+ prepend m
+ end
+
+ ScratchPad.recorded.should == [c]
+ end
+
+ it "raises an ArgumentError on a cyclic prepend" do
+ lambda {
+ ModuleSpecs::CyclicPrepend.send(:prepend_features, ModuleSpecs::CyclicPrepend)
+ }.should raise_error(ArgumentError)
+ end
+ end
+end
View
173 core/module/prepend_spec.rb
@@ -0,0 +1,173 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+ruby_version_is "2.0" do
+ describe "Module#prepend" do
+ 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.send(: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.send(:prepend, ModuleSpecs::Subclass.new) }.should_not raise_error(TypeError)
+ end
+
+ it "does not import constants" do
+ m1 = Module.new { A = 1 }
+ m2 = Module.new { prepend(m1) }
+ m1.constants.should_not include(:A)
+ 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.send(: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 "includes prepended modules in ancestors" do
+ m = Module.new
+ Class.new { prepend(m) }.ancestors.should include(m)
+ 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 "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 "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
+
+ it "accepts no-arguments" do
+ lambda {
+ Module.new do
+ prepend
+ end
+ }.should_not raise_error
+ 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
+
+ class PC
+ prepend PM1
+
+ def get
+ foo
+ end
+ end
+
+ c = PC.new
+ c.get.should == :m1
+
+ class PC
+ prepend PM2
+ end
+
+ c.get.should == :m2
+ end
+ end
+ end
+end
Something went wrong with that request. Please try again.