Skip to content

Commit

Permalink
[Fix rubocop#142] Minitest/GlobalExpectations: add EnforcedStyle co…
Browse files Browse the repository at this point in the history
…nfig parameter

Add a new configuration value for Minitest/GlobalExpectations: EnforcedStyle.
This value sets the allowed and preferred method(s) with which to detect and
correct errors.

Fixes rubocop#142
  • Loading branch information
gi committed Oct 19, 2021
1 parent cefaaa3 commit ce089d2
Show file tree
Hide file tree
Showing 6 changed files with 354 additions and 94 deletions.
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ Metrics/BlockLength:
- '**/*.rake'
- 'test/**/*.rb'

Metrics/MethodLength:
CountAsOne: ['array', 'hash', 'heredoc']

Naming/FileName:
Exclude:
- lib/rubocop-minitest.rb
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* [#142](https://github.com/rubocop/rubocop-minitest/issues/142): Fix `Minitest/GlobalExpectations` autocorrect when receiver is lambda. ([@gi][])
### New features

* [#148](https://github.com/rubocop/rubocop-minitest/pull/148): `Minitest/GlobalExpectations`: add `PreferredMethod` config value. ([@gi][])
* [#147](https://github.com/rubocop/rubocop-minitest/issues/147): Add `EnforcedStyle` config parameter for `Minitest/GlobalExpectations`. ([@gi][])

## 0.15.2 (2021-10-11)

Expand Down
7 changes: 6 additions & 1 deletion config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,12 @@ Minitest/GlobalExpectations:
Description: 'This cop checks for deprecated global expectations.'
StyleGuide: 'https://minitest.rubystyle.guide#global-expectations'
Enabled: true
PreferredMethod: _
EnforcedStyle: any
SupportedStyles:
- _
- any
- expect
- value
VersionAdded: '0.7'

Minitest/LiteralAsActualArgument:
Expand Down
59 changes: 53 additions & 6 deletions docs/modules/ROOT/pages/cops_minitest.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ and autocorrects them to use expect format.

=== Examples

==== PreferredMethod: _ (default)
==== EnforcedStyle: _

[source,ruby]
----
Expand All @@ -536,13 +536,44 @@ musts.must_equal expected_musts
wonts.wont_match expected_wonts
musts.must_raise TypeError
expect(musts).must_equal expected_musts
expect(wonts).wont_match expected_wonts
expect { musts }.must_raise TypeError
value(musts).must_equal expected_musts
value(wonts).wont_match expected_wonts
value { musts }.must_raise TypeError
# good
_(musts).must_equal expected_musts
_(wonts).wont_match expected_wonts
_ { musts }.must_raise TypeError
----

==== PreferredMethod: expect
==== EnforcedStyle: all (default)

[source,ruby]
----
# bad
musts.must_equal expected_musts
wonts.wont_match expected_wonts
musts.must_raise TypeError
# good
_(musts).must_equal expected_musts
_(wonts).wont_match expected_wonts
_ { musts }.must_raise TypeError
expect(musts).must_equal expected_musts
expect(wonts).wont_match expected_wonts
expect { musts }.must_raise TypeError
value(musts).must_equal expected_musts
value(wonts).wont_match expected_wonts
value { musts }.must_raise TypeError
----

==== EnforcedStyle: expect

[source,ruby]
----
Expand All @@ -551,13 +582,21 @@ musts.must_equal expected_musts
wonts.wont_match expected_wonts
musts.must_raise TypeError
_(musts).must_equal expected_musts
_(wonts).wont_match expected_wonts
_ { musts }.must_raise TypeError
value(musts).must_equal expected_musts
value(wonts).wont_match expected_wonts
value { musts }.must_raise TypeError
# good
expect(musts).must_equal expected_musts
expect(wonts).wont_match expected_wonts
expect { musts }.must_raise TypeError
----

==== PreferredMethod: value
==== EnforcedStyle: value

[source,ruby]
----
Expand All @@ -566,6 +605,14 @@ musts.must_equal expected_musts
wonts.wont_match expected_wonts
musts.must_raise TypeError
_(musts).must_equal expected_musts
_(wonts).wont_match expected_wonts
_ { musts }.must_raise TypeError
expect(musts).must_equal expected_musts
expect(wonts).wont_match expected_wonts
expect { musts }.must_raise TypeError
# good
value(musts).must_equal expected_musts
value(wonts).wont_match expected_wonts
Expand All @@ -577,9 +624,9 @@ value { musts }.must_raise TypeError
|===
| Name | Default value | Configurable values

| PreferredMethod
| `_`
| String
| EnforcedStyle
| `any`
| `_`, `any`, `expect`, `value`
|===

=== References
Expand Down
115 changes: 82 additions & 33 deletions lib/rubocop/cop/minitest/global_expectations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,26 @@ module Minitest
# This cop checks for deprecated global expectations
# and autocorrects them to use expect format.
#
# @example PreferredMethod: _ (default)
# @example EnforcedStyle: _
# # bad
# musts.must_equal expected_musts
# wonts.wont_match expected_wonts
# musts.must_raise TypeError
#
# expect(musts).must_equal expected_musts
# expect(wonts).wont_match expected_wonts
# expect { musts }.must_raise TypeError
#
# value(musts).must_equal expected_musts
# value(wonts).wont_match expected_wonts
# value { musts }.must_raise TypeError
#
# # good
# _(musts).must_equal expected_musts
# _(wonts).wont_match expected_wonts
# _ { musts }.must_raise TypeError
#
# @example EnforcedStyle: all (default)
# # bad
# musts.must_equal expected_musts
# wonts.wont_match expected_wonts
Expand All @@ -17,28 +36,53 @@ module Minitest
# _(wonts).wont_match expected_wonts
# _ { musts }.must_raise TypeError
#
# @example PreferredMethod: expect
# expect(musts).must_equal expected_musts
# expect(wonts).wont_match expected_wonts
# expect { musts }.must_raise TypeError
#
# value(musts).must_equal expected_musts
# value(wonts).wont_match expected_wonts
# value { musts }.must_raise TypeError
#
# @example EnforcedStyle: expect
# # bad
# musts.must_equal expected_musts
# wonts.wont_match expected_wonts
# musts.must_raise TypeError
#
# _(musts).must_equal expected_musts
# _(wonts).wont_match expected_wonts
# _ { musts }.must_raise TypeError
#
# value(musts).must_equal expected_musts
# value(wonts).wont_match expected_wonts
# value { musts }.must_raise TypeError
#
# # good
# expect(musts).must_equal expected_musts
# expect(wonts).wont_match expected_wonts
# expect { musts }.must_raise TypeError
#
# @example PreferredMethod: value
# @example EnforcedStyle: value
# # bad
# musts.must_equal expected_musts
# wonts.wont_match expected_wonts
# musts.must_raise TypeError
#
# _(musts).must_equal expected_musts
# _(wonts).wont_match expected_wonts
# _ { musts }.must_raise TypeError
#
# expect(musts).must_equal expected_musts
# expect(wonts).wont_match expected_wonts
# expect { musts }.must_raise TypeError
#
# # good
# value(musts).must_equal expected_musts
# value(wonts).wont_match expected_wonts
# value { musts }.must_raise TypeError
class GlobalExpectations < Base
include ConfigurableEnforcedStyle
extend AutoCorrector

MSG = 'Use `%<preferred>s` instead.'
Expand All @@ -56,50 +100,55 @@ class GlobalExpectations < Base

RESTRICT_ON_SEND = VALUE_MATCHERS + BLOCK_MATCHERS

VALUE_MATCHERS_STR = VALUE_MATCHERS.map do |m|
":#{m}"
end.join(' ').freeze
# There are aliases for the `_` method - `expect` and `value`
DSL_METHODS = %i[_ expect value].freeze

BLOCK_MATCHERS_STR = BLOCK_MATCHERS.map do |m|
":#{m}"
end.join(' ').freeze
def on_send(node)
receiver = node.receiver
return unless receiver

# There are aliases for the `_` method - `expect` and `value`
DSL_METHODS_LIST = %w[_ value expect].map do |n|
":#{n}"
end.join(' ').freeze
method = block_receiver?(receiver) || value_receiver?(receiver)
return if method == preferred_method || (method && style == :any)

add_offense(node, method)
end

private

def_node_matcher :value_global_expectation?, <<~PATTERN
(send !(send nil? {#{DSL_METHODS_LIST}} _) {#{VALUE_MATCHERS_STR}} ...)
def_node_matcher :block_receiver?, <<~PATTERN
(block (send nil? $#method_allowed?) _ _)
PATTERN

def_node_matcher :block_global_expectation?, <<~PATTERN
(send
[
!(send nil? {#{DSL_METHODS_LIST}} _)
!(block (send nil? {#{DSL_METHODS_LIST}}) _ _)
]
{#{BLOCK_MATCHERS_STR}}
_
)
def_node_matcher :value_receiver?, <<~PATTERN
(send nil? $#method_allowed? _)
PATTERN

def on_send(node)
return unless value_global_expectation?(node) || block_global_expectation?(node)
def add_offense(node, method)
receiver = node.receiver

message = format(MSG, preferred: preferred_receiver(node))
if method
message = format(MSG, preferred: preferred_method)

add_offense(node.receiver, message: message) do |corrector|
receiver = node.receiver
replacement = preferred_receiver(node)
corrector.replace(receiver, replacement)
super(receiver, message: message) do |corrector|
replacement = receiver.source.sub(method.to_s, preferred_method.to_s)
corrector.replace(receiver, replacement)
end
else
message = format(MSG, preferred: preferred_receiver(node))

super(receiver, message: message) do |corrector|
replacement = preferred_receiver(node)
corrector.replace(receiver, replacement)
end
end
end

private
def method_allowed?(method)
DSL_METHODS.include?(method)
end

def preferred_method
:_
style == :any ? :_ : style
end

def preferred_receiver(node)
Expand Down
Loading

0 comments on commit ce089d2

Please sign in to comment.