Skip to content

Commit

Permalink
Deprecate hash args that won't strictly match
Browse files Browse the repository at this point in the history
  • Loading branch information
floehopper committed Oct 14, 2022
1 parent c294fe7 commit a8555d8
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 12 deletions.
25 changes: 21 additions & 4 deletions lib/mocha/parameter_matchers/positional_or_keyword_hash.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'mocha/configuration'
require 'mocha/deprecation'
require 'mocha/parameter_matchers/base'

module Mocha
Expand All @@ -9,14 +10,24 @@ def initialize(value)
@value = value
end

def matches?(available_parameters)
def matches?(available_parameters) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
parameter, is_last_parameter = extract_parameter(available_parameters)
return false unless parameter.is_a?(Hash)
return false unless parameter == @value

if is_last_parameter && Mocha.configuration.strict_keyword_argument_matching?
return false unless ::Hash.ruby2_keywords_hash?(parameter) == ::Hash.ruby2_keywords_hash?(@value)
if is_last_parameter && (::Hash.ruby2_keywords_hash?(parameter) != ::Hash.ruby2_keywords_hash?(@value))
return false if Mocha.configuration.strict_keyword_argument_matching?

if Mocha::RUBY_V27_PLUS
if ::Hash.ruby2_keywords_hash?(@value)
deprecation_warning("Expected keyword arguments (#{mocha_inspect}), but received positional hash (#{parameter.mocha_inspect}).")
else
deprecation_warning("Expected positional hash (#{mocha_inspect}), but received keyword arguments (#{parameter.mocha_inspect}).")
end
end
end
parameter == @value

true
end

def mocha_inspect
Expand All @@ -28,6 +39,12 @@ def mocha_inspect
def extract_parameter(available_parameters)
[available_parameters.shift, available_parameters.empty?]
end

def deprecation_warning(details)
sentence1 = 'These will stop matching when strict keyword argument matching is enabled.'
sentence2 = 'See the documentation for Mocha::Configuration#strict_keyword_argument_matching=.'
Deprecation.warning([details, sentence1, sentence2].join(' '))
end
end
end
end
18 changes: 14 additions & 4 deletions test/acceptance/keyword_argument_matching_test.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
require File.expand_path('../acceptance_test_helper', __FILE__)

require 'deprecation_disabler'

class KeywordArgumentMatchingTest < Mocha::TestCase
include AcceptanceTest

Expand All @@ -15,7 +17,9 @@ def test_should_match_hash_parameter_with_keyword_args
test_result = run_as_test do
mock = mock()
mock.expects(:method).with(:key => 42)
mock.method({ :key => 42 }) # rubocop:disable Style/BracesAroundHashParameters
DeprecationDisabler.disable_deprecations do
mock.method({ :key => 42 }) # rubocop:disable Style/BracesAroundHashParameters
end
end
assert_passed(test_result)
end
Expand All @@ -37,7 +41,9 @@ def test_should_match_hash_parameter_with_splatted_keyword_args
test_result = run_as_test do
mock = mock()
mock.expects(:method).with(**{ :key => 42 })
mock.method({ :key => 42 }) # rubocop:disable Style/BracesAroundHashParameters
DeprecationDisabler.disable_deprecations do
mock.method({ :key => 42 }) # rubocop:disable Style/BracesAroundHashParameters
end
end
assert_passed(test_result)
end
Expand Down Expand Up @@ -77,7 +83,9 @@ def test_should_match_positional_and_keyword_args_with_last_positional_hash
test_result = run_as_test do
mock = mock()
mock.expects(:method).with(1, { :key => 42 }) # rubocop:disable Style/BracesAroundHashParameters
mock.method(1, :key => 42)
DeprecationDisabler.disable_deprecations do
mock.method(1, :key => 42)
end
end
assert_passed(test_result)
end
Expand All @@ -99,7 +107,9 @@ def test_should_match_last_positional_hash_with_keyword_args
test_result = run_as_test do
mock = mock()
mock.expects(:method).with(1, :key => 42)
mock.method(1, { :key => 42 }) # rubocop:disable Style/BracesAroundHashParameters
DeprecationDisabler.disable_deprecations do
mock.method(1, { :key => 42 }) # rubocop:disable Style/BracesAroundHashParameters
end
end
assert_passed(test_result)
end
Expand Down
25 changes: 21 additions & 4 deletions test/unit/parameter_matchers/positional_or_keyword_hash_test.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require File.expand_path('../../../test_helper', __FILE__)

require 'deprecation_disabler'
require 'mocha/parameter_matchers/positional_or_keyword_hash'
require 'mocha/parameter_matchers/instance_methods'
require 'mocha/inspect'
Expand Down Expand Up @@ -32,14 +33,30 @@ def test_should_match_keyword_args_with_keyword_args
assert matcher.matches?([Hash.ruby2_keywords_hash({ :key_1 => 1, :key_2 => 2 })]) # rubocop:disable Style/BracesAroundHashParameters
end

def test_should_match_hash_arg_with_keyword_args
def test_should_match_hash_arg_with_keyword_args_but_display_deprecation_warning_if_appropriate
matcher = Hash.ruby2_keywords_hash({ :key_1 => 1, :key_2 => 2 }).to_matcher # rubocop:disable Style/BracesAroundHashParameters
assert matcher.matches?([{ :key_1 => 1, :key_2 => 2 }])
DeprecationDisabler.disable_deprecations do
assert matcher.matches?([{ :key_1 => 1, :key_2 => 2 }])
end
return unless Mocha::RUBY_V27_PLUS

message = Mocha::Deprecation.messages.last
assert_includes message, 'Expected keyword arguments (:key_1 => 1, :key_2 => 2), but received positional hash ({:key_1 => 1, :key_2 => 2}).'
assert_includes message, 'These will stop matching when strict keyword argument matching is enabled.'
assert_includes message, 'See the documentation for Mocha::Configuration#strict_keyword_argument_matching=.'
end

def test_should_match_keyword_args_with_hash_arg
def test_should_match_keyword_args_with_hash_arg_but_display_deprecation_warning_if_appropriate
matcher = { :key_1 => 1, :key_2 => 2 }.to_matcher
assert matcher.matches?([Hash.ruby2_keywords_hash({ :key_1 => 1, :key_2 => 2 })]) # rubocop:disable Style/BracesAroundHashParameters
DeprecationDisabler.disable_deprecations do
assert matcher.matches?([Hash.ruby2_keywords_hash({ :key_1 => 1, :key_2 => 2 })]) # rubocop:disable Style/BracesAroundHashParameters
end
return unless Mocha::RUBY_V27_PLUS

message = Mocha::Deprecation.messages.last
assert_includes message, 'Expected positional hash ({:key_1 => 1, :key_2 => 2}), but received keyword arguments (:key_1 => 1, :key_2 => 2).'
assert_includes message, 'These will stop matching when strict keyword argument matching is enabled.'
assert_includes message, 'See the documentation for Mocha::Configuration#strict_keyword_argument_matching=.'
end

if Mocha::RUBY_V27_PLUS
Expand Down

0 comments on commit a8555d8

Please sign in to comment.