summaryrefslogtreecommitdiff
path: root/spec/ruby/core/module/refine_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/module/refine_spec.rb')
-rw-r--r--spec/ruby/core/module/refine_spec.rb469
1 files changed, 200 insertions, 269 deletions
diff --git a/spec/ruby/core/module/refine_spec.rb b/spec/ruby/core/module/refine_spec.rb
index 66c19ddb66..d0fc7015f8 100644
--- a/spec/ruby/core/module/refine_spec.rb
+++ b/spec/ruby/core/module/refine_spec.rb
@@ -11,7 +11,7 @@ describe "Module#refine" do
end
mod.should_not == inner_self
- inner_self.should be_kind_of(Module)
+ inner_self.should.is_a?(Module)
inner_self.name.should == nil
end
@@ -43,7 +43,7 @@ describe "Module#refine" do
end
end
- inner_self.public_instance_methods.should include(:blah)
+ inner_self.public_instance_methods.should.include?(:blah)
end
it "returns created anonymous module" do
@@ -63,7 +63,7 @@ describe "Module#refine" do
Module.new do
refine {}
end
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "raises TypeError if not passed a class" do
@@ -71,7 +71,7 @@ describe "Module#refine" do
Module.new do
refine("foo") {}
end
- end.should raise_error(TypeError)
+ end.should.raise(TypeError, "wrong argument type String (expected Class or Module)")
end
it "accepts a module as argument" do
@@ -84,7 +84,32 @@ describe "Module#refine" do
end
end
- inner_self.public_instance_methods.should include(:blah)
+ inner_self.public_instance_methods.should.include?(:blah)
+ end
+
+ it "applies refinements to the module" do
+ refinement = Module.new do
+ refine(Enumerable) do
+ def foo?
+ self.any? ? "yes" : "no"
+ end
+ end
+ end
+
+ foo = Class.new do
+ using refinement
+
+ def initialize(items)
+ @items = items
+ end
+
+ def result
+ @items.foo?
+ end
+ end
+
+ foo.new([]).result.should == "no"
+ foo.new([1]).result.should == "yes"
end
it "raises ArgumentError if not given a block" do
@@ -92,7 +117,7 @@ describe "Module#refine" do
Module.new do
refine String
end
- end.should raise_error(ArgumentError)
+ end.should.raise(ArgumentError)
end
it "applies refinements to calls in the refine block" do
@@ -111,7 +136,7 @@ describe "Module#refine" do
refine(String) {def foo; "foo"; end}
-> {
"hello".foo
- }.should raise_error(NoMethodError)
+ }.should.raise(NoMethodError)
end
end
@@ -120,7 +145,7 @@ describe "Module#refine" do
refine(String) {def foo; 'foo'; end}
end
- -> {"hello".foo}.should raise_error(NoMethodError)
+ -> {"hello".foo}.should.raise(NoMethodError)
end
# When defining multiple refinements in the same module,
@@ -184,7 +209,7 @@ describe "Module#refine" do
[1, 2].to_json_format
end
- }.should raise_error(NoMethodError)
+ }.should.raise(NoMethodError)
end
# method lookup:
@@ -196,8 +221,10 @@ describe "Module#refine" do
# * The included modules of C
describe "method lookup" do
it "looks in the object singleton class first" do
+ refined_class = ModuleSpecs.build_refined_class
+
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo; "foo from refinement"; end
end
end
@@ -206,7 +233,7 @@ describe "Module#refine" do
Module.new do
using refinement
- obj = ModuleSpecs::ClassWithFoo.new
+ obj = refined_class.new
class << obj
def foo; "foo from singleton class"; end
end
@@ -216,68 +243,48 @@ describe "Module#refine" do
result.should == "foo from singleton class"
end
- it "looks in prepended modules from the refinement first" do
- refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
- include ModuleSpecs::IncludedModule
- prepend ModuleSpecs::PrependedModule
-
- def foo; "foo from refinement"; end
+ it "looks in later included modules of the refined module first" do
+ a = Module.new do
+ def foo
+ "foo from A"
end
end
- result = nil
- Module.new do
- using refinement
- result = ModuleSpecs::ClassWithFoo.new.foo
- end
-
- result.should == "foo from prepended module"
- end
-
- it "looks in refinement then" do
- refinement = Module.new do
- refine(ModuleSpecs::ClassWithFoo) do
- include ModuleSpecs::IncludedModule
-
- def foo; "foo from refinement"; end
+ include_me_later = Module.new do
+ def foo
+ "foo from IncludeMeLater"
end
end
- result = nil
- Module.new do
- using refinement
- result = ModuleSpecs::ClassWithFoo.new.foo
+ c = Class.new do
+ include a
end
- result.should == "foo from refinement"
- end
-
- it "looks in included modules from the refinement then" do
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
- include ModuleSpecs::IncludedModule
- end
- end
+ refine c do; end
+ end
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.foo
+ c.include include_me_later
+ result = c.new.foo
end
- result.should == "foo from included module"
+ result.should == "foo from IncludeMeLater"
end
it "looks in the class then" do
+ refined_class = ModuleSpecs.build_refined_class
+
refinement = Module.new do
- refine(ModuleSpecs::ClassWithFoo) { }
+ refine(refined_class) { }
end
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.foo
+ result = refined_class.new.foo
end
result.should == "foo"
@@ -287,12 +294,14 @@ describe "Module#refine" do
# methods in a subclass have priority over refinements in a superclass
it "does not override methods in subclasses" do
- subclass = Class.new(ModuleSpecs::ClassWithFoo) do
+ refined_class = ModuleSpecs.build_refined_class
+
+ subclass = Class.new(refined_class) do
def foo; "foo from subclass"; end
end
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo; "foo from refinement"; end
end
end
@@ -308,8 +317,10 @@ describe "Module#refine" do
context "for methods accessed indirectly" do
it "is honored by Kernel#send" do
+ refined_class = ModuleSpecs.build_refined_class
+
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo; "foo from refinement"; end
end
end
@@ -317,15 +328,17 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.send :foo
+ result = refined_class.new.send :foo
end
result.should == "foo from refinement"
end
it "is honored by BasicObject#__send__" do
+ refined_class = ModuleSpecs.build_refined_class
+
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo; "foo from refinement"; end
end
end
@@ -333,7 +346,7 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.__send__ :foo
+ result = refined_class.new.__send__ :foo
end
result.should == "foo from refinement"
@@ -357,80 +370,40 @@ describe "Module#refine" do
result.should == ["(1)", "(2)", "(3)"]
end
- ruby_version_is "" ... "2.6" do
- it "is not honored by Kernel#public_send" do
- refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
- def foo; "foo from refinement"; end
- end
- end
+ it "is honored by Kernel#public_send" do
+ refined_class = ModuleSpecs.build_refined_class
- result = nil
- Module.new do
- using refinement
- result = ModuleSpecs::ClassWithFoo.new.public_send :foo
+ refinement = Module.new do
+ refine refined_class do
+ def foo; "foo from refinement"; end
end
-
- result.should == "foo"
end
- end
- ruby_version_is "2.6" do
- it "is honored by Kernel#public_send" do
- refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
- def foo; "foo from refinement"; end
- end
- end
-
- result = nil
- Module.new do
- using refinement
- result = ModuleSpecs::ClassWithFoo.new.public_send :foo
- end
-
- result.should == "foo from refinement"
+ result = nil
+ Module.new do
+ using refinement
+ result = refined_class.new.public_send :foo
end
- end
-
- ruby_version_is "" ... "2.5" do
- it "is not honored by string interpolation" do
- refinement = Module.new do
- refine Integer do
- def to_s
- "foo"
- end
- end
- end
- result = nil
- Module.new do
- using refinement
- result = "#{1}"
- end
-
- result.should == "1"
- end
+ result.should == "foo from refinement"
end
- ruby_version_is "2.5" do
- it "is honored by string interpolation" do
- refinement = Module.new do
- refine Integer do
- def to_s
- "foo"
- end
+ it "is honored by string interpolation" do
+ refinement = Module.new do
+ refine Integer do
+ def to_s
+ "foo"
end
end
+ end
- result = nil
- Module.new do
- using refinement
- result = "#{1}"
- end
-
- result.should == "foo"
+ result = nil
+ Module.new do
+ using refinement
+ result = "#{1}"
end
+
+ result.should == "foo"
end
it "is honored by Kernel#binding" do
@@ -458,166 +431,79 @@ describe "Module#refine" do
result.should == "hello from refinement"
end
- ruby_version_is "" ... "2.7" do
- it "is not honored by Kernel#method" do
- klass = Class.new
- refinement = Module.new do
- refine klass do
- def foo; end
- end
+ it "is honored by Kernel#method" do
+ klass = Class.new
+ refinement = Module.new do
+ refine klass do
+ def foo; end
end
-
- -> {
- Module.new do
- using refinement
- klass.new.method(:foo)
- end
- }.should raise_error(NameError, /undefined method `foo'/)
end
- end
-
- ruby_version_is "2.7" do
- it "is honored by Kernel#method" do
- klass = Class.new
- refinement = Module.new do
- refine klass do
- def foo; end
- end
- end
-
- result = nil
- Module.new do
- using refinement
- result = klass.new.method(:foo).class
- end
- result.should == Method
+ result = nil
+ Module.new do
+ using refinement
+ result = klass.new.method(:foo).class
end
- end
- ruby_version_is "" ... "2.7" do
- it "is not honored by Kernel#instance_method" do
- klass = Class.new
- refinement = Module.new do
- refine klass do
- def foo; end
- end
- end
-
- -> {
- Module.new do
- using refinement
- klass.instance_method(:foo)
- end
- }.should raise_error(NameError, /undefined method `foo'/)
- end
+ result.should == Method
end
- ruby_version_is "2.7" do
- it "is honored by Kernel#method" do
- klass = Class.new
- refinement = Module.new do
- refine klass do
- def foo; end
- end
- end
-
- result = nil
- Module.new do
- using refinement
- result = klass.instance_method(:foo).class
+ it "is honored by Kernel#public_method" do
+ klass = Class.new
+ refinement = Module.new do
+ refine klass do
+ def foo; end
end
-
- result.should == UnboundMethod
end
- end
- ruby_version_is "" ... "2.6" do
- it "is not honored by Kernel#respond_to?" do
- klass = Class.new
- refinement = Module.new do
- refine klass do
- def foo; end
- end
- end
-
- result = nil
- Module.new do
- using refinement
- result = klass.new.respond_to?(:foo)
- end
-
- result.should == false
+ result = nil
+ Module.new do
+ using refinement
+ result = klass.new.public_method(:foo).class
end
- end
-
- ruby_version_is "2.6" do
- it "is honored by Kernel#respond_to?" do
- klass = Class.new
- refinement = Module.new do
- refine klass do
- def foo; end
- end
- end
- result = nil
- Module.new do
- using refinement
- result = klass.new.respond_to?(:foo)
- end
-
- result.should == true
- end
+ result.should == Method
end
- ruby_version_is ""..."2.6" do
- it "is not honored by &" do
- refinement = Module.new do
- refine String do
- def to_proc(*args)
- -> * { 'foo' }
- end
- end
+ it "is honored by Kernel#instance_method" do
+ klass = Class.new
+ refinement = Module.new do
+ refine klass do
+ def foo; end
end
+ end
- -> do
- Module.new do
- using refinement
- ["hola"].map(&"upcase")
- end
- end.should raise_error(TypeError, /wrong argument type String \(expected Proc\)/)
+ result = nil
+ Module.new do
+ using refinement
+ result = klass.instance_method(:foo).class
end
- end
- ruby_version_is "2.6" do
- it "is honored by &" do
- refinement = Module.new do
- refine String do
- def to_proc(*args)
- -> * { 'foo' }
- end
- end
- end
+ result.should == UnboundMethod
+ end
- result = nil
- Module.new do
- using refinement
- result = ["hola"].map(&"upcase")
+ it "is honored by Kernel#respond_to?" do
+ klass = Class.new
+ refinement = Module.new do
+ refine klass do
+ def foo; end
end
+ end
- result.should == ['foo']
+ result = nil
+ Module.new do
+ using refinement
+ result = klass.new.respond_to?(:foo)
end
+
+ result.should == true
end
- end
- context "when super is called in a refinement" do
- it "looks in the included to refinery module" do
+ it "is honored by &" do
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
- include ModuleSpecs::IncludedModule
-
- def foo
- super
+ refine String do
+ def to_proc(*args)
+ -> * { 'foo' }
end
end
end
@@ -625,15 +511,19 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.foo
+ result = ["hola"].map(&"upcase")
end
- result.should == "foo from included module"
+ result.should == ['foo']
end
+ end
+ context "when super is called in a refinement" do
it "looks in the refined class" do
+ refined_class = ModuleSpecs.build_refined_class
+
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo
super
end
@@ -643,7 +533,7 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.foo
+ result = refined_class.new.foo
end
result.should == "foo"
@@ -652,19 +542,21 @@ describe "Module#refine" do
# super in a method of a refinement invokes the method in the refined
# class even if there is another refinement which has been activated
# in the same context.
- it "looks in the refined class even if there is another active refinement" do
+ it "looks in the refined class first if called from refined method" do
+ refined_class = ModuleSpecs.build_refined_class(for_super: true)
+
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo
- "foo from refinement"
+ [:R1]
end
end
end
refinement_with_super = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo
- super
+ [:R2] + super
end
end
end
@@ -673,10 +565,39 @@ describe "Module#refine" do
Module.new do
using refinement
using refinement_with_super
- result = ModuleSpecs::ClassWithFoo.new.foo
+ result = refined_class.new.foo
end
- result.should == "foo"
+ result.should == [:R2, :C]
+ end
+
+ it "looks only in the refined class even if there is another active refinement" do
+ refined_class = ModuleSpecs.build_refined_class(for_super: true)
+
+ refinement = Module.new do
+ refine refined_class do
+ def bar
+ "you cannot see me from super because I belong to another active R"
+ end
+ end
+ end
+
+ refinement_with_super = Module.new do
+ refine refined_class do
+ def bar
+ super
+ end
+ end
+ end
+
+
+ Module.new do
+ using refinement
+ using refinement_with_super
+ -> {
+ refined_class.new.bar
+ }.should.raise(NoMethodError)
+ end
end
end
@@ -689,7 +610,7 @@ describe "Module#refine" do
}
[1,2].orig_count.should == 2
end
- -> { [1,2].orig_count }.should raise_error(NoMethodError)
+ -> { [1,2].orig_count }.should.raise(NoMethodError)
end
it 'and alias_method aliases a method within a refinement module, but not outside it' do
@@ -701,7 +622,18 @@ describe "Module#refine" do
}
[1,2].orig_count.should == 2
end
- -> { [1,2].orig_count }.should raise_error(NoMethodError)
+ -> { [1,2].orig_count }.should.raise(NoMethodError)
+ end
+
+ it "and instance_methods returns a list of methods including those of the refined module" do
+ methods = Array.instance_methods
+ methods_2 = []
+ Module.new do
+ refine Array do
+ methods_2 = instance_methods
+ end
+ end
+ methods.should == methods_2
end
# Refinements are inherited by module inclusion.
@@ -772,11 +704,10 @@ describe "Module#refine" do
end
end
end
- spec = self
- klass = Class.new { instance_methods.should_not spec.send(:include, :refinement_only_method) }
+ klass = Class.new { instance_methods.should_not.include?(:refinement_only_method) }
instance = klass.new
- instance.methods.should_not include :refinement_only_method
+ instance.methods.should_not.include? :refinement_only_method
instance.respond_to?(:refinement_only_method).should == false
- -> { instance.method :refinement_only_method }.should raise_error(NameError)
+ -> { instance.method :refinement_only_method }.should.raise(NameError)
end
end