aboutsummaryrefslogtreecommitdiffstats
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.rb300
1 files changed, 295 insertions, 5 deletions
diff --git a/spec/ruby/core/module/refine_spec.rb b/spec/ruby/core/module/refine_spec.rb
index ca12d5d13b..ebb7111d82 100644
--- a/spec/ruby/core/module/refine_spec.rb
+++ b/spec/ruby/core/module/refine_spec.rb
@@ -731,16 +731,67 @@ describe "Module#refine" do
result.should == "foo"
end
+ it "looks in the refined class from included module" do
+ refined_class = ModuleSpecs.build_refined_class(for_super: true)
+
+ a = Module.new do
+ def foo
+ [:A] + super
+ end
+ end
+
+ refinement = Module.new do
+ refine refined_class do
+ include a
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+
+ result = refined_class.new.foo
+ end
+
+ result.should == [:A, :C]
+ end
+
+ it "looks in the refined ancestors from included module" do
+ refined_class = ModuleSpecs.build_refined_class(for_super: true)
+ subclass = Class.new(refined_class)
+
+ a = Module.new do
+ def foo
+ [:A] + super
+ end
+ end
+
+ refinement = Module.new do
+ refine refined_class do
+ include a
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+
+ result = subclass.new.foo
+ end
+
+ result.should == [:A, :C]
+ end
+
# 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
- refined_class = ModuleSpecs.build_refined_class
+ 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 refined_class do
def foo
- "foo from refinement"
+ [:R1]
end
end
end
@@ -748,7 +799,7 @@ describe "Module#refine" do
refinement_with_super = Module.new do
refine refined_class do
def foo
- super
+ [:R2] + super
end
end
end
@@ -760,7 +811,246 @@ describe "Module#refine" do
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_error(NoMethodError)
+ end
+ end
+
+ it "does't have access to active refinements for C from included module" do
+ refined_class = ModuleSpecs.build_refined_class
+
+ a = Module.new do
+ def foo
+ super + bar
+ end
+ end
+
+ refinement = Module.new do
+ refine refined_class do
+ include a
+
+ def bar
+ "bar is not seen from A methods"
+ end
+ end
+ end
+
+ Module.new do
+ using refinement
+ -> {
+ refined_class.new.foo
+ }.should raise_error(NameError) { |e| e.name.should == :bar }
+ end
+ end
+
+ it "does't have access to other active refinements from included module" do
+ refined_class = ModuleSpecs.build_refined_class
+
+ refinement_integer = Module.new do
+ refine Integer do
+ def bar
+ "bar is not seen from A methods"
+ end
+ end
+ end
+
+ a = Module.new do
+ def foo
+ super + 1.bar
+ end
+ end
+
+ refinement = Module.new do
+ refine refined_class do
+ include a
+ end
+ end
+
+ Module.new do
+ using refinement
+ using refinement_integer
+ -> {
+ refined_class.new.foo
+ }.should raise_error(NameError) { |e| e.name.should == :bar }
+ end
+ end
+
+ # https://bugs.ruby-lang.org/issues/16977
+ it "looks in the another active refinement if super called from included modules" do
+ refined_class = ModuleSpecs.build_refined_class(for_super: true)
+
+ a = Module.new do
+ def foo
+ [:A] + super
+ end
+ end
+
+ b = Module.new do
+ def foo
+ [:B] + super
+ end
+ end
+
+ refinement_a = Module.new do
+ refine refined_class do
+ include a
+ end
+ end
+
+ refinement_b = Module.new do
+ refine refined_class do
+ include b
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement_a
+ using refinement_b
+ result = refined_class.new.foo
+ end
+
+ result.should == [:B, :A, :C]
+ end
+
+ it "looks in the current active refinement from included modules" do
+ refined_class = ModuleSpecs.build_refined_class(for_super: true)
+
+ a = Module.new do
+ def foo
+ [:A] + super
+ end
+ end
+
+ b = Module.new do
+ def foo
+ [:B] + super
+ end
+ end
+
+ refinement = Module.new do
+ refine refined_class do
+ def foo
+ [:LAST] + super
+ end
+ end
+ end
+
+ refinement_a_b = Module.new do
+ refine refined_class do
+ include a
+ include b
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ using refinement_a_b
+ result = refined_class.new.foo
+ end
+
+ result.should == [:B, :A, :LAST, :C]
+ end
+
+ ruby_version_is ""..."2.8" do
+ it "looks in the lexical scope refinements before other active refinements" do
+ refined_class = ModuleSpecs.build_refined_class(for_super: true)
+
+ refinement_local = Module.new do
+ refine refined_class do
+ def foo
+ [:LOCAL] + super
+ end
+ end
+ end
+
+ a = Module.new do
+ using refinement_local
+
+ def foo
+ [:A] + super
+ end
+ end
+
+ refinement = Module.new do
+ refine refined_class do
+ include a
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = refined_class.new.foo
+ end
+
+ result.should == [:A, :LOCAL, :C]
+ end
+ end
+
+ ruby_version_is "2.8" do
+ # https://bugs.ruby-lang.org/issues/17007
+ it "does not look in the lexical scope refinements before other active refinements" do
+ refined_class = ModuleSpecs.build_refined_class(for_super: true)
+
+ refinement_local = Module.new do
+ refine refined_class do
+ def foo
+ [:LOCAL] + super
+ end
+ end
+ end
+
+ a = Module.new do
+ using refinement_local
+
+ def foo
+ [:A] + super
+ end
+ end
+
+ refinement = Module.new do
+ refine refined_class do
+ include a
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = refined_class.new.foo
+ end
+
+ result.should == [:A, :C]
+ end
end
end