rubocop-rspec 1.33.0 → 1.34.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 +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)
|