Skip to content

Commit

Permalink
Merge pull request #655 from freerange/fix-has-entry-with-keyword-arg…
Browse files Browse the repository at this point in the history
…s-regression

Fix regression in ParameterMatchers#has_entry, etc
  • Loading branch information
floehopper authored Jul 16, 2024
2 parents 5a3a208 + 3b60b7d commit c216167
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 22 deletions.
5 changes: 0 additions & 5 deletions lib/mocha/parameter_matchers/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@ module Mocha
module ParameterMatchers
# @abstract Subclass and implement +#matches?+ and +#mocha_inspect+ to define a custom matcher. Also add a suitably named instance method to {ParameterMatchers} to build an instance of the new matcher c.f. {#equals}.
class Base
# @private
def to_matcher(_expectation = nil)
self
end

# A shorthand way of combining two matchers when both must match.
#
# Returns a new {AllOf} parameter matcher combining two matchers using a logical AND.
Expand Down
19 changes: 9 additions & 10 deletions lib/mocha/parameter_matchers/instance_methods.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require 'mocha/parameter_matchers/base'
require 'mocha/parameter_matchers/equals'
require 'mocha/parameter_matchers/positional_or_keyword_hash'

Expand All @@ -6,8 +7,14 @@ module ParameterMatchers
# @private
module InstanceMethods
# @private
def to_matcher(_expectation = nil)
Mocha::ParameterMatchers::Equals.new(self)
def to_matcher(expectation: nil, top_level: false)
if is_a?(Base)
self
elsif is_a?(Hash) && top_level
Mocha::ParameterMatchers::PositionalOrKeywordHash.new(self, expectation)
else
Mocha::ParameterMatchers::Equals.new(self)
end
end
end
end
Expand All @@ -17,11 +24,3 @@ def to_matcher(_expectation = nil)
class Object
include Mocha::ParameterMatchers::InstanceMethods
end

# @private
class Hash
# @private
def to_matcher(expectation = nil)
Mocha::ParameterMatchers::PositionalOrKeywordHash.new(self, expectation)
end
end
2 changes: 1 addition & 1 deletion lib/mocha/parameters_matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def mocha_inspect
end

def matchers
@expected_parameters.map { |p| p.to_matcher(@expectation) }
@expected_parameters.map { |p| p.to_matcher(expectation: @expectation, top_level: true) }
end
end
end
18 changes: 18 additions & 0 deletions test/acceptance/keyword_argument_matching_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,24 @@ def test_should_match_keyword_args_with_nested_matcher
assert_passed(test_result)
end

def test_should_match_keyword_args_with_matcher_built_using_keyword_args
test_result = run_as_test do
mock = mock()
mock.expects(:method).with(has_entry(:k1, k2: 'v2'))
mock.method(k1: { k2: 'v2' })
end
assert_passed(test_result)
end

def test_should_not_match_keyword_args_with_matcher_built_using_keyword_args
test_result = run_as_test do
mock = mock()
mock.expects(:method).with(has_entry(:k1, k2: 'v2'))
mock.method(k1: { k2: 'v2', k3: 'v3' })
end
assert_failed(test_result)
end

def test_should_match_last_positional_hash_with_hash_matcher
test_result = run_as_test do
mock = mock()
Expand Down
12 changes: 6 additions & 6 deletions test/unit/parameter_matchers/positional_or_keyword_hash_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ def test_should_match_keyword_args_with_keyword_args
end

def test_should_match_keyword_args_with_matchers_using_keyword_args
matcher = Hash.ruby2_keywords_hash({ key_1: is_a(String), key_2: is_a(Integer) }).to_matcher # rubocop:disable Style/BracesAroundHashParameters
matcher = Hash.ruby2_keywords_hash({ key_1: is_a(String), key_2: is_a(Integer) }).to_matcher(top_level: true) # rubocop:disable Style/BracesAroundHashParameters
assert matcher.matches?([Hash.ruby2_keywords_hash({ key_1: 'foo', key_2: 2 })]) # rubocop:disable Style/BracesAroundHashParameters
end

def test_should_match_hash_arg_with_keyword_args_but_display_deprecation_warning_if_appropriate
expectation = Mocha::Expectation.new(self, :foo); execution_point = ExecutionPoint.current
matcher = Hash.ruby2_keywords_hash({ key_1: 1, key_2: 2 }).to_matcher(expectation) # rubocop:disable Style/BracesAroundHashParameters
matcher = Hash.ruby2_keywords_hash({ key_1: 1, key_2: 2 }).to_matcher(expectation: expectation, top_level: true) # rubocop:disable Style/BracesAroundHashParameters
DeprecationDisabler.disable_deprecations do
assert matcher.matches?([{ key_1: 1, key_2: 2 }])
end
Expand All @@ -58,7 +58,7 @@ def test_should_match_hash_arg_with_keyword_args_but_display_deprecation_warning

def test_should_match_keyword_args_with_hash_arg_but_display_deprecation_warning_if_appropriate
expectation = Mocha::Expectation.new(self, :foo); execution_point = ExecutionPoint.current
matcher = { key_1: 1, key_2: 2 }.to_matcher(expectation)
matcher = { key_1: 1, key_2: 2 }.to_matcher(expectation: expectation, top_level: true)
DeprecationDisabler.disable_deprecations do
assert matcher.matches?([Hash.ruby2_keywords_hash({ key_1: 1, key_2: 2 })]) # rubocop:disable Style/BracesAroundHashParameters
end
Expand Down Expand Up @@ -102,22 +102,22 @@ def test_should_match_keyword_args_with_keyword_args_when_strict_keyword_args_is
end

def test_should_not_match_hash_arg_with_keyword_args_when_strict_keyword_args_is_enabled
matcher = Hash.ruby2_keywords_hash({ key_1: 1, key_2: 2 }).to_matcher # rubocop:disable Style/BracesAroundHashParameters
matcher = Hash.ruby2_keywords_hash({ key_1: 1, key_2: 2 }).to_matcher(top_level: true) # rubocop:disable Style/BracesAroundHashParameters
Mocha::Configuration.override(strict_keyword_argument_matching: true) do
assert !matcher.matches?([{ key_1: 1, key_2: 2 }])
end
end

def test_should_not_match_keyword_args_with_hash_arg_when_strict_keyword_args_is_enabled
matcher = { key_1: 1, key_2: 2 }.to_matcher
matcher = { key_1: 1, key_2: 2 }.to_matcher(top_level: true)
Mocha::Configuration.override(strict_keyword_argument_matching: true) do
assert !matcher.matches?([Hash.ruby2_keywords_hash({ key_1: 1, key_2: 2 })]) # rubocop:disable Style/BracesAroundHashParameters
end
end

def test_should_display_deprecation_warning_even_if_parent_expectation_is_nil
expectation = nil
matcher = { key_1: 1, key_2: 2 }.to_matcher(expectation)
matcher = { key_1: 1, key_2: 2 }.to_matcher(expectation: expectation, top_level: true)
DeprecationDisabler.disable_deprecations do
matcher.matches?([Hash.ruby2_keywords_hash({ key_1: 1, key_2: 2 })]) # rubocop:disable Style/BracesAroundHashParameters
end
Expand Down

0 comments on commit c216167

Please sign in to comment.