summaryrefslogtreecommitdiff
path: root/spec/ruby/core/refinement
diff options
context:
space:
mode:
authorBenoit Daloze <eregontp@gmail.com>2023-04-25 17:04:25 +0200
committerBenoit Daloze <eregontp@gmail.com>2023-04-25 17:09:53 +0200
commitd562663e4098801c1d7fa7c64a335ea71231a598 (patch)
tree5b2ab2c9fbb86b4223263485fc5a3224562ae78d /spec/ruby/core/refinement
parentd3da01cd110ca99dd0249ee9af92e12cf845998c (diff)
Update to ruby/spec@7f69c86
Diffstat (limited to 'spec/ruby/core/refinement')
-rw-r--r--spec/ruby/core/refinement/fixtures/classes.rb10
-rw-r--r--spec/ruby/core/refinement/import_methods_spec.rb235
2 files changed, 245 insertions, 0 deletions
diff --git a/spec/ruby/core/refinement/fixtures/classes.rb b/spec/ruby/core/refinement/fixtures/classes.rb
new file mode 100644
index 0000000000..94324db47c
--- /dev/null
+++ b/spec/ruby/core/refinement/fixtures/classes.rb
@@ -0,0 +1,10 @@
+module RefinementSpec
+
+ module ModuleWithAncestors
+ include Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/refinement/import_methods_spec.rb b/spec/ruby/core/refinement/import_methods_spec.rb
index 1c526f5822..05973b2380 100644
--- a/spec/ruby/core/refinement/import_methods_spec.rb
+++ b/spec/ruby/core/refinement/import_methods_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe "Refinement#import_methods" do
ruby_version_is "3.1" do
@@ -17,6 +18,229 @@ describe "Refinement#import_methods" do
end
end
end
+
+ it "throws an exception when argument is not a module" do
+ Module.new do
+ refine String do
+ -> {
+ import_methods Integer
+ }.should raise_error(TypeError, "wrong argument type Class (expected Module)")
+ end
+ end
+ end
+
+ it "imports methods from multiple modules" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+
+ str_utils_fancy = Module.new do
+ def indent_star(level)
+ "*" * level + self
+ end
+ end
+
+ Module.new do
+ refine String do
+ import_methods str_utils, str_utils_fancy
+ "foo".indent(3).should == " foo"
+ "foo".indent_star(3).should == "***foo"
+ end
+ end
+ end
+
+ it "imports a method defined in the last module if method with same name is defined in multiple modules" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+
+ str_utils_fancy = Module.new do
+ def indent(level)
+ "*" * level + self
+ end
+ end
+
+ Module.new do
+ refine String do
+ import_methods str_utils, str_utils_fancy
+ "foo".indent(3).should == "***foo"
+ end
+ end
+ end
+
+ it "still imports methods of modules listed before a module that contains method not defined in Ruby" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+
+ string_refined = Module.new do
+ refine String do
+ -> {
+ import_methods str_utils, Kernel
+ }.should raise_error(ArgumentError)
+ end
+ end
+
+ Module.new do
+ using string_refined
+ "foo".indent(3).should == " foo"
+ end
+ end
+ end
+
+ it "warns if a module includes/prepends some other module" do
+ module1 = Module.new do
+ end
+
+ module2 = Module.new do
+ include module1
+ end
+
+ Module.new do
+ refine String do
+ -> {
+ import_methods module2
+ }.should complain(/warning: #<Module:\w*> has ancestors, but Refinement#import_methods doesn't import their methods/)
+ end
+ end
+
+ Module.new do
+ refine String do
+ -> {
+ import_methods RefinementSpec::ModuleWithAncestors
+ }.should complain(/warning: RefinementSpec::ModuleWithAncestors has ancestors, but Refinement#import_methods doesn't import their methods/)
+ end
+ end
+ end
+
+ it "doesn't import methods from included/prepended modules" do
+ Module.new do
+ refine String do
+ suppress_warning { import_methods RefinementSpec::ModuleWithAncestors }
+ end
+
+ using self
+ -> {
+ "foo".indent(3)
+ }.should raise_error(NoMethodError, /undefined method `indent' for ("foo":String|an instance of String)/)
+ end
+ end
+
+ it "doesn't import any methods if one of the arguments is not a module" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+
+ string_refined = Module.new do
+ refine String do
+ -> {
+ import_methods str_utils, Integer
+ }.should raise_error(TypeError)
+ end
+ end
+
+ Module.new do
+ using string_refined
+ -> {
+ "foo".indent(3)
+ }.should raise_error(NoMethodError)
+ end
+ end
+
+ it "imports methods from multiple modules so that methods see other's module's methods" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+ end
+
+ str_utils_normal = Module.new do
+ def indent_normal(level)
+ self.indent(level)
+ end
+ end
+
+ Module.new do
+ refine String do
+ import_methods str_utils, str_utils_normal
+ end
+
+ using self
+ "foo".indent_normal(3).should == " foo"
+ end
+ end
+
+ it "imports methods from module so that methods can see each other" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+
+ def indent_with_dot(level)
+ self.indent(level) + "."
+ end
+ end
+
+ Module.new do
+ refine String do
+ import_methods str_utils
+ end
+
+ using self
+ "foo".indent_with_dot(3).should == " foo."
+ end
+ end
+
+ it "doesn't import module's class methods" do
+ str_utils = Module.new do
+ def self.indent(level)
+ " " * level + self
+ end
+ end
+
+ Module.new do
+ refine String do
+ import_methods str_utils
+ end
+
+ using self
+ -> {
+ String.indent(3)
+ }.should raise_error(NoMethodError, /undefined method `indent' for (String:Class|class String)/)
+ end
+ end
+
+ it "imports module methods with super" do
+ class_to_refine = Class.new do
+ def foo(number)
+ 2 * number
+ end
+ end
+
+ extension = Module.new do
+ def foo(number)
+ super * 2
+ end
+ end
+
+ refinement = Module.new do
+ refine class_to_refine do
+ import_methods extension
+ end
+ end
+
+ Module.new do
+ using refinement
+ class_to_refine.new.foo(2).should == 8
+ end
end
context "when methods are not defined in Ruby code" do
@@ -29,6 +253,17 @@ describe "Refinement#import_methods" do
end
end
end
+
+ it "raises ArgumentError when importing methods from C extension" do
+ require 'zlib'
+ Module.new do
+ refine String do
+ -> {
+ import_methods Zlib
+ }.should raise_error(ArgumentError, /Can't import method which is not defined with Ruby code: Zlib#*/)
+ end
+ end
+ end
end
end
end