diff --git a/.gitignore b/.gitignore index 76b8291..72cebb9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,40 +1,2 @@ -/rspec-mocks-2.5.0.gem -/rspec-mocks-2.6.0.rc4.gem -/rspec-mocks-2.6.0.rc6.gem -/rspec-mocks-2.6.0.gem -/rspec-mocks-2.8.0.gem -/rspec-mocks-2.11.3.gem -/rspec-mocks-2.12.1.gem -/rspec-mocks-2.12.2.gem -/rspec-mocks-2.13.0.gem -/rspec-mocks-2.13.1.gem -/rspec-mocks-2.14.3.gem -/rspec-mocks-2.14.4.gem -/rspec-mocks-2.14.5.gem -/rspec-mocks-2.14.6.gem -/rspec-mocks-3.1.3.gem -/rubygem-rspec-mocks-3.1.3-full.tar.gz -/rspec-mocks-3.2.0.gem -/rubygem-rspec-mocks-3.2.0-full.tar.gz -/rspec-mocks-3.2.1.gem -/rubygem-rspec-mocks-3.2.1-full.tar.gz -/rspec-mocks-3.3.2.gem -/rubygem-rspec-mocks-3.3.2-full.tar.gz -/rspec-mocks-3.4.0.gem -/rubygem-rspec-mocks-3.4.0-full.tar.gz -/rspec-mocks-3.4.1.gem -/rubygem-rspec-mocks-3.4.1-full.tar.gz -/rspec-mocks-3.5.0.gem -/rubygem-rspec-mocks-3.5.0-full.tar.gz -/rspec-mocks-3.6.0.gem -/rubygem-rspec-mocks-3.6.0-full.tar.gz -/rspec-mocks-3.7.0.gem -/rubygem-rspec-mocks-3.7.0-full.tar.gz -/rspec-mocks-3.8.0.gem -/rubygem-rspec-mocks-3.8.0-full.tar.gz -/rspec-mocks-3.8.1.gem -/rubygem-rspec-mocks-3.8.1-full.tar.gz -/rspec-mocks-3.9.0.gem -/rubygem-rspec-mocks-3.9.0-full.tar.gz -/rspec-mocks-3.9.1.gem -/rubygem-rspec-mocks-3.9.1-full.tar.gz +/rspec-mocks-*.gem +/rubygem-rspec-mocks-*-full.tar.gz diff --git a/rspec-mocks-pr1597-ruby34-formatting.patch b/rspec-mocks-pr1597-ruby34-formatting.patch new file mode 100644 index 0000000..e99a6eb --- /dev/null +++ b/rspec-mocks-pr1597-ruby34-formatting.patch @@ -0,0 +1,429 @@ +From f8b49348d02d0220e20391665f7418f9212dac02 Mon Sep 17 00:00:00 2001 +From: Jon Rowe +Date: Fri, 18 Oct 2024 21:39:26 +0100 +Subject: [PATCH] Relax specs for Ruby 3.4 hash formatting + +--- + .../matching_arguments.feature | 6 +- + .../step_definitions/additional_cli_steps.rb | 7 +- + spec/rspec/mocks/argument_matchers_spec.rb | 14 ++-- + spec/rspec/mocks/diffing_spec.rb | 84 ++++++++++++------- + spec/rspec/mocks/double_spec.rb | 9 +- + .../mocks/hash_excluding_matcher_spec.rb | 9 +- + .../mocks/hash_including_matcher_spec.rb | 9 +- + spec/rspec/mocks/matchers/receive_spec.rb | 26 ++++-- + .../expected_arg_verification_spec.rb | 11 ++- + 9 files changed, 124 insertions(+), 51 deletions(-) + +diff --git a/features/setting_constraints/matching_arguments.feature b/features/setting_constraints/matching_arguments.feature +index caea74248..cad5cea4c 100644 +--- a/features/setting_constraints/matching_arguments.feature ++++ b/features/setting_constraints/matching_arguments.feature +@@ -73,7 +73,7 @@ Feature: Matching arguments + end + """ + When I run `rspec keyword_example_spec.rb` +- Then it should fail with the following output: ++ Then it should fail with the following output, ignoring hash syntax: + | 2 examples, 1 failure | + | | + | Failure/Error: dbl.foo(bar: "incorrect") | +@@ -100,7 +100,7 @@ Feature: Matching arguments + end + """ + When I run `rspec keyword_example_spec.rb` +- Then it should fail with the following output: ++ Then it should fail with the following output, ignoring hash syntax: + | 1 example, 1 failure | + | | + | Failure/Error: dbl.foo({bar: "also incorrect"}) | +@@ -156,7 +156,7 @@ Feature: Matching arguments + end + """ + When I run `rspec rspec_satisfy_spec.rb` +- Then it should fail with the following output: ++ Then it should fail with the following output, ignoring hash syntax: + | 2 examples, 1 failure | + | | + | Failure/Error: dbl.foo({ :a => { :b => { :c => 3 } } }) | +diff --git a/features/step_definitions/additional_cli_steps.rb b/features/step_definitions/additional_cli_steps.rb +index 77f8c0f30..acf1117e0 100644 +--- a/features/step_definitions/additional_cli_steps.rb ++++ b/features/step_definitions/additional_cli_steps.rb +@@ -22,8 +22,13 @@ + diffable + end + +-Then /^it should fail with the following output:$/ do |table| ++Then /^it should fail with the following output(, ignoring hash syntax)?:$/ do |ignore_hash_syntax, table| + step %q(the exit status should be 1) + lines = table.raw.flatten.reject(&:empty?) ++ ++ if ignore_hash_syntax && RUBY_VERSION.to_f > 3.3 ++ lines = lines.map { |line| line.gsub(/([^\s])=>/, '\1 => ') } ++ end ++ + expect(all_output).to match_table(lines) + end +diff --git a/spec/rspec/mocks/argument_matchers_spec.rb b/spec/rspec/mocks/argument_matchers_spec.rb +index eb101a04c..8f31d1786 100644 +--- a/spec/rspec/mocks/argument_matchers_spec.rb ++++ b/spec/rspec/mocks/argument_matchers_spec.rb +@@ -256,7 +256,7 @@ module Mocks + expect(a_double).to receive(:random_call).with(hash_including(:a => 1)) + expect { + a_double.random_call(:a => 2) +- }.to fail_including "expected: (hash_including(:a=>1))" ++ }.to fail_including "expected: (hash_including(#{hash_syntax(:a => 1)}))" + end + end + +@@ -270,7 +270,7 @@ module Mocks + expect(a_double).to receive(:random_call).with(hash_excluding(:a => 1)) + expect { + a_double.random_call(:a => 1) +- }.to fail_including "expected: (hash_not_including(:a=>1))" ++ }.to fail_including "expected: (hash_not_including(#{hash_syntax(:a => 1)}))" + end + end + +@@ -431,7 +431,7 @@ def ==(other) + expect(a_double).to receive(:random_call).with(:a => "a", :b => "b") + expect do + a_double.random_call(opts) +- end.to fail_with(/expected: \(\{(:a=>\"a\", :b=>\"b\"|:b=>\"b\", :a=>\"a\")\}\)/) ++ end.to fail_with(/expected: \(\{(:a\s*=>\s*\"a\", :b\s*=>\s*\"b\"|:b\s*=>\s*\"b\", :a\s*=>\s*\"a\")\}\)/) + end + else + it "matches against a hash submitted as a positional argument and received as keyword arguments in Ruby 2.7 or before" do +@@ -445,14 +445,14 @@ def ==(other) + expect(a_double).to receive(:random_call).with(:a => "b", :c => "d") + expect do + a_double.random_call(:a => "b", :c => "e") +- end.to fail_with(/expected: \(\{(:a=>\"b\", :c=>\"d\"|:c=>\"d\", :a=>\"b\")\}\)/) ++ end.to fail_with(/expected: \(\{(:a\s*=>\s*\"b\", :c\s*=>\s*\"d\"|:c\s*=>\s*\"d\", :a\s*=>\s*\"b\")\}\)/) + end + + it "fails for a hash w/ wrong keys", :reset => true do + expect(a_double).to receive(:random_call).with(:a => "b", :c => "d") + expect do + a_double.random_call("a" => "b", "c" => "d") +- end.to fail_with(/expected: \(\{(:a=>\"b\", :c=>\"d\"|:c=>\"d\", :a=>\"b\")\}\)/) ++ end.to fail_with(/expected: \(\{(:a\s*=>\s*\"b\", :c\s*=>\s*\"d\"|:c\s*=>\s*\"d\", :a\s*=>\s*\"b\")\}\)/) + end + + it "matches a class against itself" do +@@ -502,6 +502,10 @@ def ==(other) + expect { a_double.msg 3 }.to fail_including "expected: (my_thing)" + end + end ++ ++ def hash_syntax(hash) ++ hash.inspect.gsub(/\{(.*)\}/, '\1') ++ end + end + end + end +diff --git a/spec/rspec/mocks/diffing_spec.rb b/spec/rspec/mocks/diffing_spec.rb +index e40fa55b6..8be6510da 100644 +--- a/spec/rspec/mocks/diffing_spec.rb ++++ b/spec/rspec/mocks/diffing_spec.rb +@@ -100,15 +100,18 @@ + if RSpec::Support::RubyFeatures.distincts_kw_args_from_positional_hash? + eval <<-'RUBY', nil, __FILE__, __LINE__ + 1 + it "prints a diff when keyword argument were expected but got an option hash (using splat)" do ++ message = ++ "# received :foo with unexpected arguments\n" \ ++ " expected: ({:baz=>:quz, :foo=>:bar}) (keyword arguments)\n" \ ++ " got: ({:baz=>:quz, :foo=>:bar}) (options hash)" ++ ++ message = message.gsub('=>', ' => ') if RUBY_VERSION.to_f > 3.3 ++ + with_unfulfilled_double do |d| + expect(d).to receive(:foo).with(**expected_hash) + expect { + d.foo(expected_hash) +- }.to fail_with( +- "# received :foo with unexpected arguments\n" \ +- " expected: ({:baz=>:quz, :foo=>:bar}) (keyword arguments)\n" \ +- " got: ({:baz=>:quz, :foo=>:bar}) (options hash)" +- ) ++ }.to fail_with(message) + end + end + RUBY +@@ -117,14 +120,18 @@ + it "prints a diff when keyword argument were expected but got an option hash (literal)" do + with_unfulfilled_double do |d| + expect(d).to receive(:foo).with(:positional, keyword: 1) +- expect { +- options = { keyword: 1 } +- d.foo(:positional, options) +- }.to fail_with( ++ ++ message = + "# received :foo with unexpected arguments\n" \ + " expected: (:positional, {:keyword=>1}) (keyword arguments)\n" \ + " got: (:positional, {:keyword=>1}) (options hash)" +- ) ++ ++ message = message.gsub('=>',' => ') if RUBY_VERSION.to_f > 3.3 ++ ++ expect { ++ options = { keyword: 1 } ++ d.foo(:positional, options) ++ }.to fail_with(message) + end + end + RUBY +@@ -139,10 +146,7 @@ + + expect(d).to receive(:foo).with(expected_input, one: 1) + +- expect { +- options = { one: 1 } +- d.foo(actual_input, options) +- }.to fail_with( ++ message = + "# received :foo with unexpected arguments\n" \ + " expected: (#{expected_input.inspect}, {:one=>1}) (keyword arguments)\n" \ + " got: (#{actual_input.inspect}, {:one=>1}) (options hash)\n" \ +@@ -150,7 +154,13 @@ + "@@ -1 +1 @@\n" \ + "-[#{expected_input.inspect}, {:one=>1}]\n" \ + "+[#{actual_input.inspect}, {:one=>1}]\n" +- ) ++ ++ message = message.gsub('=>',' => ') if RUBY_VERSION.to_f > 3.3 ++ ++ expect { ++ options = { one: 1 } ++ d.foo(actual_input, options) ++ }.to fail_with(message) + end + end + RUBY +@@ -172,28 +182,34 @@ + if RSpec::Support::RubyFeatures.distincts_kw_args_from_positional_hash? + eval <<-'RUBY', nil, __FILE__, __LINE__ + 1 + it "prints a diff when keyword argument were expected but got an option hash (using splat)" do +- expect(d).to receive(:foo).with(:positional, **expected_hash) +- expect { +- d.foo(:positional, expected_hash) +- }.to fail_with( ++ message = + "#{d.inspect} received :foo with unexpected arguments\n" \ + " expected: (:positional, {:baz=>:quz, :foo=>:bar}) (keyword arguments)\n" \ + " got: (:positional, {:baz=>:quz, :foo=>:bar}) (options hash)" +- ) ++ ++ message.gsub!('=>',' => ') if RUBY_VERSION.to_f > 3.3 ++ ++ expect(d).to receive(:foo).with(:positional, **expected_hash) ++ expect { ++ d.foo(:positional, expected_hash) ++ }.to fail_with(message) + end + RUBY + + eval <<-'RUBY', nil, __FILE__, __LINE__ + 1 + it "prints a diff when keyword argument were expected but got an option hash (literal)" do ++ message = ++ "#{d.inspect} received :foo with unexpected arguments\n" \ ++ " expected: (:positional, {:keyword=>1}) (keyword arguments)\n" \ ++ " got: (:positional, {:keyword=>1}) (options hash)" ++ ++ message.gsub!('=>',' => ') if RUBY_VERSION.to_f > 3.3 ++ + expect(d).to receive(:foo).with(:positional, keyword: 1) + expect { + options = { keyword: 1 } + d.foo(:positional, options) +- }.to fail_with( +- "#{d.inspect} received :foo with unexpected arguments\n" \ +- " expected: (:positional, {:keyword=>1}) (keyword arguments)\n" \ +- " got: (:positional, {:keyword=>1}) (options hash)" +- ) ++ }.to fail_with(message) + end + RUBY + +@@ -206,10 +222,7 @@ + + expect(d).to receive(:foo).with(expected_input, one: 1) + +- expect { +- options = { one: 1 } +- d.foo(actual_input, options) +- }.to fail_with( ++ message = + "#{d.inspect} received :foo with unexpected arguments\n" \ + " expected: (#{expected_input.inspect}, {:one=>1}) (keyword arguments)\n" \ + " got: (#{actual_input.inspect}, {:one=>1}) (options hash)\n" \ +@@ -217,7 +230,13 @@ + "@@ -1 +1 @@\n" \ + "-[#{expected_input.inspect}, {:one=>1}]\n" \ + "+[#{actual_input.inspect}, {:one=>1}]\n" +- ) ++ ++ message = message.gsub('=>', ' => ') if RUBY_VERSION.to_f > 3.3 ++ ++ expect { ++ options = { one: 1 } ++ d.foo(actual_input, options) ++ }.to fail_with(message) + end + RUBY + end +@@ -232,6 +251,11 @@ + def hash_regex_inspect(hash) + "\\{(#{hash.map { |key, value| "#{key.inspect}=>#{value.inspect}.*" }.join "|"}){#{hash.size}}\\}" + end ++ elsif RUBY_VERSION.to_f > 3.3 ++ # Ruby head / 3.4 is changing the hash syntax inspect, but we use PP when diffing which just spaces out hashrockets ++ def hash_regex_inspect(hash) ++ Regexp.escape("{#{hash.map { |key, value| "#{key.inspect} => #{value.inspect}"}.join(", ")}}") ++ end + else + def hash_regex_inspect(hash) + Regexp.escape(hash.inspect) +diff --git a/spec/rspec/mocks/double_spec.rb b/spec/rspec/mocks/double_spec.rb +index d5dff63b3..ac65c590f 100644 +--- a/spec/rspec/mocks/double_spec.rb ++++ b/spec/rspec/mocks/double_spec.rb +@@ -526,10 +526,17 @@ def initialize(amount, units) + + if kw_args_supported? + it 'fails when calling yielding method with invalid kw args' do ++ message = ++ if RUBY_VERSION.to_f > 3.3 ++ '# yielded |{:x => 1, :y => 2}| to block with optional keyword args (:x)' ++ else ++ '# yielded |{:x=>1, :y=>2}| to block with optional keyword args (:x)' ++ end ++ + expect(@double).to receive(:yield_back).and_yield(:x => 1, :y => 2) + expect { + eval("@double.yield_back { |x: 1| }") +- }.to fail_with '# yielded |{:x=>1, :y=>2}| to block with optional keyword args (:x)' ++ }.to fail_with message + end + end + +diff --git a/spec/rspec/mocks/hash_excluding_matcher_spec.rb b/spec/rspec/mocks/hash_excluding_matcher_spec.rb +index fc0faed05..3fca99823 100644 +--- a/spec/rspec/mocks/hash_excluding_matcher_spec.rb ++++ b/spec/rspec/mocks/hash_excluding_matcher_spec.rb +@@ -4,7 +4,14 @@ module ArgumentMatchers + RSpec.describe HashExcludingMatcher do + + it "describes itself properly" do +- expect(HashExcludingMatcher.new(:a => 5).description).to eq "hash_not_including(:a=>5)" ++ message = ++ if RUBY_VERSION.to_f > 3.3 ++ "hash_not_including(a: 5)" ++ else ++ "hash_not_including(:a=>5)" ++ end ++ ++ expect(HashExcludingMatcher.new(:a => 5).description).to eq message + end + + describe "passing" do +diff --git a/spec/rspec/mocks/hash_including_matcher_spec.rb b/spec/rspec/mocks/hash_including_matcher_spec.rb +index ad5e8587a..057aec55d 100644 +--- a/spec/rspec/mocks/hash_including_matcher_spec.rb ++++ b/spec/rspec/mocks/hash_including_matcher_spec.rb +@@ -4,7 +4,14 @@ module ArgumentMatchers + RSpec.describe HashIncludingMatcher do + + it "describes itself properly" do +- expect(HashIncludingMatcher.new(:a => 1).description).to eq "hash_including(:a=>1)" ++ message = ++ if RUBY_VERSION.to_f > 3.3 ++ "hash_including(a: 1)" ++ else ++ "hash_including(:a=>1)" ++ end ++ ++ expect(HashIncludingMatcher.new(:a => 1).description).to eq message + end + + it "describes passed matchers" do +diff --git a/spec/rspec/mocks/matchers/receive_spec.rb b/spec/rspec/mocks/matchers/receive_spec.rb +index 1b71dd58f..abf266935 100644 +--- a/spec/rspec/mocks/matchers/receive_spec.rb ++++ b/spec/rspec/mocks/matchers/receive_spec.rb +@@ -130,7 +130,7 @@ def kw_args_method(a:, b:); end + dbl.kw_args_method(a: 1, b: 2) + end + +- if RUBY_VERSION >= '3.0' ++ if RUBY_VERSION.to_f >= 3.0 + it "fails to expect to receive hash with keyword args" do + expect { + dbl = instance_double(TestObject) +@@ -138,9 +138,16 @@ def kw_args_method(a:, b:); end + dbl.kw_args_method({a: 1, b: 2}) + }.to fail_with do |failure| + reset_all +- expect(failure.message) +- .to include('expected: ({:a=>1, :b=>2}) (keyword arguments)') +- .and include('got: ({:a=>1, :b=>2}) (options hash)') ++ ++ if RUBY_VERSION.to_f > 3.3 ++ expect(failure.message) ++ .to include('expected: ({:a => 1, :b => 2}) (keyword arguments)') ++ .and include('got: ({:a => 1, :b => 2}) (options hash)') ++ else ++ expect(failure.message) ++ .to include('expected: ({:a=>1, :b=>2}) (keyword arguments)') ++ .and include('got: ({:a=>1, :b=>2}) (options hash)') ++ end + end + end + else +@@ -505,9 +512,14 @@ def receiver.method_missing(*); end # a poor man's stub... + receiver.foo(1, :bar => 2) + receiver.foo(1, :bar => 3) + +- expect { verify_all }.to( +- raise_error(/received: 2 times with arguments: \(anything, hash_including\(:bar=>"anything"\)\)$/) +- ) ++ message = ++ if RUBY_VERSION.to_f > 3.3 ++ /received: 2 times with arguments: \(anything, hash_including\(bar: "anything"\)\)$/ ++ else ++ /received: 2 times with arguments: \(anything, hash_including\(:bar=>"anything"\)\)$/ ++ end ++ ++ expect { verify_all }.to raise_error(message) + end + end + end +diff --git a/spec/rspec/mocks/verifying_doubles/expected_arg_verification_spec.rb b/spec/rspec/mocks/verifying_doubles/expected_arg_verification_spec.rb +index d39995341..1860afa1a 100644 +--- a/spec/rspec/mocks/verifying_doubles/expected_arg_verification_spec.rb ++++ b/spec/rspec/mocks/verifying_doubles/expected_arg_verification_spec.rb +@@ -130,12 +130,19 @@ module Mocks + dbl.kw_args_method(1, :required_arg => 2, :optional_arg => 3) + end + +- if RUBY_VERSION >= "3" ++ if RUBY_VERSION.to_f >= 3.0 + it "fails to match against a hash submitted as a positional argument and received as keyword arguments in Ruby 3.0 or later", :reset => true do ++ messages = ++ if RUBY_VERSION.to_f > 3.3 ++ ["expected: (1, {:optional_arg => 3, :required_arg => 2}) (keyword arguments)", "got: (1, {:optional_arg => 3, :required_arg => 2}) (options hash)"] ++ else ++ ["expected: (1, {:optional_arg=>3, :required_arg=>2}) (keyword arguments)", "got: (1, {:optional_arg=>3, :required_arg=>2}) (options hash)"] ++ end ++ + expect(dbl).to receive(:kw_args_method).with(1, :required_arg => 2, :optional_arg => 3) + expect do + dbl.kw_args_method(1, {:required_arg => 2, :optional_arg => 3}) +- end.to fail_with(a_string_including("expected: (1, {:optional_arg=>3, :required_arg=>2}) (keyword arguments)", "got: (1, {:optional_arg=>3, :required_arg=>2}) (options hash)")) ++ end.to fail_with(a_string_including(*messages)) + end + else + it "matches against a hash submitted as a positional argument and received as keyword arguments in Ruby 2.7 or before" do diff --git a/rspec-mocks-pr164-ruby34-hash-syntax.patch b/rspec-mocks-pr164-ruby34-hash-syntax.patch new file mode 100644 index 0000000..2f5bec0 --- /dev/null +++ b/rspec-mocks-pr164-ruby34-hash-syntax.patch @@ -0,0 +1,190 @@ +From 9310b4b72e205c6352c4b30015a3b8f3d2fb02e8 Mon Sep 17 00:00:00 2001 +From: Jon Rowe +Date: Thu, 26 Dec 2024 11:06:37 +0000 +Subject: [PATCH 1/2] Format hashes in new {a: :b} format on Ruby 3.4 + +--- + .../step_definitions/additional_cli_steps.rb | 2 +- + .../rspec/mocks/argument_matchers_spec.rb | 24 ++++++++++++++++--- + rspec-mocks/spec/rspec/mocks/diffing_spec.rb | 17 +++++-------- + rspec-mocks/spec/rspec/mocks/double_spec.rb | 2 +- + .../spec/rspec/mocks/matchers/receive_spec.rb | 4 ++-- + .../expected_arg_verification_spec.rb | 2 +- + .../lib/rspec/support/object_formatter.rb | 2 ++ + .../spec/rspec/support/differ_spec.rb | 2 +- + .../rspec/support/object_formatter_spec.rb | 22 +++++++++++++++-- + 9 files changed, 55 insertions(+), 22 deletions(-) + +diff --git a/rspec-mocks/features/step_definitions/additional_cli_steps.rb b/rspec-mocks/features/step_definitions/additional_cli_steps.rb +index acf1117e0..9ccfac5b1 100644 +--- a/rspec-mocks/features/step_definitions/additional_cli_steps.rb ++++ b/rspec-mocks/features/step_definitions/additional_cli_steps.rb +@@ -27,7 +27,7 @@ + lines = table.raw.flatten.reject(&:empty?) + + if ignore_hash_syntax && RUBY_VERSION.to_f > 3.3 +- lines = lines.map { |line| line.gsub(/([^\s])=>/, '\1 => ') } ++ lines = lines.map { |line| line.gsub(/:(\w+)=>/, '\1: ') } + end + + expect(all_output).to match_table(lines) +diff --git a/rspec-mocks/spec/rspec/mocks/argument_matchers_spec.rb b/rspec-mocks/spec/rspec/mocks/argument_matchers_spec.rb +index 8f31d1786..4bffa727d 100644 +--- a/rspec-mocks/spec/rspec/mocks/argument_matchers_spec.rb ++++ b/rspec-mocks/spec/rspec/mocks/argument_matchers_spec.rb +@@ -431,7 +431,13 @@ def ==(other) + expect(a_double).to receive(:random_call).with(:a => "a", :b => "b") + expect do + a_double.random_call(opts) +- end.to fail_with(/expected: \(\{(:a\s*=>\s*\"a\", :b\s*=>\s*\"b\"|:b\s*=>\s*\"b\", :a\s*=>\s*\"a\")\}\)/) ++ end.to fail_with( ++ if RUBY_VERSION.to_f > 3.3 ++ /expected: \(\{a: \"a\", b: \"b\"\}\)/ ++ else ++ /expected: \(\{(:a\s*=>\s*\"a\", :b\s*=>\s*\"b\"|:b\s*=>\s*\"b\", :a\s*=>\s*\"a\")\}\)/ ++ end ++ ) + end + else + it "matches against a hash submitted as a positional argument and received as keyword arguments in Ruby 2.7 or before" do +@@ -445,14 +451,26 @@ def ==(other) + expect(a_double).to receive(:random_call).with(:a => "b", :c => "d") + expect do + a_double.random_call(:a => "b", :c => "e") +- end.to fail_with(/expected: \(\{(:a\s*=>\s*\"b\", :c\s*=>\s*\"d\"|:c\s*=>\s*\"d\", :a\s*=>\s*\"b\")\}\)/) ++ end.to fail_with( ++ if RUBY_VERSION.to_f > 3.3 ++ /expected: \(\{a: \"b\", c: \"d\"\}\)/ ++ else ++ /expected: \(\{(:a\s*=>\s*\"b\", :c\s*=>\s*\"d\"|:c\s*=>\s*\"d\", :a\s*=>\s*\"b\")\}\)/ ++ end ++ ) + end + + it "fails for a hash w/ wrong keys", :reset => true do + expect(a_double).to receive(:random_call).with(:a => "b", :c => "d") + expect do + a_double.random_call("a" => "b", "c" => "d") +- end.to fail_with(/expected: \(\{(:a\s*=>\s*\"b\", :c\s*=>\s*\"d\"|:c\s*=>\s*\"d\", :a\s*=>\s*\"b\")\}\)/) ++ end.to fail_with( ++ if RUBY_VERSION.to_f > 3.3 ++ /expected: \(\{a: \"b\", c: \"d\"\}\)/ ++ else ++ /expected: \(\{(:a\s*=>\s*\"b\", :c\s*=>\s*\"d\"|:c\s*=>\s*\"d\", :a\s*=>\s*\"b\")\}\)/ ++ end ++ ) + end + + it "matches a class against itself" do +diff --git a/rspec-mocks/spec/rspec/mocks/diffing_spec.rb b/rspec-mocks/spec/rspec/mocks/diffing_spec.rb +index f071cc1ec..b4492b4e8 100644 +--- a/rspec-mocks/spec/rspec/mocks/diffing_spec.rb ++++ b/rspec-mocks/spec/rspec/mocks/diffing_spec.rb +@@ -105,7 +105,7 @@ + " expected: ({:baz=>:quz, :foo=>:bar}) (keyword arguments)\n" \ + " got: ({:baz=>:quz, :foo=>:bar}) (options hash)" + +- message = message.gsub('=>', ' => ') if RUBY_VERSION.to_f > 3.3 ++ message = message.gsub(/:(\w+)=>/, '\1: ') if RUBY_VERSION.to_f > 3.3 + + with_unfulfilled_double do |d| + expect(d).to receive(:foo).with(**expected_hash) +@@ -126,7 +126,7 @@ + " expected: (:positional, {:keyword=>1}) (keyword arguments)\n" \ + " got: (:positional, {:keyword=>1}) (options hash)" + +- message = message.gsub('=>',' => ') if RUBY_VERSION.to_f > 3.3 ++ message = message.gsub(/:(\w+)=>/, '\1: ') if RUBY_VERSION.to_f > 3.3 + + expect { + options = { keyword: 1 } +@@ -155,7 +155,7 @@ + "-[#{expected_input.inspect}, {:one=>1}]\n" \ + "+[#{actual_input.inspect}, {:one=>1}]\n" + +- message = message.gsub('=>',' => ') if RUBY_VERSION.to_f > 3.3 ++ message = message.gsub(/:(\w+)=>/, '\1: ') if RUBY_VERSION.to_f > 3.3 + + expect { + options = { one: 1 } +@@ -187,7 +187,7 @@ + " expected: (:positional, {:baz=>:quz, :foo=>:bar}) (keyword arguments)\n" \ + " got: (:positional, {:baz=>:quz, :foo=>:bar}) (options hash)" + +- message.gsub!('=>',' => ') if RUBY_VERSION.to_f > 3.3 ++ message = message.gsub(/:(\w+)=>/, '\1: ') if RUBY_VERSION.to_f > 3.3 + + expect(d).to receive(:foo).with(:positional, **expected_hash) + expect { +@@ -203,7 +203,7 @@ + " expected: (:positional, {:keyword=>1}) (keyword arguments)\n" \ + " got: (:positional, {:keyword=>1}) (options hash)" + +- message.gsub!('=>',' => ') if RUBY_VERSION.to_f > 3.3 ++ message = message.gsub(/:(\w+)=>/, '\1: ') if RUBY_VERSION.to_f > 3.3 + + expect(d).to receive(:foo).with(:positional, keyword: 1) + expect { +@@ -231,7 +231,7 @@ + "-[#{expected_input.inspect}, {:one=>1}]\n" \ + "+[#{actual_input.inspect}, {:one=>1}]\n" + +- message = message.gsub('=>', ' => ') if RUBY_VERSION.to_f > 3.3 ++ message = message.gsub(/:(\w+)=>/, '\1: ') if RUBY_VERSION.to_f > 3.3 + + expect { + options = { one: 1 } +@@ -251,11 +251,6 @@ + def hash_regex_inspect(hash) + "\\{(#{hash.map { |key, value| "#{key.inspect}=>#{value.inspect}.*" }.join "|"}){#{hash.size}}\\}" + end +- elsif RUBY_VERSION.to_f > 3.3 +- # Ruby head / 3.4 is changing the hash syntax inspect, but we use PP when diffing which just spaces out hashrockets +- def hash_regex_inspect(hash) +- Regexp.escape("{#{hash.map { |key, value| "#{key.inspect} => #{value.inspect}"}.join(", ")}}") +- end + else + def hash_regex_inspect(hash) + Regexp.escape(hash.inspect) +diff --git a/rspec-mocks/spec/rspec/mocks/double_spec.rb b/rspec-mocks/spec/rspec/mocks/double_spec.rb +index ac65c590f..9738edfa7 100644 +--- a/rspec-mocks/spec/rspec/mocks/double_spec.rb ++++ b/rspec-mocks/spec/rspec/mocks/double_spec.rb +@@ -528,7 +528,7 @@ def initialize(amount, units) + it 'fails when calling yielding method with invalid kw args' do + message = + if RUBY_VERSION.to_f > 3.3 +- '# yielded |{:x => 1, :y => 2}| to block with optional keyword args (:x)' ++ '# yielded |{x: 1, y: 2}| to block with optional keyword args (:x)' + else + '# yielded |{:x=>1, :y=>2}| to block with optional keyword args (:x)' + end +diff --git a/rspec-mocks/spec/rspec/mocks/matchers/receive_spec.rb b/rspec-mocks/spec/rspec/mocks/matchers/receive_spec.rb +index 3e71bd289..307c86a6f 100644 +--- a/rspec-mocks/spec/rspec/mocks/matchers/receive_spec.rb ++++ b/rspec-mocks/spec/rspec/mocks/matchers/receive_spec.rb +@@ -141,8 +141,8 @@ def kw_args_method(a:, b:); end + + if RUBY_VERSION.to_f > 3.3 + expect(failure.message) +- .to include('expected: ({:a => 1, :b => 2}) (keyword arguments)') +- .and include('got: ({:a => 1, :b => 2}) (options hash)') ++ .to include('expected: ({a: 1, b: 2}) (keyword arguments)') ++ .and include('got: ({a: 1, b: 2}) (options hash)') + else + expect(failure.message) + .to include('expected: ({:a=>1, :b=>2}) (keyword arguments)') +diff --git a/rspec-mocks/spec/rspec/mocks/verifying_doubles/expected_arg_verification_spec.rb b/rspec-mocks/spec/rspec/mocks/verifying_doubles/expected_arg_verification_spec.rb +index a3f3d2034..48646a1e6 100644 +--- a/rspec-mocks/spec/rspec/mocks/verifying_doubles/expected_arg_verification_spec.rb ++++ b/rspec-mocks/spec/rspec/mocks/verifying_doubles/expected_arg_verification_spec.rb +@@ -134,7 +134,7 @@ module Mocks + it "fails to match against a hash submitted as a positional argument and received as keyword arguments in Ruby 3.0 or later", :reset => true do + messages = + if RUBY_VERSION.to_f > 3.3 +- ["expected: (1, {:optional_arg => 3, :required_arg => 2}) (keyword arguments)", "got: (1, {:optional_arg => 3, :required_arg => 2}) (options hash)"] ++ ["expected: (1, {optional_arg: 3, required_arg: 2}) (keyword arguments)", "got: (1, {optional_arg: 3, required_arg: 2}) (options hash)"] + else + ["expected: (1, {:optional_arg=>3, :required_arg=>2}) (keyword arguments)", "got: (1, {:optional_arg=>3, :required_arg=>2}) (options hash)"] + end + diff --git a/rspec-mocks-pr282-skip-mock-for-ruby4_0-inspect.patch b/rspec-mocks-pr282-skip-mock-for-ruby4_0-inspect.patch new file mode 100644 index 0000000..d1c309b --- /dev/null +++ b/rspec-mocks-pr282-skip-mock-for-ruby4_0-inspect.patch @@ -0,0 +1,35 @@ +From 939c4799993b7ff7e524fac701ae6490772ca6de Mon Sep 17 00:00:00 2001 +From: Jon Rowe +Date: Mon, 1 Dec 2025 14:08:25 +0000 +Subject: [PATCH] Skip mock for calls to `:respond_to?` from `Kernel#inspect` + +--- + rspec-mocks/lib/rspec/mocks/method_double.rb | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/rspec-mocks/lib/rspec/mocks/method_double.rb b/rspec-mocks/lib/rspec/mocks/method_double.rb +index e2edb1e21..3276c49a5 100644 +--- a/rspec-mocks/lib/rspec/mocks/method_double.rb ++++ b/rspec-mocks/lib/rspec/mocks/method_double.rb +@@ -68,8 +68,19 @@ def define_proxy_method + + save_original_implementation_callable! + definition_target.class_exec(self, method_name, @original_visibility || visibility) do |method_double, method_name, visibility| +- define_method(method_name) do |*args, &block| +- method_double.proxy_method_invoked(self, *args, &block) ++ if RUBY_VERSION.to_f > 3 && method_name == :respond_to? ++ define_method(method_name) do |*args, &block| ++ # This is a work around for a respond_to? check within kernel_inspect ++ if caller_locations[0].label == "Kernel#inspect" ++ super(*args, &block) ++ else ++ method_double.proxy_method_invoked(self, *args, &block) ++ end ++ end ++ else ++ define_method(method_name) do |*args, &block| ++ method_double.proxy_method_invoked(self, *args, &block) ++ end + end + # This can't be `if respond_to?(:ruby2_keywords, true)`, + # see https://github.com/rspec/rspec-mocks/pull/1385#issuecomment-755340298 diff --git a/rspec-related-create-full-tarball.sh b/rspec-related-create-full-tarball.sh index a847c6c..c0ba6bf 100644 --- a/rspec-related-create-full-tarball.sh +++ b/rspec-related-create-full-tarball.sh @@ -14,10 +14,9 @@ CURRDIR=$(pwd) TMPDIRPATH=$(mktemp -d /var/tmp/rspec-tar-XXXXXX) pushd $TMPDIRPATH -git clone https://github.com/rspec/$1.git -pushd $1 -git reset --hard v$2 -popd +git clone https://github.com/rspec/rspec.git +pushd rspec +git reset --hard $1-v$2 ln -sf $1 $1-$2 tar czf ${CURRDIR}/rubygem-$1-$2-full.tar.gz $1-$2/./ diff --git a/rubygem-rspec-mocks.spec b/rubygem-rspec-mocks.spec index dea331c..2a2f1da 100644 --- a/rubygem-rspec-mocks.spec +++ b/rubygem-rspec-mocks.spec @@ -1,33 +1,43 @@ -%global majorver 3.9.1 +%global majorver 3.13.7 #%%global preminorver .rc6 %global rpmminorver .%(echo %preminorver | sed -e 's|^\\.\\.*||') %global fullver %{majorver}%{?preminorver} -%global fedorarel 1 +%global baserelease 2 %global gem_name rspec-mocks -%global need_bootstrap_set 0 +%bcond_with bootstrap %undefine __brp_mangle_shebangs Summary: RSpec's 'test double' framework (mocks and stubs) Name: rubygem-%{gem_name} Version: %{majorver} -Release: %{?preminorver:0.}%{fedorarel}%{?preminorver:%{rpmminorver}}%{?dist}.2 +Release: %{?preminorver:0.}%{baserelease}%{?preminorver:%{rpmminorver}}%{?dist} +# SPDX confirmed License: MIT -URL: http://github.com/rspec/rspec-mocks +URL: https://rspec.info Source0: https://rubygems.org/gems/%{gem_name}-%{fullver}.gem # %%{SOURCE2} %%{name} %%{version} Source1: rubygem-%{gem_name}-%{version}-full.tar.gz Source2: rspec-related-create-full-tarball.sh +# https://github.com/rspec/rspec/pull/282/commits/939c4799993b7ff7e524fac701ae6490772ca6de +# Skip mock for ruby4_0 Kernel#inspect +Patch0: rspec-mocks-pr282-skip-mock-for-ruby4_0-inspect.patch -#BuildRequires: ruby(release) BuildRequires: rubygems-devel -%if 0%{?need_bootstrap_set} < 1 +%if %{without bootstrap} +# rspec BuildRequires: rubygem(rspec) -BuildRequires: rubygem(thread_order) +BuildRequires: rubygem(rake) +%if %{undefined rhel} +# cucumber +BuildRequires: rubygem(aruba) +BuildRequires: rubygem(cucumber) +BuildRequires: rubygem(minitest) +%endif BuildRequires: git %endif BuildArch: noarch @@ -48,6 +58,11 @@ This package contains documentation for %{name}. gem unpack %{SOURCE0} %setup -q -D -T -n %{gem_name}-%{version} -b 1 +%patch -P0 -p2 + +# Cucumber 7 syntax change +sed -i cucumber.yml -e "s|~@wip|not @wip|" +sed -i features/support/disallow_certain_apis.rb -e "s|~@allow-old-syntax|not @allow-old-syntax|" gem specification %{SOURCE0} -l --ruby > %{gem_name}.gemspec @@ -63,12 +78,33 @@ cp -a .%{gem_dir}/* \ # cleanups rm -f %{buildroot}%{gem_instdir}/{.document,.yardopts} -%if 0%{?need_bootstrap_set} < 1 %check +%if %{with bootstrap} +# Don't do actual check +exit 0 +%endif + +%if %{defined rhel} +# avoid aruba dep on RHEL, but tests fail if files are removed entirely +echo -n > spec/integration/rails_support_spec.rb +echo -n > spec/support/aruba.rb +%else +# Don't call bundler +sed -i spec/integration/rails_support_spec.rb \ + -e 's|bundle exec rspec|rspec|' +%endif + # library_wide_checks.rb needs UTF-8 LANG=C.UTF-8 -ruby -rrubygems -Ilib/ -S rspec spec/ +export RUBYLIB=$(pwd)/lib +rspec spec/ + +%if 0%{?rhel} +# Don't do cucumber test +exit 0 %endif +export CUCUMBER_PUBLISH_QUIET=true +cucumber %files %dir %{gem_instdir} @@ -86,6 +122,125 @@ ruby -rrubygems -Ilib/ -S rspec spec/ %{gem_docdir} %changelog +* Tue Dec 02 2025 Mamoru TASAKA - 3.13.7-2 +- Backport upstream patch to skip mock for Kernel#inspect on ruby4_0 + +* Mon Nov 24 2025 Mamoru TASAKA - 3.13.7-1 +- 3.13.7 + +* Fri Oct 17 2025 Mamoru TASAKA - 3.13.6-1 +- 3.13.6 + +* Fri Jul 25 2025 Fedora Release Engineering - 3.13.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild + +* Thu May 29 2025 Mamoru TASAKA - 3.13.5-1 +- 3.13.5 + +* Thu May 15 2025 Mamoru TASAKA - 3.13.4-1 +- 3.13.4 + +* Sat Jan 18 2025 Fedora Release Engineering - 3.13.2-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild + +* Sun Dec 29 2024 Mamoru TASAKA - 3.13.2-3 +- Coordinate with rspec-support change wrt ruby34 hash inspect support + +* Wed Nov 06 2024 Mamoru TASAKA - 3.13.2-2 +- Backport upstream patch to support ruby34 formatting + +* Thu Oct 03 2024 Mamoru TASAKA - 3.13.2-1 +- 3.13.2 + +* Fri Jul 19 2024 Fedora Release Engineering - 3.13.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + +* Thu May 09 2024 Mamoru TASAKA - 3.13.1-1 +- 3.13.1 + +* Thu Apr 18 2024 Jun Aruga - 3.13.0-2 +- Remove unused thread_order build dependency + +* Fri Feb 09 2024 Mamoru TASAKA - 3.13.0-1 +- 3.13.0 + +* Fri Jan 26 2024 Fedora Release Engineering - 3.12.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Fri Jul 21 2023 Fedora Release Engineering - 3.12.6-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Sun Jul 16 2023 Mamoru TASAKA - 3.12.6-1 +- 3.12.6 + +* Sat Apr 1 2023 Mamoru TASAKA - 3.12.5-1 +- 3.12.5 + +* Tue Mar 14 2023 Mamoru TASAKA - 3.12.4-1 +- 3.12.4 + +* Thu Mar 09 2023 Yaakov Selkowitz - 3.12.3-2 +- Disable unwanted dependencies in RHEL builds + +* Thu Feb 16 2023 Mamoru TASAKA - 3.12.3-1 +- 3.12.3 + +* Fri Jan 20 2023 Fedora Release Engineering - 3.12.0-3.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Fri Dec 2 2022 Mamoru TASAKA - 3.12.0-3 +- Backport upstream reviewing patch for ruby32 ruby2_keywords treatment change + +* Thu Nov 3 2022 Mamoru TASAKA - 3.12.0-2 +- On Fedora 37, remove "Display keyword hashes" feature for now + (On Fedora 38, this is effective) + +* Thu Oct 27 2022 Mamoru TASAKA - 3.12.0-1 +- 3.12.0 + +* Wed Oct 26 2022 Mamoru TASAKA - 3.11.2-1 +- 3.11.2 + +* Mon Oct 3 2022 Mamoru TASAKA - 3.11.1-2 +- Backport upstream patch for ruby32 wrt method reference changes + +* Sat Jul 23 2022 Fedora Release Engineering - 3.11.1-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Thu Apr 7 2022 Mamoru TASAKA - 3.11.1-1 +- 3.11.1 + +* Thu Feb 10 2022 Mamoru TASAKA - 3.11.0-1 +- 3.11.0 + +* Sun Jan 30 2022 Mamoru TASAKA - 3.10.3-1 +- 3.10.3 + +* Sun Jan 30 2022 Mamoru TASAKA - 3.10.2-3 +- BR: rubygem(rake) for check + +* Thu Jan 20 2022 Mamoru TASAKA - 3.10.2-2 +- Execute cucumber test + +* Fri Jul 23 2021 Fedora Release Engineering - 3.10.2-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Mon Feb 1 2021 Mamoru TASAKA - 3.10.2-1 +- 3.10.2 + +* Wed Jan 27 2021 Fedora Release Engineering - 3.10.1-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Tue Dec 29 2020 Mamoru TASAKA - 3.10.1-1 +- 3.10.1 + +* Fri Dec 11 2020 Mamoru TASAKA - 3.10.0-1 +- Enable tests again + +* Fri Dec 11 2020 Mamoru TASAKA - 3.10.0-0.1 +- 3.10.0 +- Once disable test for bootstrap + * Wed Jul 29 2020 Fedora Release Engineering - 3.9.1-1.2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild diff --git a/sources b/sources index f0f3b15..38528a1 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (rspec-mocks-3.9.1.gem) = 08299764f0d053d96125e3f3542fe16b189a87bcd6f27965f97394608c949dab2767cc2b5ebd9718db24b39e79656261cbec17f755599f5c6de9d5b77e87d877 -SHA512 (rubygem-rspec-mocks-3.9.1-full.tar.gz) = 0e901235d4884c938b7a1a17ff00b6eca87ec262c5647defb846d59aeb1887a72aba3c9b3f54773a3445d03d78b976536a95b7328a880d12956176fb93b04fbf +SHA512 (rspec-mocks-3.13.7.gem) = fa30824f1d7ab82e2c0d1cde1f076cb84b9a9e1e9e7292e33bcfda934468a50f2b59a1dc539137be14ad5b86465ed6fa12c32af2e3a79992c3ce5d278072861c +SHA512 (rubygem-rspec-mocks-3.13.7-full.tar.gz) = 7666b07e6b9806e36d53ede810c6efc0ceb57bc554c96e0fdf44efbfd9dd027a8e999ce942d20bf46f93f93bfae1a88c7ffd0bfbf2cdf08601093a98218a059a