Skip to content

Commit

Permalink
Fix an incorrect autocorrect for Minitest/AssertMatch
Browse files Browse the repository at this point in the history
This PR fixes an incorrect autocorrect for `Minitest/AssertMatch`
when `assert` with `match` and RHS is a regexp literal.

A regular expression literal must be the first argument to `assert_match`.
`TypeError: no implicit conversion of Regexp into String` will occur if it is
passed as the second argument.

```ruby
assert_match(object, /regexp/) #=> TypeError: no implicit conversion of Regexp into String
```

This issue was found on faker-ruby/faker#2556.
  • Loading branch information
koic committed Sep 6, 2022
1 parent 4b5c9d6 commit 9460a61
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 5 deletions.
@@ -0,0 +1 @@
* [#181](https://github.com/rubocop/rubocop-minitest/pull/181): Fix an incorrect autocorrect for `Minitest/AssertMatch` when `assert` with `match` and RHS is a regexp literal. ([@koic][])
2 changes: 1 addition & 1 deletion lib/rubocop/cop/minitest/assert_match.rb
Expand Up @@ -18,7 +18,7 @@ module Minitest
class AssertMatch < Base
extend MinitestCopRule

define_rule :assert, target_method: :match
define_rule :assert, target_method: :match, inverse: 'regexp_type?'
end
end
end
Expand Down
14 changes: 10 additions & 4 deletions lib/rubocop/cop/mixin/minitest_cop_rule.rb
Expand Up @@ -19,7 +19,8 @@ module MinitestCopRule
# autocorrection. The preferred method name that connects
# `assertion_method` and `target_method` with `_` is
# the default name.
# @param inverse [Boolean] An optional param. Order of arguments replaced by autocorrection.
# @param inverse [Boolean, String] An optional param. Order of arguments replaced by autocorrection.
# If string is passed, it becomes a predicate method for the first argument node.
# @api private
#
def define_rule(assertion_method, target_method:, preferred_method: nil, inverse: false)
Expand Down Expand Up @@ -78,10 +79,15 @@ def offense_message(arguments)
def new_arguments(arguments)
receiver = correct_receiver(arguments.first.receiver)
method_argument = arguments.first.arguments.first&.source
method_argument = arguments.first.arguments.first
new_arguments = [receiver, method_argument].compact
new_arguments.reverse! if #{inverse}
new_arguments = [receiver, method_argument&.source].compact
inverse_condition = if %w[true false].include?('#{inverse}')
#{inverse}
else
method_argument.#{inverse}
end
new_arguments.reverse! if inverse_condition
new_arguments
end
Expand Down
38 changes: 38 additions & 0 deletions test/rubocop/cop/minitest/assert_match_test.rb
Expand Up @@ -22,6 +22,44 @@ def test_do_something
RUBY
end

def test_registers_offense_when_using_assert_with_match_and_lhs_is_regexp_literal
assert_offense(<<~RUBY)
class FooTest < Minitest::Test
def test_do_something
assert(/regexp/.match(object))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `assert_match(/regexp/, object)`.
end
end
RUBY

assert_correction(<<~RUBY)
class FooTest < Minitest::Test
def test_do_something
assert_match(/regexp/, object)
end
end
RUBY
end

def test_registers_offense_when_using_assert_with_match_and_rhs_is_regexp_literal
assert_offense(<<~RUBY)
class FooTest < Minitest::Test
def test_do_something
assert(object.match(/regexp/))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using `assert_match(/regexp/, object)`.
end
end
RUBY

assert_correction(<<~RUBY)
class FooTest < Minitest::Test
def test_do_something
assert_match(/regexp/, object)
end
end
RUBY
end

def test_registers_offense_when_using_assert_with_match_and_message
assert_offense(<<~RUBY, @cop)
class FooTest < Minitest::Test
Expand Down

0 comments on commit 9460a61

Please sign in to comment.