rubocop-rspec 1.42.0 → 1.44.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +44 -2
- data/config/default.yml +41 -3
- data/lib/rubocop-rspec.rb +2 -1
- data/lib/rubocop/cop/rspec/align_left_let_brace.rb +1 -1
- data/lib/rubocop/cop/rspec/align_right_let_brace.rb +1 -1
- data/lib/rubocop/cop/rspec/any_instance.rb +1 -1
- data/lib/rubocop/cop/rspec/around_block.rb +2 -2
- data/lib/rubocop/cop/rspec/base.rb +76 -0
- data/lib/rubocop/cop/rspec/be.rb +1 -1
- data/lib/rubocop/cop/rspec/be_eql.rb +1 -1
- data/lib/rubocop/cop/rspec/before_after_all.rb +1 -1
- data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +1 -1
- data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +6 -3
- data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +1 -1
- data/lib/rubocop/cop/rspec/context_method.rb +2 -2
- data/lib/rubocop/cop/rspec/context_wording.rb +3 -3
- data/lib/rubocop/cop/rspec/cop.rb +2 -66
- data/lib/rubocop/cop/rspec/describe_class.rb +40 -30
- data/lib/rubocop/cop/rspec/describe_method.rb +14 -6
- data/lib/rubocop/cop/rspec/describe_symbol.rb +2 -2
- data/lib/rubocop/cop/rspec/described_class.rb +2 -2
- data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +1 -1
- data/lib/rubocop/cop/rspec/dialect.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_example_group.rb +124 -6
- data/lib/rubocop/cop/rspec/empty_hook.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_line_after_example.rb +4 -8
- data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +4 -8
- data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +7 -10
- data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +4 -8
- data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +5 -8
- data/lib/rubocop/cop/rspec/example_length.rb +1 -1
- data/lib/rubocop/cop/rspec/example_without_description.rb +1 -1
- data/lib/rubocop/cop/rspec/example_wording.rb +4 -4
- data/lib/rubocop/cop/rspec/expect_actual.rb +1 -1
- data/lib/rubocop/cop/rspec/expect_change.rb +1 -1
- data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
- data/lib/rubocop/cop/rspec/expect_output.rb +1 -1
- data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +3 -3
- data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +10 -6
- data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +1 -1
- data/lib/rubocop/cop/rspec/file_path.rb +25 -17
- data/lib/rubocop/cop/rspec/focus.rb +7 -11
- data/lib/rubocop/cop/rspec/hook_argument.rb +5 -6
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +1 -1
- data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +2 -3
- data/lib/rubocop/cop/rspec/implicit_expect.rb +1 -1
- data/lib/rubocop/cop/rspec/implicit_subject.rb +8 -6
- data/lib/rubocop/cop/rspec/instance_spy.rb +1 -1
- data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
- data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +1 -1
- data/lib/rubocop/cop/rspec/it_behaves_like.rb +1 -1
- data/lib/rubocop/cop/rspec/iterated_expectation.rb +1 -1
- data/lib/rubocop/cop/rspec/leading_subject.rb +24 -17
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +1 -1
- data/lib/rubocop/cop/rspec/let_before_examples.rb +1 -1
- data/lib/rubocop/cop/rspec/let_setup.rb +6 -3
- data/lib/rubocop/cop/rspec/message_chain.rb +1 -1
- data/lib/rubocop/cop/rspec/message_expectation.rb +1 -1
- data/lib/rubocop/cop/rspec/message_spies.rb +1 -1
- data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +1 -1
- data/lib/rubocop/cop/rspec/multiple_describes.rb +11 -8
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +7 -11
- data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +148 -0
- data/lib/rubocop/cop/rspec/multiple_subjects.rb +1 -1
- data/lib/rubocop/cop/rspec/named_subject.rb +1 -1
- data/lib/rubocop/cop/rspec/nested_groups.rb +4 -4
- data/lib/rubocop/cop/rspec/not_to_not.rb +1 -1
- data/lib/rubocop/cop/rspec/overwriting_setup.rb +1 -1
- data/lib/rubocop/cop/rspec/pending.rb +1 -1
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +7 -14
- data/lib/rubocop/cop/rspec/rails/http_status.rb +1 -1
- data/lib/rubocop/cop/rspec/receive_counts.rb +1 -1
- data/lib/rubocop/cop/rspec/receive_never.rb +2 -2
- data/lib/rubocop/cop/rspec/repeated_description.rb +1 -1
- data/lib/rubocop/cop/rspec/repeated_example.rb +2 -2
- data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +1 -1
- data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +1 -1
- data/lib/rubocop/cop/rspec/repeated_include_example.rb +103 -0
- data/lib/rubocop/cop/rspec/return_from_stub.rb +1 -1
- data/lib/rubocop/cop/rspec/scattered_let.rb +1 -1
- data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
- data/lib/rubocop/cop/rspec/shared_context.rb +1 -1
- data/lib/rubocop/cop/rspec/shared_examples.rb +1 -1
- data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +1 -1
- data/lib/rubocop/cop/rspec/stubbed_mock.rb +172 -0
- data/lib/rubocop/cop/rspec/subject_stub.rb +6 -6
- data/lib/rubocop/cop/rspec/unspecified_exception.rb +1 -1
- data/lib/rubocop/cop/rspec/variable_definition.rb +6 -6
- data/lib/rubocop/cop/rspec/variable_name.rb +28 -9
- data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -1
- data/lib/rubocop/cop/rspec/void_expect.rb +1 -1
- data/lib/rubocop/cop/rspec/yield.rb +1 -1
- data/lib/rubocop/cop/rspec_cops.rb +3 -0
- data/lib/rubocop/rspec/corrector/move_node.rb +7 -5
- data/lib/rubocop/rspec/description_extractor.rb +1 -1
- data/lib/rubocop/rspec/{blank_line_separation.rb → empty_line_separation.rb} +13 -2
- data/lib/rubocop/rspec/example_group.rb +2 -2
- data/lib/rubocop/rspec/hook.rb +1 -5
- data/lib/rubocop/rspec/language.rb +12 -5
- data/lib/rubocop/rspec/language/node_pattern.rb +6 -1
- data/lib/rubocop/rspec/top_level_describe.rb +2 -2
- data/lib/rubocop/rspec/top_level_group.rb +26 -13
- data/lib/rubocop/rspec/variable.rb +1 -1
- data/lib/rubocop/rspec/version.rb +1 -1
- metadata +38 -6
@@ -208,18 +208,20 @@ module RuboCop
|
|
208
208
|
'is_a?'
|
209
209
|
when 'be_an_instance_of', 'be_instance_of', 'an_instance_of'
|
210
210
|
'instance_of?'
|
211
|
-
when 'include'
|
212
|
-
|
211
|
+
when 'include'
|
212
|
+
'include?'
|
213
|
+
when 'respond_to'
|
214
|
+
'respond_to?'
|
213
215
|
when /^have_(.+)/
|
214
216
|
"has_#{Regexp.last_match(1)}?"
|
215
217
|
else
|
216
|
-
matcher[/^be_(.+)/, 1]
|
218
|
+
"#{matcher[/^be_(.+)/, 1]}?"
|
217
219
|
end
|
218
220
|
end
|
219
221
|
# rubocop:enable Metrics/MethodLength
|
220
222
|
|
221
223
|
def replacement_matcher(node)
|
222
|
-
case [cop_config['Strict'], node.
|
224
|
+
case [cop_config['Strict'], node.method?(:to)]
|
223
225
|
when [true, true]
|
224
226
|
'be(true)'
|
225
227
|
when [true, false]
|
@@ -269,7 +271,7 @@ module RuboCop
|
|
269
271
|
#
|
270
272
|
# # good - the above code is rewritten to it by this cop
|
271
273
|
# expect(foo.something?).to be_truthy
|
272
|
-
class PredicateMatcher <
|
274
|
+
class PredicateMatcher < Base
|
273
275
|
extend AutoCorrector
|
274
276
|
include ConfigurableEnforcedStyle
|
275
277
|
include InflectedHelper
|
@@ -288,15 +290,6 @@ module RuboCop
|
|
288
290
|
check_explicit(node) if style == :explicit
|
289
291
|
end
|
290
292
|
|
291
|
-
def autocorrect(node)
|
292
|
-
case style
|
293
|
-
when :inflected
|
294
|
-
autocorrect_inflected(node)
|
295
|
-
when :explicit
|
296
|
-
autocorrect_explicit(node)
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
293
|
private
|
301
294
|
|
302
295
|
# returns args location with whitespace
|
@@ -23,7 +23,7 @@ module RuboCop
|
|
23
23
|
# expect(foo).to receive(:bar).at_most(:once)
|
24
24
|
# expect(foo).to receive(:bar).at_most(:twice).times
|
25
25
|
#
|
26
|
-
class ReceiveCounts <
|
26
|
+
class ReceiveCounts < Base
|
27
27
|
extend AutoCorrector
|
28
28
|
|
29
29
|
MSG = 'Use `%<alternative>s` instead of `%<original>s`.'
|
@@ -13,14 +13,14 @@ module RuboCop
|
|
13
13
|
# # good
|
14
14
|
# expect(foo).not_to receive(:bar)
|
15
15
|
#
|
16
|
-
class ReceiveNever <
|
16
|
+
class ReceiveNever < Base
|
17
17
|
extend AutoCorrector
|
18
18
|
MSG = 'Use `not_to receive` instead of `never`.'
|
19
19
|
|
20
20
|
def_node_search :method_on_stub?, '(send nil? :receive ...)'
|
21
21
|
|
22
22
|
def on_send(node)
|
23
|
-
return unless node.
|
23
|
+
return unless node.method?(:never) && method_on_stub?(node)
|
24
24
|
|
25
25
|
add_offense(node.loc.selector) do |corrector|
|
26
26
|
autocorrect(corrector, node)
|
@@ -15,7 +15,7 @@ module RuboCop
|
|
15
15
|
# expect(user).to be_valid
|
16
16
|
# end
|
17
17
|
#
|
18
|
-
class RepeatedExample <
|
18
|
+
class RepeatedExample < Base
|
19
19
|
MSG = "Don't repeat examples within an example group."
|
20
20
|
|
21
21
|
def on_block(node)
|
@@ -41,7 +41,7 @@ module RuboCop
|
|
41
41
|
def example_signature(example)
|
42
42
|
key_parts = [example.metadata, example.implementation]
|
43
43
|
|
44
|
-
if example.definition.
|
44
|
+
if example.definition.method?(:its)
|
45
45
|
key_parts << example.definition.arguments
|
46
46
|
end
|
47
47
|
|
@@ -43,7 +43,7 @@ module RuboCop
|
|
43
43
|
# it { is_expected.to respond_to :each }
|
44
44
|
# end
|
45
45
|
#
|
46
|
-
class RepeatedExampleGroupBody <
|
46
|
+
class RepeatedExampleGroupBody < Base
|
47
47
|
MSG = 'Repeated %<group>s block body on line(s) %<loc>s'
|
48
48
|
|
49
49
|
def_node_matcher :several_example_groups?, <<-PATTERN
|
@@ -43,7 +43,7 @@ module RuboCop
|
|
43
43
|
# # example group
|
44
44
|
# end
|
45
45
|
#
|
46
|
-
class RepeatedExampleGroupDescription <
|
46
|
+
class RepeatedExampleGroupDescription < Base
|
47
47
|
MSG = 'Repeated %<group>s block description on line(s) %<loc>s'
|
48
48
|
|
49
49
|
def_node_matcher :several_example_groups?, <<-PATTERN
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Check for repeated include of shared examples.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
# describe 'foo' do
|
12
|
+
# include_examples 'cool stuff'
|
13
|
+
# include_examples 'cool stuff'
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# # bad
|
17
|
+
# describe 'foo' do
|
18
|
+
# it_behaves_like 'a cool', 'thing'
|
19
|
+
# it_behaves_like 'a cool', 'thing'
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # bad
|
23
|
+
# context 'foo' do
|
24
|
+
# it_should_behave_like 'a duck'
|
25
|
+
# it_should_behave_like 'a duck'
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# # good
|
29
|
+
# describe 'foo' do
|
30
|
+
# include_examples 'cool stuff'
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# describe 'bar' do
|
34
|
+
# include_examples 'cool stuff'
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# # good
|
38
|
+
# describe 'foo' do
|
39
|
+
# it_behaves_like 'a cool', 'thing'
|
40
|
+
# it_behaves_like 'a cool', 'person'
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# # good
|
44
|
+
# context 'foo' do
|
45
|
+
# it_should_behave_like 'a duck'
|
46
|
+
# it_should_behave_like 'a goose'
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
class RepeatedIncludeExample < Base
|
50
|
+
MSG = 'Repeated include of shared_examples %<name>s ' \
|
51
|
+
'on line(s) %<repeat>s'
|
52
|
+
|
53
|
+
def_node_matcher :several_include_examples?, <<-PATTERN
|
54
|
+
(begin <#include_examples? #include_examples? ...>)
|
55
|
+
PATTERN
|
56
|
+
|
57
|
+
def_node_matcher :include_examples?, Includes::EXAMPLES.send_pattern
|
58
|
+
|
59
|
+
def_node_matcher :shared_examples_name, <<-PATTERN
|
60
|
+
(send _ #{Includes::EXAMPLES.node_pattern_union} $_ ...)
|
61
|
+
PATTERN
|
62
|
+
|
63
|
+
def on_begin(node)
|
64
|
+
return unless several_include_examples?(node)
|
65
|
+
|
66
|
+
repeated_include_examples(node).each do |item, repeats|
|
67
|
+
add_offense(item, message: message(item, repeats))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def repeated_include_examples(node)
|
74
|
+
node
|
75
|
+
.children
|
76
|
+
.select { |child| literal_include_examples?(child) }
|
77
|
+
.group_by { |child| signature_keys(child) }
|
78
|
+
.values
|
79
|
+
.reject(&:one?)
|
80
|
+
.flat_map { |items| add_repeated_lines(items) }
|
81
|
+
end
|
82
|
+
|
83
|
+
def literal_include_examples?(node)
|
84
|
+
include_examples?(node) &&
|
85
|
+
node.arguments.all?(&:recursive_literal_or_const?)
|
86
|
+
end
|
87
|
+
|
88
|
+
def add_repeated_lines(items)
|
89
|
+
repeated_lines = items.map(&:first_line)
|
90
|
+
items.map { |item| [item, repeated_lines - [item.first_line]] }
|
91
|
+
end
|
92
|
+
|
93
|
+
def signature_keys(item)
|
94
|
+
item.arguments
|
95
|
+
end
|
96
|
+
|
97
|
+
def message(item, repeats)
|
98
|
+
format(MSG, name: shared_examples_name(item).source, repeat: repeats)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -16,7 +16,7 @@ module RuboCop
|
|
16
16
|
# allow(foo).to receive(:bar, :baz)
|
17
17
|
# allow(foo).to receive("bar.baz")
|
18
18
|
#
|
19
|
-
class SingleArgumentMessageChain <
|
19
|
+
class SingleArgumentMessageChain < Base
|
20
20
|
extend AutoCorrector
|
21
21
|
|
22
22
|
MSG = 'Use `%<recommended>s` instead of calling '\
|
@@ -0,0 +1,172 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks that message expectations do not have a configured response.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
# expect(foo).to receive(:bar).with(42).and_return("hello world")
|
12
|
+
#
|
13
|
+
# # good (without spies)
|
14
|
+
# allow(foo).to receive(:bar).with(42).and_return("hello world")
|
15
|
+
# expect(foo).to receive(:bar).with(42)
|
16
|
+
#
|
17
|
+
class StubbedMock < Base
|
18
|
+
MSG = 'Prefer `%<replacement>s` over `%<method_name>s` when ' \
|
19
|
+
'configuring a response.'
|
20
|
+
|
21
|
+
# @!method message_expectation?(node)
|
22
|
+
# Match message expectation matcher
|
23
|
+
#
|
24
|
+
# @example source that matches
|
25
|
+
# receive(:foo)
|
26
|
+
#
|
27
|
+
# @example source that matches
|
28
|
+
# receive_message_chain(:foo, :bar)
|
29
|
+
#
|
30
|
+
# @example source that matches
|
31
|
+
# receive(:foo).with('bar')
|
32
|
+
#
|
33
|
+
# @param node [RuboCop::AST::Node]
|
34
|
+
# @return [Array<RuboCop::AST::Node>] matching nodes
|
35
|
+
def_node_matcher :message_expectation?, <<-PATTERN
|
36
|
+
{
|
37
|
+
(send nil? { :receive :receive_message_chain } ...) # receive(:foo)
|
38
|
+
(send (send nil? :receive ...) :with ...) # receive(:foo).with('bar')
|
39
|
+
}
|
40
|
+
PATTERN
|
41
|
+
|
42
|
+
def_node_matcher :configured_response?, <<~PATTERN
|
43
|
+
{ :and_return :and_raise :and_throw :and_yield
|
44
|
+
:and_call_original :and_wrap_original }
|
45
|
+
PATTERN
|
46
|
+
|
47
|
+
# @!method expectation(node)
|
48
|
+
# Match expectation
|
49
|
+
#
|
50
|
+
# @example source that matches
|
51
|
+
# is_expected.to be_in_the_bar
|
52
|
+
#
|
53
|
+
# @example source that matches
|
54
|
+
# expect(cocktail).to contain_exactly(:fresh_orange_juice, :campari)
|
55
|
+
#
|
56
|
+
# @example source that matches
|
57
|
+
# expect_any_instance_of(Officer).to be_alert
|
58
|
+
#
|
59
|
+
# @param node [RuboCop::AST::Node]
|
60
|
+
# @yield [RuboCop::AST::Node] expectation, method name, matcher
|
61
|
+
def_node_matcher :expectation, <<~PATTERN
|
62
|
+
(send
|
63
|
+
$(send nil? $#{Expectations::ALL.node_pattern_union} ...)
|
64
|
+
:to $_)
|
65
|
+
PATTERN
|
66
|
+
|
67
|
+
# @!method matcher_with_configured_response(node)
|
68
|
+
# Match matcher with a configured response
|
69
|
+
#
|
70
|
+
# @example source that matches
|
71
|
+
# receive(:foo).and_return('bar')
|
72
|
+
#
|
73
|
+
# @example source that matches
|
74
|
+
# receive(:lower).and_raise(SomeError)
|
75
|
+
#
|
76
|
+
# @example source that matches
|
77
|
+
# receive(:redirect).and_call_original
|
78
|
+
#
|
79
|
+
# @param node [RuboCop::AST::Node]
|
80
|
+
# @yield [RuboCop::AST::Node] matcher
|
81
|
+
def_node_matcher :matcher_with_configured_response, <<~PATTERN
|
82
|
+
(send #message_expectation? #configured_response? _)
|
83
|
+
PATTERN
|
84
|
+
|
85
|
+
# @!method matcher_with_return_block(node)
|
86
|
+
# Match matcher with a return block
|
87
|
+
#
|
88
|
+
# @example source that matches
|
89
|
+
# receive(:foo) { 'bar' }
|
90
|
+
#
|
91
|
+
# @param node [RuboCop::AST::Node]
|
92
|
+
# @yield [RuboCop::AST::Node] matcher
|
93
|
+
def_node_matcher :matcher_with_return_block, <<~PATTERN
|
94
|
+
(block #message_expectation? args _) # receive(:foo) { 'bar' }
|
95
|
+
PATTERN
|
96
|
+
|
97
|
+
# @!method matcher_with_hash(node)
|
98
|
+
# Match matcher with a configured response defined as a hash
|
99
|
+
#
|
100
|
+
# @example source that matches
|
101
|
+
# receive_messages(foo: 'bar', baz: 'qux')
|
102
|
+
#
|
103
|
+
# @example source that matches
|
104
|
+
# receive_message_chain(:foo, bar: 'baz')
|
105
|
+
#
|
106
|
+
# @param node [RuboCop::AST::Node]
|
107
|
+
# @yield [RuboCop::AST::Node] matcher
|
108
|
+
def_node_matcher :matcher_with_hash, <<~PATTERN
|
109
|
+
{
|
110
|
+
(send nil? :receive_messages hash) # receive_messages(foo: 'bar', baz: 'qux')
|
111
|
+
(send nil? :receive_message_chain ... hash) # receive_message_chain(:foo, bar: 'baz')
|
112
|
+
}
|
113
|
+
PATTERN
|
114
|
+
|
115
|
+
# @!method matcher_with_blockpass(node)
|
116
|
+
# Match matcher with a configured response in block-pass
|
117
|
+
#
|
118
|
+
# @example source that matches
|
119
|
+
# receive(:foo, &canned)
|
120
|
+
#
|
121
|
+
# @example source that matches
|
122
|
+
# receive_message_chain(:foo, :bar, &canned)
|
123
|
+
#
|
124
|
+
# @example source that matches
|
125
|
+
# receive(:foo).with('bar', &canned)
|
126
|
+
#
|
127
|
+
# @param node [RuboCop::AST::Node]
|
128
|
+
# @yield [RuboCop::AST::Node] matcher
|
129
|
+
def_node_matcher :matcher_with_blockpass, <<~PATTERN
|
130
|
+
{
|
131
|
+
(send nil? { :receive :receive_message_chain } ... block_pass) # receive(:foo, &canned)
|
132
|
+
(send (send nil? :receive ...) :with ... block_pass) # receive(:foo).with('foo', &canned)
|
133
|
+
}
|
134
|
+
PATTERN
|
135
|
+
|
136
|
+
def on_send(node)
|
137
|
+
expectation(node, &method(:on_expectation))
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def on_expectation(expectation, method_name, matcher)
|
143
|
+
flag_expectation = lambda do
|
144
|
+
add_offense(expectation, message: msg(method_name))
|
145
|
+
end
|
146
|
+
|
147
|
+
matcher_with_configured_response(matcher, &flag_expectation)
|
148
|
+
matcher_with_return_block(matcher, &flag_expectation)
|
149
|
+
matcher_with_hash(matcher, &flag_expectation)
|
150
|
+
matcher_with_blockpass(matcher, &flag_expectation)
|
151
|
+
end
|
152
|
+
|
153
|
+
def msg(method_name)
|
154
|
+
format(MSG,
|
155
|
+
method_name: method_name,
|
156
|
+
replacement: replacement(method_name))
|
157
|
+
end
|
158
|
+
|
159
|
+
def replacement(method_name)
|
160
|
+
case method_name
|
161
|
+
when :expect
|
162
|
+
:allow
|
163
|
+
when :is_expected
|
164
|
+
'allow(subject)'
|
165
|
+
when :expect_any_instance_of
|
166
|
+
:allow_any_instance_of
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|