rubocop-rspec 1.33.0 → 1.34.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -2
- data/README.md +10 -2
- data/config/default.yml +6 -1
- data/lib/rubocop/cop/rspec/any_instance.rb +0 -1
- data/lib/rubocop/cop/rspec/around_block.rb +1 -2
- data/lib/rubocop/cop/rspec/before_after_all.rb +0 -1
- data/lib/rubocop/cop/rspec/context_wording.rb +18 -17
- data/lib/rubocop/cop/rspec/describe_class.rb +1 -1
- data/lib/rubocop/cop/rspec/describe_method.rb +1 -1
- data/lib/rubocop/cop/rspec/describe_symbol.rb +1 -1
- data/lib/rubocop/cop/rspec/described_class.rb +79 -13
- data/lib/rubocop/cop/rspec/empty_example_group.rb +1 -1
- data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +1 -1
- data/lib/rubocop/cop/rspec/example_length.rb +1 -1
- data/lib/rubocop/cop/rspec/example_wording.rb +6 -4
- data/lib/rubocop/cop/rspec/expect_actual.rb +1 -1
- data/lib/rubocop/cop/rspec/expect_output.rb +2 -0
- data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +1 -1
- data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +1 -2
- data/lib/rubocop/cop/rspec/file_path.rb +0 -1
- data/lib/rubocop/cop/rspec/focus.rb +1 -1
- data/lib/rubocop/cop/rspec/hook_argument.rb +0 -1
- 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 +0 -1
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +128 -0
- data/lib/rubocop/cop/rspec/let_before_examples.rb +1 -1
- data/lib/rubocop/cop/rspec/let_setup.rb +2 -4
- data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +1 -2
- data/lib/rubocop/cop/rspec/multiple_describes.rb +1 -1
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +32 -16
- data/lib/rubocop/cop/rspec/multiple_subjects.rb +1 -1
- data/lib/rubocop/cop/rspec/nested_groups.rb +0 -1
- data/lib/rubocop/cop/rspec/overwriting_setup.rb +0 -1
- data/lib/rubocop/cop/rspec/pending.rb +1 -1
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +0 -3
- data/lib/rubocop/cop/rspec/repeated_description.rb +1 -1
- data/lib/rubocop/cop/rspec/repeated_example.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 +0 -1
- data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +1 -1
- data/lib/rubocop/cop/rspec/subject_stub.rb +17 -20
- data/lib/rubocop/cop/rspec/unspecified_exception.rb +1 -4
- 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_cops.rb +1 -0
- data/lib/rubocop/rspec/language.rb +1 -1
- data/lib/rubocop/rspec/top_level_describe.rb +0 -4
- data/lib/rubocop/rspec/version.rb +1 -1
- data/spec/rubocop/cop/rspec/cop_spec.rb +3 -3
- data/spec/rubocop/cop/rspec/describe_class_spec.rb +7 -0
- data/spec/rubocop/cop/rspec/described_class_spec.rb +113 -80
- data/spec/rubocop/cop/rspec/example_wording_spec.rb +33 -0
- data/spec/rubocop/cop/rspec/leaky_constant_declaration_spec.rb +91 -0
- data/spec/rubocop/cop/rspec/let_setup_spec.rb +2 -2
- data/spec/rubocop/cop/rspec/multiple_expectations_spec.rb +64 -37
- data/spec/rubocop/cop/rspec/subject_stub_spec.rb +113 -14
- data/spec/rubocop/rspec/language/selector_set_spec.rb +2 -2
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b93f9fd4cff11c9b4a47a1bffca8e578bcf0e354320b461d63cdab7d01fad49b
|
4
|
+
data.tar.gz: 31244d48dd90be566b9f3b18dbe3f7c40112de41ef9fe9dbcbc282e20da2c66e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca99737cdb9ebea08757e8412974d678c846623798efab61a3a8e3e35ece75ccde9c3bcb41a2e800eeefa465ea955ee2683e843b62c0eda3698a0fa9f562fa05
|
7
|
+
data.tar.gz: ff707c6bd4b46f289beb68127b4b49a214c490914098aaadacf436c0efbf41511ef942cbeb52f50428310788d05fdeaf43be69a6bfe43bf5383fd50d7fe075d9
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,18 @@
|
|
2
2
|
|
3
3
|
## Master (Unreleased)
|
4
4
|
|
5
|
+
## 1.34.0 (2019-07-23)
|
6
|
+
|
7
|
+
* Remove `AggregateFailuresByDefault` config option of `RSpec/MultipleExpectations`. ([@pirj][])
|
8
|
+
* Add `RSpec/LeakyConstantDeclaration` cop. ([@jonatas][], [@pirj][])
|
9
|
+
* Improve `aggregate_failures` metadata detection of `RSpec/MultipleExpectations`. ([@pirj][])
|
10
|
+
* Improve `RSpec/SubjectStub` detection and message. ([@pirj][])
|
11
|
+
* Change message of `RSpec/LetSetup` cop to be more descriptive. ([@foton][])
|
12
|
+
* Improve `RSpec/ExampleWording` to handle interpolated example messages. ([@nc-holodakg][])
|
13
|
+
* Improve detection by allowing the use of `RSpec` as a top-level constant. ([@pirj][])
|
14
|
+
* Fix `RSpec/DescribedClass`'s incorrect detection. ([@pirj][])
|
15
|
+
* Improve `RSpec/DescribedClass`'s ability to detect inside modules and classes. ([@pirj][])
|
16
|
+
|
5
17
|
## 1.33.0 (2019-05-13)
|
6
18
|
|
7
19
|
* Let `RSpec/DescribedClass` pass `Struct` instantiation closures. ([@schmijos][])
|
@@ -202,7 +214,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
202
214
|
* Add [observed_nesting/max_nesting] info to `RSpec/NestedGroups` messages. ([@dgollahon][])
|
203
215
|
* Add `RSpec/ItBehavesLike` cop. ([@dgollahon][])
|
204
216
|
* Add `RSpec/SharedContext` cop. ([@Darhazer][])
|
205
|
-
* `
|
217
|
+
* `RSpec/MultipleExpectations`: Count aggregate_failures block as single expectation. ([@Darhazer][])
|
206
218
|
* Fix `ExpectActual` cop flagging `rspec-rails` routing specs. ([@backus][])
|
207
219
|
* Fix `FilePath` cop not registering offenses for files like `spec/blog/user.rb` when it should be `spec/blog/user_spec.rb`. ([@backus][])
|
208
220
|
|
@@ -310,7 +322,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
310
322
|
* Update to rubocop 0.37.2. ([@nijikon][])
|
311
323
|
* Update ruby versions we test against. ([@nijikon][])
|
312
324
|
* Add `RSpec::NotToNot` cop. ([@miguelfteixeira][])
|
313
|
-
* Add `
|
325
|
+
* Add `RSpec/AnyInstance` cop. ([@mlarraz][])
|
314
326
|
|
315
327
|
## 1.3.1
|
316
328
|
|
@@ -418,3 +430,5 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
|
|
418
430
|
[@mkenyon]: https://github.com/mkenyon
|
419
431
|
[@gsamokovarov]: https://github.com/gsamokovarov
|
420
432
|
[@schmijos]: https://github.com/schmijos
|
433
|
+
[@foton]: https://github.com/foton
|
434
|
+
[@nc-holodakg]: https://github.com/nc-holodakg
|
data/README.md
CHANGED
@@ -32,10 +32,18 @@ ways to do this:
|
|
32
32
|
|
33
33
|
Put this into your `.rubocop.yml`.
|
34
34
|
|
35
|
-
```
|
35
|
+
```yaml
|
36
36
|
require: rubocop-rspec
|
37
37
|
```
|
38
38
|
|
39
|
+
Alternatively, use the following array notation when specifying multiple extensions.
|
40
|
+
|
41
|
+
```yaml
|
42
|
+
require:
|
43
|
+
- rubocop-other-extension
|
44
|
+
- rubocop-rspec
|
45
|
+
```
|
46
|
+
|
39
47
|
Now you can run `rubocop` and it will automatically load the RuboCop RSpec
|
40
48
|
cops together with the standard cops.
|
41
49
|
|
@@ -119,7 +127,7 @@ is a feature of RSpec itself – you can read about it in the [RSpec Documentati
|
|
119
127
|
Enforcing
|
120
128
|
|
121
129
|
```ruby
|
122
|
-
|
130
|
+
RSpec.describe MyClass do
|
123
131
|
...
|
124
132
|
end
|
125
133
|
```
|
data/config/default.yml
CHANGED
@@ -50,7 +50,7 @@ RSpec/BeforeAfterAll:
|
|
50
50
|
StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll
|
51
51
|
|
52
52
|
RSpec/ContextWording:
|
53
|
-
Description:
|
53
|
+
Description: Checks that `context` docstring starts with an allowed prefix.
|
54
54
|
Enabled: true
|
55
55
|
Prefixes:
|
56
56
|
- when
|
@@ -251,6 +251,11 @@ RSpec/LeadingSubject:
|
|
251
251
|
Enabled: true
|
252
252
|
StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeadingSubject
|
253
253
|
|
254
|
+
RSpec/LeakyConstantDeclaration:
|
255
|
+
Description: Checks that no class, module, or constant is declared.
|
256
|
+
Enabled: true
|
257
|
+
StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeakyConstantDeclaration
|
258
|
+
|
254
259
|
RSpec/LetBeforeExamples:
|
255
260
|
Description: Checks for `let` definitions that come after an example.
|
256
261
|
Enabled: true
|
@@ -51,7 +51,7 @@ module RuboCop
|
|
51
51
|
private
|
52
52
|
|
53
53
|
def add_no_arg_offense(node)
|
54
|
-
add_offense(node,
|
54
|
+
add_offense(node, message: MSG_NO_ARG)
|
55
55
|
end
|
56
56
|
|
57
57
|
def check_for_unused_proxy(block, proxy)
|
@@ -63,7 +63,6 @@ module RuboCop
|
|
63
63
|
|
64
64
|
add_offense(
|
65
65
|
proxy,
|
66
|
-
location: :expression,
|
67
66
|
message: format(MSG_UNUSED_ARG, arg: name)
|
68
67
|
)
|
69
68
|
end
|
@@ -3,18 +3,22 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
|
-
# `context`
|
6
|
+
# Checks that `context` docstring starts with an allowed prefix.
|
7
7
|
#
|
8
8
|
# @see https://github.com/reachlocal/rspec-style-guide#context-descriptions
|
9
9
|
# @see http://www.betterspecs.org/#contexts
|
10
10
|
#
|
11
|
-
# @example `Prefixes` configuration
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
# -
|
17
|
-
# -
|
11
|
+
# @example `Prefixes` configuration
|
12
|
+
#
|
13
|
+
# # .rubocop.yml
|
14
|
+
# # RSpec/ContextWording:
|
15
|
+
# # Prefixes:
|
16
|
+
# # - when
|
17
|
+
# # - with
|
18
|
+
# # - without
|
19
|
+
# # - if
|
20
|
+
# # - unless
|
21
|
+
# # - for
|
18
22
|
#
|
19
23
|
# @example
|
20
24
|
# # bad
|
@@ -35,7 +39,8 @@ module RuboCop
|
|
35
39
|
|
36
40
|
def on_block(node)
|
37
41
|
context_wording(node) do |context|
|
38
|
-
add_offense(context,
|
42
|
+
add_offense(context,
|
43
|
+
message: format(MSG, prefixes: joined_prefixes))
|
39
44
|
end
|
40
45
|
end
|
41
46
|
|
@@ -45,14 +50,6 @@ module RuboCop
|
|
45
50
|
!prefixes.include?(description.split.first)
|
46
51
|
end
|
47
52
|
|
48
|
-
def prefixes
|
49
|
-
cop_config['Prefixes'] || []
|
50
|
-
end
|
51
|
-
|
52
|
-
def message
|
53
|
-
format(MSG, prefixes: joined_prefixes)
|
54
|
-
end
|
55
|
-
|
56
53
|
def joined_prefixes
|
57
54
|
quoted = prefixes.map { |prefix| "'#{prefix}'" }
|
58
55
|
return quoted.first if quoted.size == 1
|
@@ -60,6 +57,10 @@ module RuboCop
|
|
60
57
|
quoted << "or #{quoted.pop}"
|
61
58
|
quoted.join(', ')
|
62
59
|
end
|
60
|
+
|
61
|
+
def prefixes
|
62
|
+
cop_config['Prefixes'] || []
|
63
|
+
end
|
63
64
|
end
|
64
65
|
end
|
65
66
|
end
|
@@ -33,7 +33,6 @@ module RuboCop
|
|
33
33
|
# end
|
34
34
|
#
|
35
35
|
class DescribedClass < Cop
|
36
|
-
include RuboCop::RSpec::TopLevelDescribe
|
37
36
|
include ConfigurableEnforcedStyle
|
38
37
|
|
39
38
|
DESCRIBED_CLASS = 'described_class'
|
@@ -48,20 +47,19 @@ module RuboCop
|
|
48
47
|
|
49
48
|
def_node_matcher :scope_changing_syntax?, '{def class module}'
|
50
49
|
|
50
|
+
def_node_matcher :described_constant, <<-PATTERN
|
51
|
+
(block (send _ :describe $(const ...) ...) (args) $_)
|
52
|
+
PATTERN
|
53
|
+
|
51
54
|
def on_block(node)
|
52
|
-
# In case the explicit style is used, we
|
53
|
-
# being described.
|
54
|
-
|
55
|
+
# In case the explicit style is used, we need to remember what's
|
56
|
+
# being described.
|
57
|
+
@described_class, body = described_constant(node)
|
55
58
|
|
56
|
-
return
|
57
|
-
return unless top_level_describe?(describe)
|
59
|
+
return unless body
|
58
60
|
|
59
61
|
find_usage(body) do |match|
|
60
|
-
add_offense(
|
61
|
-
match,
|
62
|
-
location: :expression,
|
63
|
-
message: message(match.const_name)
|
64
|
-
)
|
62
|
+
add_offense(match, message: message(match.const_name))
|
65
63
|
end
|
66
64
|
end
|
67
65
|
|
@@ -108,16 +106,84 @@ module RuboCop
|
|
108
106
|
end
|
109
107
|
|
110
108
|
def skip_blocks?
|
111
|
-
cop_config['SkipBlocks']
|
109
|
+
cop_config['SkipBlocks']
|
112
110
|
end
|
113
111
|
|
114
112
|
def offensive?(node)
|
115
113
|
if style == :described_class
|
116
|
-
|
114
|
+
offensive_described_class?(node)
|
117
115
|
else
|
118
116
|
node.send_type? && node.method_name == :described_class
|
119
117
|
end
|
120
118
|
end
|
119
|
+
|
120
|
+
def offensive_described_class?(node)
|
121
|
+
return unless node.const_type?
|
122
|
+
|
123
|
+
nearest_described_class, = node.each_ancestor(:block)
|
124
|
+
.map { |ancestor| described_constant(ancestor) }.find(&:itself)
|
125
|
+
|
126
|
+
return if nearest_described_class.equal?(node)
|
127
|
+
|
128
|
+
full_const_name(nearest_described_class) == full_const_name(node)
|
129
|
+
end
|
130
|
+
|
131
|
+
def full_const_name(node)
|
132
|
+
collapse_namespace(namespace(node), const_name(node))
|
133
|
+
end
|
134
|
+
|
135
|
+
# @param namespace [Array<Symbol>]
|
136
|
+
# @param const [Array<Symbol>]
|
137
|
+
# @return [Array<Symbol>]
|
138
|
+
# @example
|
139
|
+
# # nil represents base constant
|
140
|
+
# collapse_namespace([], :C) # => [:C]
|
141
|
+
# collapse_namespace([:A, :B], [:C) # => [:A, :B, :C]
|
142
|
+
# collapse_namespace([:A, :B], [:B, :C) # => [:A, :B, :C]
|
143
|
+
# collapse_namespace([:A, :B], [nil, :C) # => [nil, :C]
|
144
|
+
# collapse_namespace([:A, :B], [nil, :B, :C) # => [nil, :B, :C]
|
145
|
+
def collapse_namespace(namespace, const)
|
146
|
+
return const if namespace.empty?
|
147
|
+
return const if const.first.nil?
|
148
|
+
|
149
|
+
start = [0, (namespace.length - const.length)].max
|
150
|
+
max = namespace.length
|
151
|
+
intersection = (start..max).find do |shift|
|
152
|
+
namespace[shift, max - shift] == const[0, max - shift]
|
153
|
+
end
|
154
|
+
[*namespace[0, intersection], *const]
|
155
|
+
end
|
156
|
+
|
157
|
+
# @param node [RuboCop::AST::Node]
|
158
|
+
# @return [Array<Symbol>]
|
159
|
+
# @example
|
160
|
+
# const_name(s(:const, nil, :C)) # => [:C]
|
161
|
+
# const_name(s(:const, s(:const, nil, :M), :C)) # => [:M, :C]
|
162
|
+
# const_name(s(:const, s(:cbase), :C)) # => [nil, :C]
|
163
|
+
def const_name(node)
|
164
|
+
# rubocop:disable InternalAffairs/NodeDestructuring
|
165
|
+
namespace, name = *node
|
166
|
+
# rubocop:enable InternalAffairs/NodeDestructuring
|
167
|
+
if !namespace
|
168
|
+
[name]
|
169
|
+
elsif namespace.cbase_type?
|
170
|
+
[nil, name]
|
171
|
+
else
|
172
|
+
[*const_name(namespace), name]
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# @param node [RuboCop::AST::Node]
|
177
|
+
# @return [Array<Symbol>]
|
178
|
+
# @example
|
179
|
+
# namespace(node) # => [:A, :B, :C]
|
180
|
+
def namespace(node)
|
181
|
+
node
|
182
|
+
.each_ancestor(:class, :module)
|
183
|
+
.reverse_each
|
184
|
+
.flat_map { |ancestor| ancestor.defined_module_name.split('::') }
|
185
|
+
.map(&:to_sym)
|
186
|
+
end
|
121
187
|
end
|
122
188
|
end
|
123
189
|
end
|
@@ -36,10 +36,12 @@ module RuboCop
|
|
36
36
|
SHOULD_PREFIX = /\Ashould(?:n't)?\b/i.freeze
|
37
37
|
IT_PREFIX = /\Ait /i.freeze
|
38
38
|
|
39
|
-
def_node_matcher
|
40
|
-
:
|
41
|
-
|
42
|
-
|
39
|
+
def_node_matcher :it_description, <<-PATTERN
|
40
|
+
(block (send _ :it ${
|
41
|
+
(str $_)
|
42
|
+
(dstr (str $_ ) ...)
|
43
|
+
} ...) ...)
|
44
|
+
PATTERN
|
43
45
|
|
44
46
|
def on_block(node)
|
45
47
|
it_description(node) do |description_node, message|
|
@@ -21,7 +21,9 @@ module RuboCop
|
|
21
21
|
def on_gvasgn(node)
|
22
22
|
return unless inside_example_scope?(node)
|
23
23
|
|
24
|
+
# rubocop:disable InternalAffairs/NodeDestructuring
|
24
25
|
variable_name, _rhs = *node
|
26
|
+
# rubocop:enable InternalAffairs/NodeDestructuring
|
25
27
|
name = variable_name[1..-1]
|
26
28
|
return unless name.eql?('stdout') || name.eql?('stderr')
|
27
29
|
|
@@ -51,8 +51,7 @@ module RuboCop
|
|
51
51
|
return unless n_times_block_without_arg?(node)
|
52
52
|
return unless contains_only_factory?(node.body)
|
53
53
|
|
54
|
-
add_offense(node.send_node,
|
55
|
-
location: :expression, message: MSG_CREATE_LIST)
|
54
|
+
add_offense(node.send_node, message: MSG_CREATE_LIST)
|
56
55
|
end
|
57
56
|
|
58
57
|
def on_send(node)
|