rubocop-rspec 2.22.0 → 2.27.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 +94 -9
- data/README.md +1 -1
- data/config/default.yml +126 -21
- data/lib/rubocop/cop/rspec/around_block.rb +3 -3
- data/lib/rubocop/cop/rspec/be.rb +1 -1
- data/lib/rubocop/cop/rspec/be_empty.rb +1 -0
- data/lib/rubocop/cop/rspec/be_eq.rb +1 -1
- data/lib/rubocop/cop/rspec/be_eql.rb +1 -1
- data/lib/rubocop/cop/rspec/be_nil.rb +2 -2
- data/lib/rubocop/cop/rspec/before_after_all.rb +7 -13
- data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +2 -2
- data/lib/rubocop/cop/rspec/change_by_zero.rb +30 -4
- data/lib/rubocop/cop/rspec/context_method.rb +2 -2
- data/lib/rubocop/cop/rspec/context_wording.rb +1 -1
- data/lib/rubocop/cop/rspec/describe_symbol.rb +1 -1
- data/lib/rubocop/cop/rspec/described_class.rb +33 -11
- data/lib/rubocop/cop/rspec/duplicated_metadata.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_example_group.rb +4 -1
- data/lib/rubocop/cop/rspec/empty_line_after_example.rb +2 -2
- data/lib/rubocop/cop/rspec/empty_metadata.rb +46 -0
- data/lib/rubocop/cop/rspec/eq.rb +47 -0
- data/lib/rubocop/cop/rspec/example_length.rb +11 -5
- data/lib/rubocop/cop/rspec/example_without_description.rb +11 -2
- data/lib/rubocop/cop/rspec/example_wording.rb +11 -2
- data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +14 -5
- data/lib/rubocop/cop/rspec/expect_actual.rb +7 -4
- data/lib/rubocop/cop/rspec/expect_change.rb +2 -2
- data/lib/rubocop/cop/rspec/expect_output.rb +1 -4
- data/lib/rubocop/cop/rspec/file_path.rb +6 -0
- data/lib/rubocop/cop/rspec/focus.rb +17 -2
- data/lib/rubocop/cop/rspec/hook_argument.rb +2 -2
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +1 -1
- data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +2 -2
- data/lib/rubocop/cop/rspec/implicit_expect.rb +1 -1
- data/lib/rubocop/cop/rspec/implicit_subject.rb +2 -2
- data/lib/rubocop/cop/rspec/indexed_let.rb +32 -1
- data/lib/rubocop/cop/rspec/instance_spy.rb +2 -2
- data/lib/rubocop/cop/rspec/instance_variable.rb +3 -3
- data/lib/rubocop/cop/rspec/is_expected_specify.rb +45 -0
- data/lib/rubocop/cop/rspec/iterated_expectation.rb +3 -3
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +1 -1
- data/lib/rubocop/cop/rspec/let_before_examples.rb +5 -1
- data/lib/rubocop/cop/rspec/let_setup.rb +1 -1
- data/lib/rubocop/cop/rspec/message_expectation.rb +1 -2
- data/lib/rubocop/cop/rspec/message_spies.rb +0 -2
- data/lib/rubocop/cop/rspec/metadata_style.rb +202 -0
- data/lib/rubocop/cop/rspec/mixin/file_help.rb +14 -0
- data/lib/rubocop/cop/rspec/mixin/metadata.rb +21 -7
- data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +2 -2
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +12 -7
- data/lib/rubocop/cop/rspec/named_subject.rb +1 -1
- data/lib/rubocop/cop/rspec/pending.rb +12 -2
- data/lib/rubocop/cop/rspec/pending_without_reason.rb +1 -1
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +9 -9
- data/lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb +1 -1
- data/lib/rubocop/cop/rspec/rails/have_http_status.rb +34 -10
- data/lib/rubocop/cop/rspec/rails/http_status.rb +29 -18
- data/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +314 -22
- data/lib/rubocop/cop/rspec/rails/negation_be_valid.rb +102 -0
- data/lib/rubocop/cop/rspec/receive_counts.rb +1 -1
- data/lib/rubocop/cop/rspec/receive_messages.rb +161 -0
- data/lib/rubocop/cop/rspec/redundant_predicate_matcher.rb +67 -0
- data/lib/rubocop/cop/rspec/remove_const.rb +40 -0
- data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +1 -1
- data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +2 -2
- data/lib/rubocop/cop/rspec/repeated_include_example.rb +1 -1
- data/lib/rubocop/cop/rspec/repeated_subject_call.rb +124 -0
- data/lib/rubocop/cop/rspec/return_from_stub.rb +1 -1
- data/lib/rubocop/cop/rspec/shared_context.rb +1 -1
- data/lib/rubocop/cop/rspec/shared_examples.rb +66 -20
- data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +2 -3
- data/lib/rubocop/cop/rspec/sort_metadata.rb +2 -1
- data/lib/rubocop/cop/rspec/spec_file_path_format.rb +133 -0
- data/lib/rubocop/cop/rspec/spec_file_path_suffix.rb +40 -0
- data/lib/rubocop/cop/rspec/stubbed_mock.rb +1 -1
- data/lib/rubocop/cop/rspec/subject_stub.rb +4 -4
- data/lib/rubocop/cop/rspec/unspecified_exception.rb +2 -2
- data/lib/rubocop/cop/rspec/variable_definition.rb +4 -4
- data/lib/rubocop/cop/rspec/verified_double_reference.rb +6 -6
- data/lib/rubocop/cop/rspec/verified_doubles.rb +2 -2
- data/lib/rubocop/cop/rspec/void_expect.rb +4 -3
- data/lib/rubocop/cop/rspec_cops.rb +11 -0
- data/lib/rubocop/rspec/language.rb +8 -8
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop/rspec/wording.rb +8 -0
- data/lib/rubocop-rspec.rb +1 -0
- metadata +20 -8
@@ -48,12 +48,17 @@ module RuboCop
|
|
48
48
|
# end
|
49
49
|
# end
|
50
50
|
#
|
51
|
-
# @example
|
52
|
-
# #
|
53
|
-
#
|
54
|
-
#
|
51
|
+
# @example `Max: 1` (default)
|
52
|
+
# # bad
|
53
|
+
# describe UserCreator do
|
54
|
+
# it 'builds a user' do
|
55
|
+
# expect(user.name).to eq("John")
|
56
|
+
# expect(user.age).to eq(22)
|
57
|
+
# end
|
58
|
+
# end
|
55
59
|
#
|
56
|
-
#
|
60
|
+
# @example `Max: 2`
|
61
|
+
# # good
|
57
62
|
# describe UserCreator do
|
58
63
|
# it 'builds a user' do
|
59
64
|
# expect(user.name).to eq("John")
|
@@ -70,7 +75,7 @@ module RuboCop
|
|
70
75
|
TRUE = ->(node) { node.true_type? }
|
71
76
|
|
72
77
|
# @!method aggregate_failures?(node)
|
73
|
-
def_node_matcher :aggregate_failures?,
|
78
|
+
def_node_matcher :aggregate_failures?, <<~PATTERN
|
74
79
|
(block {
|
75
80
|
(send _ _ <(sym :aggregate_failures) ...>)
|
76
81
|
(send _ _ ... (hash <(pair (sym :aggregate_failures) %1) ...>))
|
@@ -81,7 +86,7 @@ module RuboCop
|
|
81
86
|
def_node_matcher :expect?, '(send nil? #Expectations.all ...)'
|
82
87
|
|
83
88
|
# @!method aggregate_failures_block?(node)
|
84
|
-
def_node_matcher :aggregate_failures_block?,
|
89
|
+
def_node_matcher :aggregate_failures_block?, <<~PATTERN
|
85
90
|
(block (send nil? :aggregate_failures ...) ...)
|
86
91
|
PATTERN
|
87
92
|
|
@@ -41,10 +41,15 @@ module RuboCop
|
|
41
41
|
def_node_matcher :skippable?, <<~PATTERN
|
42
42
|
{
|
43
43
|
(send #rspec? #ExampleGroups.regular ...)
|
44
|
-
|
44
|
+
#skippable_example?
|
45
45
|
}
|
46
46
|
PATTERN
|
47
47
|
|
48
|
+
# @!method skippable_example?(node)
|
49
|
+
def_node_matcher :skippable_example?, <<~PATTERN
|
50
|
+
(send nil? #Examples.regular ...)
|
51
|
+
PATTERN
|
52
|
+
|
48
53
|
# @!method pending_block?(node)
|
49
54
|
def_node_matcher :pending_block?, <<~PATTERN
|
50
55
|
{
|
@@ -62,7 +67,12 @@ module RuboCop
|
|
62
67
|
private
|
63
68
|
|
64
69
|
def skipped?(node)
|
65
|
-
skippable?(node) && skipped_in_metadata?(node)
|
70
|
+
(skippable?(node) && skipped_in_metadata?(node)) ||
|
71
|
+
skipped_regular_example_without_body?(node)
|
72
|
+
end
|
73
|
+
|
74
|
+
def skipped_regular_example_without_body?(node)
|
75
|
+
skippable_example?(node) && !node.block_node
|
66
76
|
end
|
67
77
|
end
|
68
78
|
end
|
@@ -103,7 +103,7 @@ module RuboCop
|
|
103
103
|
on_pending_by_metadata(node)
|
104
104
|
return unless (parent = parent_node(node))
|
105
105
|
|
106
|
-
if
|
106
|
+
if spec_group?(parent) || block_node_example_group?(node)
|
107
107
|
on_skipped_by_example_method(node)
|
108
108
|
on_skipped_by_example_group_method(node)
|
109
109
|
elsif example?(parent)
|
@@ -26,7 +26,7 @@ module RuboCop
|
|
26
26
|
end
|
27
27
|
|
28
28
|
# @!method predicate_in_actual?(node)
|
29
|
-
def_node_matcher :predicate_in_actual?,
|
29
|
+
def_node_matcher :predicate_in_actual?, <<~PATTERN
|
30
30
|
(send
|
31
31
|
(send nil? :expect {
|
32
32
|
(block $(send !nil? #predicate? ...) ...)
|
@@ -36,12 +36,12 @@ module RuboCop
|
|
36
36
|
PATTERN
|
37
37
|
|
38
38
|
# @!method be_bool?(node)
|
39
|
-
def_node_matcher :be_bool?,
|
39
|
+
def_node_matcher :be_bool?, <<~PATTERN
|
40
40
|
(send nil? {:be :eq :eql :equal} {true false})
|
41
41
|
PATTERN
|
42
42
|
|
43
43
|
# @!method be_boolthy?(node)
|
44
|
-
def_node_matcher :be_boolthy?,
|
44
|
+
def_node_matcher :be_boolthy?, <<~PATTERN
|
45
45
|
(send nil? {:be_truthy :be_falsey :be_falsy :a_truthy_value :a_falsey_value :a_falsy_value})
|
46
46
|
PATTERN
|
47
47
|
|
@@ -74,7 +74,7 @@ module RuboCop
|
|
74
74
|
name[0..-2]
|
75
75
|
when 'exist?', 'exists?'
|
76
76
|
'exist'
|
77
|
-
when
|
77
|
+
when /\Ahas_/
|
78
78
|
name.sub('has_', 'have_')[0..-2]
|
79
79
|
else
|
80
80
|
"be_#{name[0..-2]}"
|
@@ -179,7 +179,7 @@ module RuboCop
|
|
179
179
|
end
|
180
180
|
|
181
181
|
# @!method predicate_matcher?(node)
|
182
|
-
def_node_matcher :predicate_matcher?,
|
182
|
+
def_node_matcher :predicate_matcher?, <<~PATTERN
|
183
183
|
(send
|
184
184
|
(send nil? :expect $!nil?)
|
185
185
|
#Runners.all
|
@@ -188,7 +188,7 @@ module RuboCop
|
|
188
188
|
PATTERN
|
189
189
|
|
190
190
|
# @!method predicate_matcher_block?(node)
|
191
|
-
def_node_matcher :predicate_matcher_block?,
|
191
|
+
def_node_matcher :predicate_matcher_block?, <<~PATTERN
|
192
192
|
(block
|
193
193
|
(send
|
194
194
|
(send nil? :expect $!nil?)
|
@@ -202,7 +202,7 @@ module RuboCop
|
|
202
202
|
|
203
203
|
return false if allowed_explicit_matchers.include?(name)
|
204
204
|
|
205
|
-
name.start_with?('be_', 'have_') && !name.end_with?('?') ||
|
205
|
+
(name.start_with?('be_', 'have_') && !name.end_with?('?')) ||
|
206
206
|
%w[include respond_to].include?(name)
|
207
207
|
end
|
208
208
|
|
@@ -240,10 +240,10 @@ module RuboCop
|
|
240
240
|
'include?'
|
241
241
|
when 'respond_to'
|
242
242
|
'respond_to?'
|
243
|
-
when
|
243
|
+
when /\Ahave_(.+)/
|
244
244
|
"has_#{Regexp.last_match(1)}?"
|
245
245
|
else
|
246
|
-
"#{matcher[
|
246
|
+
"#{matcher[/\Abe_(.+)/, 1]}?"
|
247
247
|
end
|
248
248
|
end
|
249
249
|
# rubocop:enable Metrics/MethodLength
|
@@ -6,48 +6,72 @@ module RuboCop
|
|
6
6
|
module Rails
|
7
7
|
# Checks that tests use `have_http_status` instead of equality matchers.
|
8
8
|
#
|
9
|
-
# @example
|
9
|
+
# @example ResponseMethods: ['response', 'last_response'] (default)
|
10
10
|
# # bad
|
11
11
|
# expect(response.status).to be(200)
|
12
|
-
# expect(
|
12
|
+
# expect(last_response.code).to eq("200")
|
13
13
|
#
|
14
14
|
# # good
|
15
15
|
# expect(response).to have_http_status(200)
|
16
|
+
# expect(last_response).to have_http_status(200)
|
17
|
+
#
|
18
|
+
# @example ResponseMethods: ['foo_response']
|
19
|
+
# # bad
|
20
|
+
# expect(foo_response.status).to be(200)
|
21
|
+
#
|
22
|
+
# # good
|
23
|
+
# expect(foo_response).to have_http_status(200)
|
24
|
+
#
|
25
|
+
# # also good
|
26
|
+
# expect(response).to have_http_status(200)
|
27
|
+
# expect(last_response).to have_http_status(200)
|
16
28
|
#
|
17
29
|
class HaveHttpStatus < ::RuboCop::Cop::Base
|
18
30
|
extend AutoCorrector
|
19
31
|
|
20
32
|
MSG =
|
21
|
-
'Prefer `expect(response).%<to>s
|
22
|
-
'over `%<bad_code>s`.'
|
33
|
+
'Prefer `expect(%<response>s).%<to>s ' \
|
34
|
+
'have_http_status(%<status>s)` over `%<bad_code>s`.'
|
23
35
|
|
24
36
|
RUNNERS = %i[to to_not not_to].to_set
|
25
37
|
RESTRICT_ON_SEND = RUNNERS
|
26
38
|
|
27
39
|
# @!method match_status(node)
|
28
|
-
def_node_matcher :match_status,
|
40
|
+
def_node_matcher :match_status, <<~PATTERN
|
29
41
|
(send
|
30
42
|
(send nil? :expect
|
31
|
-
$(send (send nil?
|
43
|
+
$(send $(send nil? #response_methods?) {:status :code})
|
32
44
|
)
|
33
45
|
$RUNNERS
|
34
46
|
$(send nil? {:be :eq :eql :equal} ({int str} $_))
|
35
47
|
)
|
36
48
|
PATTERN
|
37
49
|
|
38
|
-
def on_send(node)
|
39
|
-
match_status(node) do
|
50
|
+
def on_send(node) # rubocop:disable Metrics/MethodLength
|
51
|
+
match_status(node) do
|
52
|
+
|response_status, response_method, to, match, status|
|
40
53
|
return unless status.to_s.match?(/\A\d+\z/)
|
41
54
|
|
42
|
-
message = format(MSG,
|
55
|
+
message = format(MSG, response: response_method.method_name,
|
56
|
+
to: to, status: status,
|
43
57
|
bad_code: node.source)
|
44
58
|
add_offense(node, message: message) do |corrector|
|
45
|
-
corrector.replace(response_status,
|
59
|
+
corrector.replace(response_status, response_method.method_name)
|
46
60
|
corrector.replace(match.loc.selector, 'have_http_status')
|
47
61
|
corrector.replace(match.first_argument, status.to_s)
|
48
62
|
end
|
49
63
|
end
|
50
64
|
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def response_methods?(name)
|
69
|
+
response_methods.include?(name.to_s)
|
70
|
+
end
|
71
|
+
|
72
|
+
def response_methods
|
73
|
+
cop_config.fetch('ResponseMethods', [])
|
74
|
+
end
|
51
75
|
end
|
52
76
|
end
|
53
77
|
end
|
@@ -17,10 +17,12 @@ module RuboCop
|
|
17
17
|
# # bad
|
18
18
|
# it { is_expected.to have_http_status 200 }
|
19
19
|
# it { is_expected.to have_http_status 404 }
|
20
|
+
# it { is_expected.to have_http_status "403" }
|
20
21
|
#
|
21
22
|
# # good
|
22
23
|
# it { is_expected.to have_http_status :ok }
|
23
24
|
# it { is_expected.to have_http_status :not_found }
|
25
|
+
# it { is_expected.to have_http_status :forbidden }
|
24
26
|
# it { is_expected.to have_http_status :success }
|
25
27
|
# it { is_expected.to have_http_status :error }
|
26
28
|
#
|
@@ -28,10 +30,12 @@ module RuboCop
|
|
28
30
|
# # bad
|
29
31
|
# it { is_expected.to have_http_status :ok }
|
30
32
|
# it { is_expected.to have_http_status :not_found }
|
33
|
+
# it { is_expected.to have_http_status "forbidden" }
|
31
34
|
#
|
32
35
|
# # good
|
33
36
|
# it { is_expected.to have_http_status 200 }
|
34
37
|
# it { is_expected.to have_http_status 404 }
|
38
|
+
# it { is_expected.to have_http_status 403 }
|
35
39
|
# it { is_expected.to have_http_status :success }
|
36
40
|
# it { is_expected.to have_http_status :error }
|
37
41
|
#
|
@@ -39,8 +43,10 @@ module RuboCop
|
|
39
43
|
# # bad
|
40
44
|
# it { is_expected.to have_http_status :ok }
|
41
45
|
# it { is_expected.to have_http_status :not_found }
|
46
|
+
# it { is_expected.to have_http_status "forbidden" }
|
42
47
|
# it { is_expected.to have_http_status 200 }
|
43
48
|
# it { is_expected.to have_http_status 404 }
|
49
|
+
# it { is_expected.to have_http_status "403" }
|
44
50
|
#
|
45
51
|
# # good
|
46
52
|
# it { is_expected.to be_ok }
|
@@ -54,12 +60,14 @@ module RuboCop
|
|
54
60
|
RESTRICT_ON_SEND = %i[have_http_status].freeze
|
55
61
|
|
56
62
|
# @!method http_status(node)
|
57
|
-
def_node_matcher :http_status,
|
58
|
-
(send nil? :have_http_status ${int sym})
|
63
|
+
def_node_matcher :http_status, <<~PATTERN
|
64
|
+
(send nil? :have_http_status ${int sym str})
|
59
65
|
PATTERN
|
60
66
|
|
61
67
|
def on_send(node)
|
62
68
|
http_status(node) do |arg|
|
69
|
+
return if arg.str_type? && arg.heredoc?
|
70
|
+
|
63
71
|
checker = checker_class.new(arg)
|
64
72
|
return unless checker.offensive?
|
65
73
|
|
@@ -99,6 +107,10 @@ module RuboCop
|
|
99
107
|
format(MSG, prefer: prefer, current: current)
|
100
108
|
end
|
101
109
|
|
110
|
+
def current
|
111
|
+
offense_range.source
|
112
|
+
end
|
113
|
+
|
102
114
|
def offense_range
|
103
115
|
node
|
104
116
|
end
|
@@ -123,10 +135,6 @@ module RuboCop
|
|
123
135
|
symbol.inspect
|
124
136
|
end
|
125
137
|
|
126
|
-
def current
|
127
|
-
number.inspect
|
128
|
-
end
|
129
|
-
|
130
138
|
private
|
131
139
|
|
132
140
|
def symbol
|
@@ -134,7 +142,7 @@ module RuboCop
|
|
134
142
|
end
|
135
143
|
|
136
144
|
def number
|
137
|
-
node.
|
145
|
+
node.value.to_i
|
138
146
|
end
|
139
147
|
end
|
140
148
|
|
@@ -148,10 +156,6 @@ module RuboCop
|
|
148
156
|
number.to_s
|
149
157
|
end
|
150
158
|
|
151
|
-
def current
|
152
|
-
symbol.inspect
|
153
|
-
end
|
154
|
-
|
155
159
|
private
|
156
160
|
|
157
161
|
def symbol
|
@@ -159,7 +163,7 @@ module RuboCop
|
|
159
163
|
end
|
160
164
|
|
161
165
|
def number
|
162
|
-
::Rack::Utils::SYMBOL_TO_STATUS_CODE[symbol]
|
166
|
+
::Rack::Utils::SYMBOL_TO_STATUS_CODE[symbol.to_sym]
|
163
167
|
end
|
164
168
|
end
|
165
169
|
|
@@ -177,15 +181,13 @@ module RuboCop
|
|
177
181
|
def prefer
|
178
182
|
if node.sym_type?
|
179
183
|
"be_#{node.value}"
|
180
|
-
|
184
|
+
elsif node.int_type?
|
181
185
|
"be_#{symbol}"
|
186
|
+
elsif node.str_type?
|
187
|
+
"be_#{normalize_str}"
|
182
188
|
end
|
183
189
|
end
|
184
190
|
|
185
|
-
def current
|
186
|
-
offense_range.source
|
187
|
-
end
|
188
|
-
|
189
191
|
private
|
190
192
|
|
191
193
|
def symbol
|
@@ -193,7 +195,16 @@ module RuboCop
|
|
193
195
|
end
|
194
196
|
|
195
197
|
def number
|
196
|
-
node.
|
198
|
+
node.value.to_i
|
199
|
+
end
|
200
|
+
|
201
|
+
def normalize_str
|
202
|
+
str = node.value.to_s
|
203
|
+
if str.match?(/\A\d+\z/)
|
204
|
+
::Rack::Utils::SYMBOL_TO_STATUS_CODE.key(str.to_i)
|
205
|
+
else
|
206
|
+
str
|
207
|
+
end
|
197
208
|
end
|
198
209
|
end
|
199
210
|
end
|