rubocop-rspec 1.38.1 → 1.43.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 +57 -0
- data/CODE_OF_CONDUCT.md +17 -0
- data/README.md +1 -61
- data/config/default.yml +159 -19
- data/lib/rubocop-rspec.rb +5 -2
- 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 +1 -1
- data/lib/rubocop/cop/rspec/base.rb +74 -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 +69 -0
- 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 +3 -87
- data/lib/rubocop/cop/rspec/describe_class.rb +29 -23
- data/lib/rubocop/cop/rspec/describe_method.rb +14 -7
- 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 +91 -7
- data/lib/rubocop/cop/rspec/empty_hook.rb +46 -0
- 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 +24 -21
- 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 +57 -21
- 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 +10 -29
- data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +1 -1
- 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 +4 -8
- 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 +22 -26
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +2 -5
- data/lib/rubocop/cop/rspec/let_before_examples.rb +10 -26
- data/lib/rubocop/cop/rspec/let_setup.rb +21 -6
- 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 +8 -8
- data/lib/rubocop/cop/rspec/nested_groups.rb +12 -13
- 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 +32 -69
- data/lib/rubocop/cop/rspec/rails/http_status.rb +7 -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 +12 -2
- data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +1 -1
- data/lib/rubocop/cop/rspec/return_from_stub.rb +12 -22
- data/lib/rubocop/cop/rspec/scattered_let.rb +12 -2
- 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 +7 -9
- data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +15 -18
- data/lib/rubocop/cop/rspec/subject_stub.rb +25 -53
- data/lib/rubocop/cop/rspec/unspecified_exception.rb +1 -1
- data/lib/rubocop/cop/rspec/variable_definition.rb +56 -0
- data/lib/rubocop/cop/rspec/variable_name.rb +66 -0
- 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 +6 -1
- data/lib/rubocop/rspec/corrector/move_node.rb +54 -0
- data/lib/rubocop/rspec/description_extractor.rb +2 -6
- data/lib/rubocop/rspec/{blank_line_separation.rb → empty_line_separation.rb} +13 -10
- data/lib/rubocop/rspec/example_group.rb +21 -49
- data/lib/rubocop/rspec/factory_bot.rb +7 -1
- data/lib/rubocop/rspec/language.rb +13 -3
- data/lib/rubocop/rspec/language/node_pattern.rb +11 -2
- data/lib/rubocop/rspec/top_level_describe.rb +2 -2
- data/lib/rubocop/rspec/top_level_group.rb +55 -0
- data/lib/rubocop/rspec/variable.rb +16 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- metadata +36 -13
- data/lib/rubocop/rspec/util.rb +0 -19
@@ -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
|
|
@@ -3,10 +3,11 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
|
-
# Checks that spec file paths are consistent
|
6
|
+
# Checks that spec file paths are consistent and well-formed.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
8
|
+
# By default, this checks that spec file paths are consistent with the
|
9
|
+
# test subject and and enforces that it reflects the described
|
10
|
+
# class/module and its optionally called out method.
|
10
11
|
#
|
11
12
|
# With the configuration option `IgnoreMethods` the called out method will
|
12
13
|
# be ignored when determining the enforced path.
|
@@ -15,6 +16,10 @@ module RuboCop
|
|
15
16
|
# be specified that should not as usual be transformed from CamelCase to
|
16
17
|
# snake_case (e.g. 'RuboCop' => 'rubocop' ).
|
17
18
|
#
|
19
|
+
# With the configuration option `SpecSuffixOnly` test files will only
|
20
|
+
# be checked to ensure they end in '_spec.rb'. This option disables
|
21
|
+
# checking for consistency in the test subject or test methods.
|
22
|
+
#
|
18
23
|
# @example
|
19
24
|
# # bad
|
20
25
|
# whatever_spec.rb # describe MyClass
|
@@ -41,42 +46,66 @@ module RuboCop
|
|
41
46
|
# # good
|
42
47
|
# my_class_spec.rb # describe MyClass, '#method'
|
43
48
|
#
|
44
|
-
|
45
|
-
|
49
|
+
# @example when configuration is `SpecSuffixOnly: true`
|
50
|
+
# # good
|
51
|
+
# whatever_spec.rb # describe MyClass
|
52
|
+
#
|
53
|
+
# # good
|
54
|
+
# my_class_spec.rb # describe MyClass
|
55
|
+
#
|
56
|
+
# # good
|
57
|
+
# my_class_spec.rb # describe MyClass, '#method'
|
58
|
+
#
|
59
|
+
class FilePath < Base
|
60
|
+
include RuboCop::RSpec::TopLevelGroup
|
46
61
|
|
47
62
|
MSG = 'Spec path should end with `%<suffix>s`.'
|
48
63
|
|
49
|
-
|
50
|
-
|
64
|
+
def_node_matcher :const_described, <<~PATTERN
|
65
|
+
(block
|
66
|
+
$(send #rspec? _example_group $(const ...) $...) ...
|
67
|
+
)
|
68
|
+
PATTERN
|
51
69
|
|
52
|
-
|
53
|
-
return unless const_described?(node) && single_top_level_describe?
|
54
|
-
return if routing_spec?(args)
|
70
|
+
def_node_search :routing_metadata?, '(pair (sym :type) (sym :routing))'
|
55
71
|
|
56
|
-
|
72
|
+
def on_top_level_group(node)
|
73
|
+
return unless top_level_groups.one?
|
57
74
|
|
58
|
-
|
75
|
+
const_described(node) do |send_node, described_class, arguments|
|
76
|
+
next if routing_spec?(arguments)
|
59
77
|
|
60
|
-
|
61
|
-
|
62
|
-
message: format(MSG, suffix: glob)
|
63
|
-
)
|
78
|
+
ensure_correct_file_path(send_node, described_class, arguments)
|
79
|
+
end
|
64
80
|
end
|
65
81
|
|
66
82
|
private
|
67
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
|
+
|
68
91
|
def routing_spec?(args)
|
69
92
|
args.any?(&method(:routing_metadata?))
|
70
93
|
end
|
71
94
|
|
72
|
-
def glob_for(
|
95
|
+
def glob_for(described_class, method_name)
|
96
|
+
return glob_for_spec_suffix_only? if spec_suffix_only?
|
97
|
+
|
73
98
|
"#{expected_path(described_class)}#{name_glob(method_name)}*_spec.rb"
|
74
99
|
end
|
75
100
|
|
76
|
-
def
|
77
|
-
|
101
|
+
def glob_for_spec_suffix_only?
|
102
|
+
'*_spec.rb'
|
103
|
+
end
|
104
|
+
|
105
|
+
def name_glob(method_name)
|
106
|
+
return unless method_name&.str_type?
|
78
107
|
|
79
|
-
"*#{
|
108
|
+
"*#{method_name.str_content.gsub(/\W/, '')}" unless ignore_methods?
|
80
109
|
end
|
81
110
|
|
82
111
|
def expected_path(constant)
|
@@ -103,12 +132,19 @@ module RuboCop
|
|
103
132
|
end
|
104
133
|
|
105
134
|
def filename_ends_with?(glob)
|
106
|
-
|
135
|
+
filename =
|
136
|
+
RuboCop::PathUtil.relative_path(processed_source.buffer.name)
|
137
|
+
.gsub('../', '')
|
138
|
+
File.fnmatch?("*#{glob}", filename)
|
107
139
|
end
|
108
140
|
|
109
141
|
def relevant_rubocop_rspec_file?(_file)
|
110
142
|
true
|
111
143
|
end
|
144
|
+
|
145
|
+
def spec_suffix_only?
|
146
|
+
cop_config['SpecSuffixOnly']
|
147
|
+
end
|
112
148
|
end
|
113
149
|
end
|
114
150
|
end
|
@@ -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,9 +23,8 @@ module RuboCop
|
|
23
23
|
# expect(foo).to be
|
24
24
|
# end
|
25
25
|
#
|
26
|
-
class HooksBeforeExamples <
|
27
|
-
|
28
|
-
include RuboCop::RSpec::FinalEndLocation
|
26
|
+
class HooksBeforeExamples < Base
|
27
|
+
extend AutoCorrector
|
29
28
|
|
30
29
|
MSG = 'Move `%<hook>s` above the examples in the group.'
|
31
30
|
|
@@ -42,17 +41,6 @@ module RuboCop
|
|
42
41
|
check_hooks(node.body) if multiline_block?(node.body)
|
43
42
|
end
|
44
43
|
|
45
|
-
def autocorrect(node)
|
46
|
-
lambda do |corrector|
|
47
|
-
first_example = find_first_example(node.parent)
|
48
|
-
first_example_pos = first_example.loc.expression
|
49
|
-
indent = "\n" + ' ' * first_example.loc.column
|
50
|
-
|
51
|
-
corrector.insert_before(first_example_pos, source(node) + indent)
|
52
|
-
corrector.remove(node_range_with_surrounding_space(node))
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
44
|
private
|
57
45
|
|
58
46
|
def multiline_block?(block)
|
@@ -67,10 +55,10 @@ module RuboCop
|
|
67
55
|
next if child.sibling_index < first_example.sibling_index
|
68
56
|
next unless hook?(child)
|
69
57
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
58
|
+
msg = format(MSG, hook: child.method_name)
|
59
|
+
add_offense(child, message: msg) do |corrector|
|
60
|
+
autocorrect(corrector, child, first_example)
|
61
|
+
end
|
74
62
|
end
|
75
63
|
end
|
76
64
|
|
@@ -78,17 +66,10 @@ module RuboCop
|
|
78
66
|
node.children.find { |sibling| example_or_group?(sibling) }
|
79
67
|
end
|
80
68
|
|
81
|
-
def
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
def source(node)
|
87
|
-
node_range(node).source
|
88
|
-
end
|
89
|
-
|
90
|
-
def node_range(node)
|
91
|
-
node.loc.expression.with(end_pos: final_end_location(node).end_pos)
|
69
|
+
def autocorrect(corrector, node, first_example)
|
70
|
+
RuboCop::RSpec::Corrector::MoveNode.new(
|
71
|
+
node, corrector, processed_source
|
72
|
+
).move_before(first_example)
|
92
73
|
end
|
93
74
|
end
|
94
75
|
end
|
@@ -16,7 +16,7 @@ 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
|
@@ -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
|
|