From b94890bc6794d598cb5b03029edeab3fe694d334 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Mon, 2 Oct 2023 12:56:10 +0900 Subject: [PATCH] Make `Minitest/AssertMatch` aware of `assert_operator` This PR makes `Minitest/AssertMatch` aware of `assert_operator`. --- ...t_assert_match_aware_of_assert_operator.md | 1 + lib/rubocop/cop/minitest/assert_match.rb | 47 +++++++++++++++++-- lib/rubocop/cop/minitest/refute_match.rb | 1 + .../rubocop/cop/minitest/assert_match_test.rb | 39 +++++++++++---- 4 files changed, 76 insertions(+), 12 deletions(-) create mode 100644 changelog/new_make_minitest_assert_match_aware_of_assert_operator.md diff --git a/changelog/new_make_minitest_assert_match_aware_of_assert_operator.md b/changelog/new_make_minitest_assert_match_aware_of_assert_operator.md new file mode 100644 index 00000000..fb908759 --- /dev/null +++ b/changelog/new_make_minitest_assert_match_aware_of_assert_operator.md @@ -0,0 +1 @@ +* [#268](https://github.com/rubocop/rubocop-minitest/pull/268): Make `Minitest/AssertMatch` aware of `assert_operator`. ([@koic][]) diff --git a/lib/rubocop/cop/minitest/assert_match.rb b/lib/rubocop/cop/minitest/assert_match.rb index 3ab38390..9c39f958 100644 --- a/lib/rubocop/cop/minitest/assert_match.rb +++ b/lib/rubocop/cop/minitest/assert_match.rb @@ -11,6 +11,7 @@ module Minitest # assert(matcher.match(string)) # assert(matcher.match?(string)) # assert(matcher =~ string) + # assert_operator(matcher, :=~, string) # assert(matcher.match(string), 'message') # # # good @@ -18,10 +19,50 @@ module Minitest # assert_match(matcher, string, 'message') # class AssertMatch < Base - extend MinitestCopRule + include ArgumentRangeHelper + extend AutoCorrector - define_rule :assert, target_method: %i[match match? =~], - preferred_method: :assert_match, inverse: 'regexp_type?' + MSG = 'Prefer using `assert_match(%s)`.' + RESTRICT_ON_SEND = %i[assert assert_operator].freeze + + def_node_matcher :assert_match, <<~PATTERN + { + (send nil? :assert (send $_ {:match :match? :=~} $_) $...) + (send nil? :assert_operator $_ (sym :=~) $_ $...) + } + PATTERN + + # rubocop:disable Metrics/AbcSize + def on_send(node) + assert_match(node) do |expected, actual, rest_args| + basic_arguments = order_expected_and_actual(expected, actual) + preferred = (message_arg = rest_args.first) ? "#{basic_arguments}, #{message_arg.source}" : basic_arguments + message = format(MSG, preferred: preferred) + + add_offense(node, message: message) do |corrector| + corrector.replace(node.loc.selector, 'assert_match') + + range = if node.method?(:assert) + node.first_argument + else + node.first_argument.source_range.begin.join(node.arguments[2].source_range.end) + end + + corrector.replace(range, basic_arguments) + end + end + end + # rubocop:enable Metrics/AbcSize + + private + + def order_expected_and_actual(expected, actual) + if actual.regexp_type? + [actual, expected] + else + [expected, actual] + end.map(&:source).join(', ') + end end end end diff --git a/lib/rubocop/cop/minitest/refute_match.rb b/lib/rubocop/cop/minitest/refute_match.rb index bdc6822c..e372de12 100644 --- a/lib/rubocop/cop/minitest/refute_match.rb +++ b/lib/rubocop/cop/minitest/refute_match.rb @@ -11,6 +11,7 @@ module Minitest # refute(matcher.match(string)) # refute(matcher.match?(string)) # refute(matcher =~ string) + # refute_operator(matcher, :=~, string) # refute(matcher.match(string), 'message') # # # good diff --git a/test/rubocop/cop/minitest/assert_match_test.rb b/test/rubocop/cop/minitest/assert_match_test.rb index b7edba0e..dce3e9dc 100644 --- a/test/rubocop/cop/minitest/assert_match_test.rb +++ b/test/rubocop/cop/minitest/assert_match_test.rb @@ -105,24 +105,35 @@ def test_do_something RUBY end + # Redundant parentheses should be removed by `Style/RedundantParentheses` cop. define_method("test_registers_offense_when_using_assert_with_#{matcher}_in_redundant_parentheses") do - assert_offense(<<~RUBY, matcher: matcher) + assert_no_offenses(<<~RUBY, matcher: matcher) class FooTest < Minitest::Test def test_do_something assert((matcher.#{matcher}(string))) - ^^^^^^^^^^^^^^^^^{matcher}^^^^^^^^^^ Prefer using `assert_match(matcher, string)`. end end RUBY + end + end - assert_correction(<<~RUBY) - class FooTest < Minitest::Test - def test_do_something - assert_match((matcher, string)) - end + def test_registers_offense_when_using_assert_operator_with_match_operator + assert_offense(<<~RUBY) + class FooTest < Minitest::Test + def test_do_something + assert_operator(matcher, :=~, object) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `assert_match(matcher, object)`. end - RUBY - end + end + RUBY + + assert_correction(<<~RUBY) + class FooTest < Minitest::Test + def test_do_something + assert_match(matcher, object) + end + end + RUBY end def test_does_not_register_offense_when_using_assert_match @@ -154,4 +165,14 @@ def test_do_something end RUBY end + + def test_does_not_register_offense_when_using_assert_operator_with_mismatch_operator + assert_no_offenses(<<~RUBY) + class FooTest < Minitest::Test + def test_do_something + assert_operator(matcher, :!~, object) + end + end + RUBY + end end