rubocop-rspec 1.41.0 → 1.44.0
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 +43 -2
- data/config/default.yml +41 -3
- data/lib/rubocop-rspec.rb +2 -1
- data/lib/rubocop/cop/rspec/align_left_let_brace.rb +12 -19
- data/lib/rubocop/cop/rspec/align_right_let_brace.rb +12 -19
- 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 +2 -2
- data/lib/rubocop/cop/rspec/be_eql.rb +6 -6
- data/lib/rubocop/cop/rspec/before_after_all.rb +1 -1
- data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +19 -17
- data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +14 -12
- data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +1 -1
- data/lib/rubocop/cop/rspec/context_method.rb +7 -9
- 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 +12 -9
- data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +1 -1
- data/lib/rubocop/cop/rspec/dialect.rb +5 -12
- data/lib/rubocop/cop/rspec/empty_example_group.rb +124 -6
- data/lib/rubocop/cop/rspec/empty_hook.rb +6 -10
- data/lib/rubocop/cop/rspec/empty_line_after_example.rb +5 -7
- data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +5 -9
- data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +8 -8
- data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +5 -9
- data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +6 -6
- 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 +10 -11
- data/lib/rubocop/cop/rspec/expect_actual.rb +8 -11
- data/lib/rubocop/cop/rspec/expect_change.rb +10 -35
- data/lib/rubocop/cop/rspec/expect_in_hook.rb +3 -3
- data/lib/rubocop/cop/rspec/expect_output.rb +2 -2
- data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +20 -20
- data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +20 -22
- data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +7 -8
- 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 +16 -23
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +13 -14
- data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +2 -3
- data/lib/rubocop/cop/rspec/implicit_expect.rb +7 -15
- data/lib/rubocop/cop/rspec/implicit_subject.rb +16 -11
- data/lib/rubocop/cop/rspec/instance_spy.rb +18 -12
- data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
- data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +3 -6
- data/lib/rubocop/cop/rspec/it_behaves_like.rb +5 -6
- data/lib/rubocop/cop/rspec/iterated_expectation.rb +1 -1
- data/lib/rubocop/cop/rspec/leading_subject.rb +27 -20
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +1 -1
- data/lib/rubocop/cop/rspec/let_before_examples.rb +13 -11
- data/lib/rubocop/cop/rspec/let_setup.rb +6 -3
- data/lib/rubocop/cop/rspec/message_chain.rb +7 -6
- data/lib/rubocop/cop/rspec/message_expectation.rb +2 -2
- data/lib/rubocop/cop/rspec/message_spies.rb +2 -3
- 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 +18 -19
- data/lib/rubocop/cop/rspec/named_subject.rb +2 -2
- data/lib/rubocop/cop/rspec/nested_groups.rb +4 -4
- data/lib/rubocop/cop/rspec/not_to_not.rb +5 -6
- 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 +30 -67
- data/lib/rubocop/cop/rspec/rails/http_status.rb +5 -9
- data/lib/rubocop/cop/rspec/receive_counts.rb +15 -17
- data/lib/rubocop/cop/rspec/receive_never.rb +12 -12
- 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 +9 -20
- data/lib/rubocop/cop/rspec/scattered_let.rb +8 -11
- data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
- data/lib/rubocop/cop/rspec/shared_context.rb +8 -21
- data/lib/rubocop/cop/rspec/shared_examples.rb +6 -9
- data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +15 -18
- 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 +14 -11
- 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 -10
- 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 +40 -8
@@ -24,7 +24,8 @@ module RuboCop
|
|
24
24
|
#
|
25
25
|
# # good
|
26
26
|
# 3.times { create :user }
|
27
|
-
class CreateList <
|
27
|
+
class CreateList < Base
|
28
|
+
extend AutoCorrector
|
28
29
|
include ConfigurableEnforcedStyle
|
29
30
|
|
30
31
|
MSG_CREATE_LIST = 'Prefer create_list.'
|
@@ -43,7 +44,7 @@ module RuboCop
|
|
43
44
|
PATTERN
|
44
45
|
|
45
46
|
def_node_matcher :factory_list_call, <<-PATTERN
|
46
|
-
(send
|
47
|
+
(send {(const nil? {:FactoryGirl :FactoryBot}) nil?} :create_list (sym _) (int $_) ...)
|
47
48
|
PATTERN
|
48
49
|
|
49
50
|
def on_block(node)
|
@@ -51,26 +52,19 @@ module RuboCop
|
|
51
52
|
return unless n_times_block_without_arg?(node)
|
52
53
|
return unless contains_only_factory?(node.body)
|
53
54
|
|
54
|
-
add_offense(node.send_node, message: MSG_CREATE_LIST)
|
55
|
+
add_offense(node.send_node, message: MSG_CREATE_LIST) do |corrector|
|
56
|
+
CreateListCorrector.new(node.send_node).call(corrector)
|
57
|
+
end
|
55
58
|
end
|
56
59
|
|
57
60
|
def on_send(node)
|
58
61
|
return unless style == :n_times
|
59
62
|
|
60
|
-
factory_list_call(node) do |
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def autocorrect(node)
|
70
|
-
if style == :create_list
|
71
|
-
CreateListCorrector.new(node)
|
72
|
-
else
|
73
|
-
TimesCorrector.new(node)
|
63
|
+
factory_list_call(node) do |count|
|
64
|
+
message = format(MSG_N_TIMES, number: count)
|
65
|
+
add_offense(node.loc.selector, message: message) do |corrector|
|
66
|
+
TimesCorrector.new(node).call(corrector)
|
67
|
+
end
|
74
68
|
end
|
75
69
|
end
|
76
70
|
|
@@ -85,7 +79,7 @@ module RuboCop
|
|
85
79
|
end
|
86
80
|
|
87
81
|
# :nodoc
|
88
|
-
|
82
|
+
module Corrector
|
89
83
|
private
|
90
84
|
|
91
85
|
def build_options_string(options)
|
@@ -108,14 +102,16 @@ module RuboCop
|
|
108
102
|
end
|
109
103
|
|
110
104
|
# :nodoc
|
111
|
-
class TimesCorrector
|
105
|
+
class TimesCorrector
|
106
|
+
include Corrector
|
107
|
+
|
112
108
|
def initialize(node)
|
113
109
|
@node = node
|
114
110
|
end
|
115
111
|
|
116
112
|
def call(corrector)
|
117
113
|
replacement = generate_n_times_block(node)
|
118
|
-
corrector.replace(node
|
114
|
+
corrector.replace(node, replacement)
|
119
115
|
end
|
120
116
|
|
121
117
|
private
|
@@ -136,7 +132,9 @@ module RuboCop
|
|
136
132
|
end
|
137
133
|
|
138
134
|
# :nodoc:
|
139
|
-
class CreateListCorrector
|
135
|
+
class CreateListCorrector
|
136
|
+
include Corrector
|
137
|
+
|
140
138
|
def initialize(node)
|
141
139
|
@node = node.parent
|
142
140
|
end
|
@@ -148,7 +146,7 @@ module RuboCop
|
|
148
146
|
call_replacement(node)
|
149
147
|
end
|
150
148
|
|
151
|
-
corrector.replace(node
|
149
|
+
corrector.replace(node, replacement)
|
152
150
|
end
|
153
151
|
|
154
152
|
private
|
@@ -19,7 +19,9 @@ module RuboCop
|
|
19
19
|
# # good
|
20
20
|
# factory :foo, class: 'Foo' do
|
21
21
|
# end
|
22
|
-
class FactoryClassName <
|
22
|
+
class FactoryClassName < Base
|
23
|
+
extend AutoCorrector
|
24
|
+
|
23
25
|
MSG = "Pass '%<class_name>s' string instead of `%<class_name>s` " \
|
24
26
|
'constant.'
|
25
27
|
ALLOWED_CONSTANTS = %w[Hash OpenStruct].freeze
|
@@ -32,13 +34,10 @@ module RuboCop
|
|
32
34
|
class_name(node) do |cn|
|
33
35
|
next if allowed?(cn.const_name)
|
34
36
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
def autocorrect(node)
|
40
|
-
lambda do |corrector|
|
41
|
-
corrector.replace(node.loc.expression, "'#{node.source}'")
|
37
|
+
msg = format(MSG, class_name: cn.const_name)
|
38
|
+
add_offense(cn, message: msg) do |corrector|
|
39
|
+
corrector.replace(cn, "'#{cn.source}'")
|
40
|
+
end
|
42
41
|
end
|
43
42
|
end
|
44
43
|
|
@@ -56,35 +56,43 @@ module RuboCop
|
|
56
56
|
# # good
|
57
57
|
# my_class_spec.rb # describe MyClass, '#method'
|
58
58
|
#
|
59
|
-
class FilePath <
|
60
|
-
include RuboCop::RSpec::
|
59
|
+
class FilePath < Base
|
60
|
+
include RuboCop::RSpec::TopLevelGroup
|
61
61
|
|
62
62
|
MSG = 'Spec path should end with `%<suffix>s`.'
|
63
63
|
|
64
|
-
|
64
|
+
def_node_matcher :const_described, <<~PATTERN
|
65
|
+
(block
|
66
|
+
$(send #rspec? _example_group $(const ...) $...) ...
|
67
|
+
)
|
68
|
+
PATTERN
|
69
|
+
|
65
70
|
def_node_search :routing_metadata?, '(pair (sym :type) (sym :routing))'
|
66
71
|
|
67
|
-
def
|
68
|
-
return unless
|
69
|
-
return if routing_spec?(args)
|
72
|
+
def on_top_level_example_group(node)
|
73
|
+
return unless top_level_groups.one?
|
70
74
|
|
71
|
-
|
75
|
+
const_described(node) do |send_node, described_class, arguments|
|
76
|
+
next if routing_spec?(arguments)
|
72
77
|
|
73
|
-
|
74
|
-
|
75
|
-
add_offense(
|
76
|
-
node,
|
77
|
-
message: format(MSG, suffix: glob)
|
78
|
-
)
|
78
|
+
ensure_correct_file_path(send_node, described_class, arguments)
|
79
|
+
end
|
79
80
|
end
|
80
81
|
|
81
82
|
private
|
82
83
|
|
84
|
+
def ensure_correct_file_path(send_node, described_class, arguments)
|
85
|
+
glob = glob_for(described_class, arguments.first)
|
86
|
+
return if filename_ends_with?(glob)
|
87
|
+
|
88
|
+
add_offense(send_node, message: format(MSG, suffix: glob))
|
89
|
+
end
|
90
|
+
|
83
91
|
def routing_spec?(args)
|
84
92
|
args.any?(&method(:routing_metadata?))
|
85
93
|
end
|
86
94
|
|
87
|
-
def glob_for(
|
95
|
+
def glob_for(described_class, method_name)
|
88
96
|
return glob_for_spec_suffix_only? if spec_suffix_only?
|
89
97
|
|
90
98
|
"#{expected_path(described_class)}#{name_glob(method_name)}*_spec.rb"
|
@@ -94,10 +102,10 @@ module RuboCop
|
|
94
102
|
'*_spec.rb'
|
95
103
|
end
|
96
104
|
|
97
|
-
def name_glob(
|
98
|
-
return unless
|
105
|
+
def name_glob(method_name)
|
106
|
+
return unless method_name&.str_type?
|
99
107
|
|
100
|
-
"*#{
|
108
|
+
"*#{method_name.str_content.gsub(/\W/, '')}" unless ignore_methods?
|
101
109
|
end
|
102
110
|
|
103
111
|
def expected_path(constant)
|
@@ -19,23 +19,19 @@ module RuboCop
|
|
19
19
|
# # good
|
20
20
|
# describe MyClass do
|
21
21
|
# end
|
22
|
-
class Focus <
|
22
|
+
class Focus < Base
|
23
23
|
MSG = 'Focused spec found.'
|
24
24
|
|
25
|
-
focusable =
|
26
|
-
ExampleGroups::GROUPS +
|
27
|
-
ExampleGroups::SKIPPED +
|
28
|
-
Examples::EXAMPLES +
|
29
|
-
Examples::SKIPPED +
|
30
|
-
Examples::PENDING
|
31
|
-
|
32
25
|
focused = ExampleGroups::FOCUSED + Examples::FOCUSED
|
33
26
|
|
34
|
-
|
27
|
+
def_node_matcher :focusable_selector?,
|
28
|
+
(ExampleGroups::GROUPS + ExampleGroups::SKIPPED +
|
29
|
+
Examples::EXAMPLES + Examples::SKIPPED +
|
30
|
+
Examples::PENDING).node_pattern_union
|
35
31
|
|
36
32
|
def_node_matcher :metadata, <<-PATTERN
|
37
|
-
{(send #
|
38
|
-
(send #
|
33
|
+
{(send #rspec? #focusable_selector? <$(sym :focus) ...>)
|
34
|
+
(send #rspec? #focusable_selector? ... (hash <$(pair (sym :focus) true) ...>))}
|
39
35
|
PATTERN
|
40
36
|
|
41
37
|
def_node_matcher :focused_block?, focused.send_pattern
|
@@ -57,20 +57,20 @@ module RuboCop
|
|
57
57
|
# before(:example) do
|
58
58
|
# # ...
|
59
59
|
# end
|
60
|
-
class HookArgument <
|
60
|
+
class HookArgument < Base
|
61
|
+
extend AutoCorrector
|
61
62
|
include ConfigurableEnforcedStyle
|
62
63
|
|
63
|
-
IMPLICIT_MSG = 'Omit the default `%<scope>p` '
|
64
|
-
'argument for RSpec hooks.'
|
64
|
+
IMPLICIT_MSG = 'Omit the default `%<scope>p` argument for RSpec hooks.'
|
65
65
|
EXPLICIT_MSG = 'Use `%<scope>p` for RSpec hooks.'
|
66
66
|
|
67
|
-
|
67
|
+
def_node_matcher :hook?, Hooks::ALL.node_pattern_union
|
68
68
|
|
69
69
|
def_node_matcher :scoped_hook, <<-PATTERN
|
70
|
-
(block $(send _ #
|
70
|
+
(block $(send _ #hook? (sym ${:each :example})) ...)
|
71
71
|
PATTERN
|
72
72
|
|
73
|
-
def_node_matcher :unscoped_hook,
|
73
|
+
def_node_matcher :unscoped_hook, '(block $(send _ #hook?) ...)'
|
74
74
|
|
75
75
|
def on_block(node)
|
76
76
|
hook(node) do |method_send, scope_name|
|
@@ -78,18 +78,11 @@ module RuboCop
|
|
78
78
|
return check_implicit(method_send) unless scope_name
|
79
79
|
|
80
80
|
style_detected(scope_name)
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
87
|
-
|
88
|
-
def autocorrect(node)
|
89
|
-
scope = implicit_style? ? '' : "(#{style.inspect})"
|
90
|
-
|
91
|
-
lambda do |corrector|
|
92
|
-
corrector.replace(argument_range(node), scope)
|
81
|
+
msg = explicit_message(scope_name)
|
82
|
+
add_offense(method_send, message: msg) do |corrector|
|
83
|
+
scope = implicit_style? ? '' : "(#{style.inspect})"
|
84
|
+
corrector.replace(argument_range(method_send), scope)
|
85
|
+
end
|
93
86
|
end
|
94
87
|
end
|
95
88
|
|
@@ -99,11 +92,11 @@ module RuboCop
|
|
99
92
|
style_detected(:implicit)
|
100
93
|
return if implicit_style?
|
101
94
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
95
|
+
msg = explicit_message(nil)
|
96
|
+
add_offense(method_send.loc.selector, message: msg) do |corrector|
|
97
|
+
scope = "(#{style.inspect})"
|
98
|
+
corrector.replace(argument_range(method_send), scope)
|
99
|
+
end
|
107
100
|
end
|
108
101
|
|
109
102
|
def explicit_message(scope)
|
@@ -23,7 +23,9 @@ module RuboCop
|
|
23
23
|
# expect(foo).to be
|
24
24
|
# end
|
25
25
|
#
|
26
|
-
class HooksBeforeExamples <
|
26
|
+
class HooksBeforeExamples < Base
|
27
|
+
extend AutoCorrector
|
28
|
+
|
27
29
|
MSG = 'Move `%<hook>s` above the examples in the group.'
|
28
30
|
|
29
31
|
def_node_matcher :example_or_group?, <<-PATTERN
|
@@ -39,15 +41,6 @@ module RuboCop
|
|
39
41
|
check_hooks(node.body) if multiline_block?(node.body)
|
40
42
|
end
|
41
43
|
|
42
|
-
def autocorrect(node)
|
43
|
-
lambda do |corrector|
|
44
|
-
first_example = find_first_example(node.parent)
|
45
|
-
RuboCop::RSpec::Corrector::MoveNode.new(
|
46
|
-
node, corrector, processed_source
|
47
|
-
).move_before(first_example)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
44
|
private
|
52
45
|
|
53
46
|
def multiline_block?(block)
|
@@ -62,16 +55,22 @@ module RuboCop
|
|
62
55
|
next if child.sibling_index < first_example.sibling_index
|
63
56
|
next unless hook?(child)
|
64
57
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
58
|
+
msg = format(MSG, hook: child.method_name)
|
59
|
+
add_offense(child, message: msg) do |corrector|
|
60
|
+
autocorrect(corrector, child, first_example)
|
61
|
+
end
|
69
62
|
end
|
70
63
|
end
|
71
64
|
|
72
65
|
def find_first_example(node)
|
73
66
|
node.children.find { |sibling| example_or_group?(sibling) }
|
74
67
|
end
|
68
|
+
|
69
|
+
def autocorrect(corrector, node, first_example)
|
70
|
+
RuboCop::RSpec::Corrector::MoveNode.new(
|
71
|
+
node, corrector, processed_source
|
72
|
+
).move_before(first_example)
|
73
|
+
end
|
75
74
|
end
|
76
75
|
end
|
77
76
|
end
|
@@ -16,14 +16,13 @@ module RuboCop
|
|
16
16
|
# it 'changes something to a new value' do
|
17
17
|
# expect { do_something }.to change(something).to(new_value)
|
18
18
|
# end
|
19
|
-
class ImplicitBlockExpectation <
|
19
|
+
class ImplicitBlockExpectation < Base
|
20
20
|
MSG = 'Avoid implicit block expectations.'
|
21
21
|
|
22
22
|
def_node_matcher :lambda?, <<-PATTERN
|
23
23
|
{
|
24
24
|
(send (const nil? :Proc) :new)
|
25
|
-
(send nil? :proc)
|
26
|
-
(send nil? :lambda)
|
25
|
+
(send nil? {:proc :lambda})
|
27
26
|
}
|
28
27
|
PATTERN
|
29
28
|
|
@@ -24,7 +24,8 @@ module RuboCop
|
|
24
24
|
# # good
|
25
25
|
# it { should be_truthy }
|
26
26
|
#
|
27
|
-
class ImplicitExpect <
|
27
|
+
class ImplicitExpect < Base
|
28
|
+
extend AutoCorrector
|
28
29
|
include ConfigurableEnforcedStyle
|
29
30
|
|
30
31
|
MSG = 'Prefer `%<good>s` over `%<bad>s`.'
|
@@ -54,20 +55,11 @@ module RuboCop
|
|
54
55
|
else
|
55
56
|
opposite_style_detected
|
56
57
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def autocorrect(node)
|
66
|
-
lambda do |corrector|
|
67
|
-
offense = offending_expect(node)
|
68
|
-
replacement = replacement_source(offense.source)
|
69
|
-
|
70
|
-
corrector.replace(offense, replacement)
|
58
|
+
msg = offense_message(expectation_source)
|
59
|
+
add_offense(source_range, message: msg) do |corrector|
|
60
|
+
replacement = replacement_source(expectation_source)
|
61
|
+
corrector.replace(source_range, replacement)
|
62
|
+
end
|
71
63
|
end
|
72
64
|
end
|
73
65
|
|
@@ -26,7 +26,8 @@ module RuboCop
|
|
26
26
|
# # good
|
27
27
|
# it { expect(subject).to be_truthy }
|
28
28
|
#
|
29
|
-
class ImplicitSubject <
|
29
|
+
class ImplicitSubject < Base
|
30
|
+
extend AutoCorrector
|
30
31
|
include ConfigurableEnforcedStyle
|
31
32
|
|
32
33
|
MSG = "Don't use implicit subject."
|
@@ -39,33 +40,37 @@ module RuboCop
|
|
39
40
|
return unless implicit_subject?(node)
|
40
41
|
return if valid_usage?(node)
|
41
42
|
|
42
|
-
add_offense(node)
|
43
|
+
add_offense(node) do |corrector|
|
44
|
+
autocorrect(corrector, node)
|
45
|
+
end
|
43
46
|
end
|
44
47
|
|
45
|
-
|
48
|
+
private
|
49
|
+
|
50
|
+
def autocorrect(corrector, node)
|
46
51
|
replacement = 'expect(subject)'
|
47
|
-
|
52
|
+
case node.method_name
|
53
|
+
when :should
|
48
54
|
replacement += '.to'
|
49
|
-
|
55
|
+
when :should_not
|
50
56
|
replacement += '.not_to'
|
51
57
|
end
|
52
58
|
|
53
|
-
|
59
|
+
corrector.replace(node.loc.selector, replacement)
|
54
60
|
end
|
55
61
|
|
56
|
-
private
|
57
|
-
|
58
62
|
def valid_usage?(node)
|
59
63
|
example = node.ancestors.find { |parent| example?(parent) }
|
60
64
|
return false if example.nil?
|
61
65
|
|
62
|
-
example.
|
66
|
+
example.method?(:its) || allowed_by_style?(example)
|
63
67
|
end
|
64
68
|
|
65
69
|
def allowed_by_style?(example)
|
66
|
-
|
70
|
+
case style
|
71
|
+
when :single_line_only
|
67
72
|
example.single_line?
|
68
|
-
|
73
|
+
when :single_statement_only
|
69
74
|
!example.body.begin_type?
|
70
75
|
else
|
71
76
|
false
|