rubocop-rspec 1.39.0 → 1.40.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9bb27c4586307d99c6c4575351d9974dc872229cd91b5f5f4deb99530c7e0297
4
- data.tar.gz: 6efec312480c6800454ceb42eec2905e9d093bcc1f107be2f60c36a0a3ac0f4b
3
+ metadata.gz: 59e10874a1394fa4741d2f03d4e3fc99fc86a708b8973024be0e33f568e20b0a
4
+ data.tar.gz: b33b46623283aebafe40edd9509c58cabe052a4602fdebd97f69250e9f7ea206
5
5
  SHA512:
6
- metadata.gz: 4c0ae32d6609fa83633e18a6fe0172c8d1dc849595180f2a2b2a3c7f673dd50dc6eb695b9c880498be42ca7e9dc468f1f67c43d0677c0ae0e845b8c89630b673
7
- data.tar.gz: c0e23ebca292ecff3d294d4bbe6b9a020be769cb834115f8e9dbd55d3dbd798fda2ddc548799a869b1620810e355ed7aee8a3210fecb5fa77f844a815361c2b8
6
+ metadata.gz: 1e109509a667750018f86fb3fbe6e05cce32a22fb99dde8bcd39ab4bdecb688af372baea3e05b1a156074b8c1f295ae129415356510c72a72face5b49e51b492
7
+ data.tar.gz: fa38c3aa5e06adc57a1ca991e2dc42cb9511580a4214089323c1f76403f923940f845c709ff0393805035766184b2855fab4d31b4af11b5cdea9f278cdf2d87c
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
+ ## 1.40.0 (2020-06-11)
6
+
7
+ * Add new `RSpec/VariableName` cop. ([@tejasbubane][])
8
+ * Add new `RSpec/VariableDefinition` cop. ([@tejasbubane][])
9
+ * Expand `Capybara/VisibilityMatcher` to support more than just `have_selector`. ([@twalpole][])
10
+ * Add new `SpecSuffixOnly` option to `RSpec/FilePath` cop. ([@zdennis][])
11
+ * Allow `RSpec/RepeatedExampleGroupBody` to differ only by described_class. ([@robotdana][])
12
+ * Fix `RSpec/FilePath` detection across sibling directories. ([@rolfschmidt][])
13
+ * Improve the performance of `RSpec/SubjectStub` by an order of magnitude. ([@andrykonchin][])
14
+
5
15
  ## 1.39.0 (2020-05-01)
6
16
 
7
17
  * Fix `RSpec/FilePath` detection when absolute path includes test subject. ([@eitoball][])
@@ -503,3 +513,8 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
503
513
  [@aried3r]: https://github.com/aried3r
504
514
  [@AlexWayfer]: https://github.com/AlexWayfer
505
515
  [@tejasbubane]: https://github.com/tejasbubane
516
+ [@twalpole]: https://github.com/twalpole
517
+ [@zdennis]: https://github.com/zdennis
518
+ [@robotdana]: https://github.com/robotdana
519
+ [@rolfschmidt]: https://github.com/rolfschmidt
520
+ [@andrykonchin]: https://github.com/andrykonchin
data/README.md CHANGED
@@ -67,27 +67,7 @@ rubocop-rspec is available on Code Climate as part of the rubocop engine. [Learn
67
67
 
68
68
  ## Documentation
69
69
 
70
- You can read more about RuboCop-RSpec in its [official manual](http://rubocop-rspec.readthedocs.io).
71
-
72
- ## Inspecting files that don't end with `_spec.rb`
73
-
74
- By default, `rubocop-rspec` only inspects code within paths ending in `_spec.rb` or including `spec/`. You can override this setting in your config file by specifying one or more patterns:
75
-
76
- ```yaml
77
- # Inspect all files
78
- AllCops:
79
- RSpec:
80
- Patterns:
81
- - '.+'
82
- ```
83
-
84
- ```yaml
85
- # Inspect only files ending with `_test.rb`
86
- AllCops:
87
- RSpec:
88
- Patterns:
89
- - '_test.rb$'
90
- ```
70
+ You can read more about RuboCop-RSpec in its [official manual](https://docs.rubocop.org/rubocop-rspec).
91
71
 
92
72
  ## The Cops
93
73
 
@@ -104,46 +84,6 @@ RSpec/FilePath:
104
84
  - spec/my_poorly_named_spec_file.rb
105
85
  ```
106
86
 
107
- ## Non-goals of RuboCop RSpec
108
-
109
- ### Enforcing `should` vs. `expect` syntax
110
-
111
- Enforcing
112
-
113
- ```ruby
114
- expect(calculator.compute(line_item)).to eq(5)
115
- ```
116
-
117
- over
118
-
119
- ```ruby
120
- calculator.compute(line_item).should == 5
121
- ```
122
-
123
- is a feature of RSpec itself – you can read about it in the [RSpec Documentation](https://relishapp.com/rspec/rspec-expectations/docs/syntax-configuration#disable-should-syntax)
124
-
125
- ### Enforcing an explicit RSpec receiver for top-level methods (disabling monkey patching)
126
-
127
- Enforcing
128
-
129
- ```ruby
130
- RSpec.describe MyClass do
131
- ...
132
- end
133
- ```
134
-
135
- over
136
-
137
- ```ruby
138
- describe MyClass do
139
- ...
140
- end
141
- ```
142
-
143
- can be achieved using RSpec's `disable_monkey_patching!` method, which you can read more about in the [RSpec Documentation](https://relishapp.com/rspec/rspec-core/v/3-7/docs/configuration/zero-monkey-patching-mode#monkey-patched-methods-are-undefined-with-%60disable-monkey-patching!%60). This will also prevent `should` from being defined on every object in your system.
144
-
145
- Before disabling `should` you will need all your specs to use the `expect` syntax. You can use [Transpec](http://yujinakayama.me/transpec/), which will do the conversion for you.
146
-
147
87
  ## Contributing
148
88
 
149
89
  Checkout the [contribution guidelines](.github/CONTRIBUTING.md).
@@ -13,31 +13,37 @@ AllCops:
13
13
  RSpec/AlignLeftLetBrace:
14
14
  Description: Checks that left braces for adjacent single line lets are aligned.
15
15
  Enabled: false
16
+ VersionAdded: '1.16'
16
17
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AlignLeftLetBrace
17
18
 
18
19
  RSpec/AlignRightLetBrace:
19
20
  Description: Checks that right braces for adjacent single line lets are aligned.
20
21
  Enabled: false
22
+ VersionAdded: '1.16'
21
23
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AlignRightLetBrace
22
24
 
23
25
  RSpec/AnyInstance:
24
26
  Description: Check that instances are not being stubbed globally.
25
27
  Enabled: true
28
+ VersionAdded: '1.4'
26
29
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AnyInstance
27
30
 
28
31
  RSpec/AroundBlock:
29
32
  Description: Checks that around blocks actually run the test.
30
33
  Enabled: true
34
+ VersionAdded: '1.11'
31
35
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AroundBlock
32
36
 
33
37
  RSpec/Be:
34
38
  Description: Check for expectations where `be` is used without argument.
35
39
  Enabled: true
40
+ VersionAdded: '1.25'
36
41
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Be
37
42
 
38
43
  RSpec/BeEql:
39
44
  Description: Check for expectations where `be(...)` can replace `eql(...)`.
40
45
  Enabled: true
46
+ VersionAdded: '1.7'
41
47
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEql
42
48
 
43
49
  RSpec/BeforeAfterAll:
@@ -47,11 +53,13 @@ RSpec/BeforeAfterAll:
47
53
  - spec/spec_helper.rb
48
54
  - spec/rails_helper.rb
49
55
  - spec/support/**/*.rb
56
+ VersionAdded: '1.12'
50
57
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll
51
58
 
52
59
  RSpec/ContextMethod:
53
60
  Description: "`context` should not be used for specifying methods."
54
61
  Enabled: true
62
+ VersionAdded: '1.36'
55
63
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextMethod
56
64
 
57
65
  RSpec/ContextWording:
@@ -61,86 +69,103 @@ RSpec/ContextWording:
61
69
  - when
62
70
  - with
63
71
  - without
72
+ VersionAdded: '1.20'
73
+ VersionChanged: 1.20.1
64
74
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextWording
65
75
 
66
76
  RSpec/DescribeClass:
67
77
  Description: Check that the first argument to the top level describe is a constant.
68
78
  Enabled: true
79
+ VersionAdded: '1.0'
69
80
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeClass
70
81
 
71
82
  RSpec/DescribeMethod:
72
83
  Description: Checks that the second argument to `describe` specifies a method.
73
84
  Enabled: true
85
+ VersionAdded: '1.0'
74
86
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeMethod
75
87
 
76
88
  RSpec/DescribeSymbol:
77
89
  Description: Avoid describing symbols.
78
90
  Enabled: true
91
+ VersionAdded: '1.15'
79
92
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeSymbol
80
93
 
81
94
  RSpec/DescribedClass:
82
95
  Description: Checks that tests use `described_class`.
83
- SkipBlocks: false
84
96
  Enabled: true
97
+ SkipBlocks: false
85
98
  EnforcedStyle: described_class
86
99
  SupportedStyles:
87
100
  - described_class
88
101
  - explicit
102
+ SafeAutoCorrect: false
103
+ VersionAdded: '1.0'
104
+ VersionChanged: '1.11'
89
105
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClass
90
106
 
91
107
  RSpec/DescribedClassModuleWrapping:
92
108
  Description: Avoid opening modules and defining specs within them.
93
109
  Enabled: false
110
+ VersionAdded: '1.37'
94
111
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClassModuleWrapping
95
112
 
96
113
  RSpec/Dialect:
97
114
  Description: This cop enforces custom RSpec dialects.
98
115
  Enabled: false
99
116
  PreferredMethods: {}
117
+ VersionAdded: '1.33'
100
118
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Dialect
101
119
 
102
120
  RSpec/EmptyExampleGroup:
103
121
  Description: Checks if an example group does not include any tests.
104
122
  Enabled: true
105
123
  CustomIncludeMethods: []
124
+ VersionAdded: '1.7'
106
125
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyExampleGroup
107
126
 
108
127
  RSpec/EmptyHook:
109
128
  Description: Checks for empty before and after hooks.
110
129
  Enabled: true
111
- VersionAdded: 1.39.0
130
+ VersionAdded: '1.39'
112
131
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyHook
113
132
 
114
133
  RSpec/EmptyLineAfterExample:
115
134
  Description: Checks if there is an empty line after example blocks.
116
135
  Enabled: true
117
136
  AllowConsecutiveOneLiners: true
137
+ VersionAdded: '1.36'
118
138
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExample
119
139
 
120
140
  RSpec/EmptyLineAfterExampleGroup:
121
141
  Description: Checks if there is an empty line after example group blocks.
122
142
  Enabled: true
143
+ VersionAdded: '1.27'
123
144
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExampleGroup
124
145
 
125
146
  RSpec/EmptyLineAfterFinalLet:
126
147
  Description: Checks if there is an empty line after the last let block.
127
148
  Enabled: true
149
+ VersionAdded: '1.14'
128
150
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterFinalLet
129
151
 
130
152
  RSpec/EmptyLineAfterHook:
131
153
  Description: Checks if there is an empty line after hook blocks.
132
154
  Enabled: true
155
+ VersionAdded: '1.27'
133
156
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterHook
134
157
 
135
158
  RSpec/EmptyLineAfterSubject:
136
159
  Description: Checks if there is an empty line after subject block.
137
160
  Enabled: true
161
+ VersionAdded: '1.14'
138
162
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterSubject
139
163
 
140
164
  RSpec/ExampleLength:
141
165
  Description: Checks for long examples.
142
166
  Enabled: true
143
167
  Max: 5
168
+ VersionAdded: '1.5'
144
169
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleLength
145
170
 
146
171
  RSpec/ExampleWithoutDescription:
@@ -151,6 +176,7 @@ RSpec/ExampleWithoutDescription:
151
176
  - always_allow
152
177
  - single_line_only
153
178
  - disallow
179
+ VersionAdded: '1.22'
154
180
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWithoutDescription
155
181
 
156
182
  RSpec/ExampleWording:
@@ -162,6 +188,8 @@ RSpec/ExampleWording:
162
188
  have: has
163
189
  HAVE: HAS
164
190
  IgnoredWords: []
191
+ VersionAdded: '1.0'
192
+ VersionChanged: '1.2'
165
193
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWording
166
194
 
167
195
  RSpec/ExpectActual:
@@ -169,6 +197,7 @@ RSpec/ExpectActual:
169
197
  Enabled: true
170
198
  Exclude:
171
199
  - spec/routing/**/*
200
+ VersionAdded: '1.7'
172
201
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectActual
173
202
 
174
203
  RSpec/ExpectChange:
@@ -178,30 +207,37 @@ RSpec/ExpectChange:
178
207
  SupportedStyles:
179
208
  - method_call
180
209
  - block
210
+ VersionAdded: '1.22'
181
211
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectChange
182
212
 
183
213
  RSpec/ExpectInHook:
184
- Enabled: true
185
214
  Description: Do not use `expect` in hooks such as `before`.
215
+ Enabled: true
216
+ VersionAdded: '1.16'
186
217
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectInHook
187
218
 
188
219
  RSpec/ExpectOutput:
189
220
  Description: Checks for opportunities to use `expect { ... }.to output`.
190
221
  Enabled: true
222
+ VersionAdded: '1.10'
191
223
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExpectOutput
192
224
 
193
225
  RSpec/FilePath:
194
- Description: Checks that spec file paths are consistent with the test subject.
226
+ Description: Checks that spec file paths are consistent and well-formed.
195
227
  Enabled: true
196
228
  CustomTransform:
197
229
  RuboCop: rubocop
198
230
  RSpec: rspec
199
231
  IgnoreMethods: false
232
+ SpecSuffixOnly: false
233
+ VersionAdded: '1.2'
234
+ VersionChanged: '1.40'
200
235
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FilePath
201
236
 
202
237
  RSpec/Focus:
203
238
  Description: Checks if examples are focused.
204
239
  Enabled: true
240
+ VersionAdded: '1.5'
205
241
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Focus
206
242
 
207
243
  RSpec/HookArgument:
@@ -212,16 +248,19 @@ RSpec/HookArgument:
212
248
  - implicit
213
249
  - each
214
250
  - example
251
+ VersionAdded: '1.7'
215
252
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HookArgument
216
253
 
217
254
  RSpec/HooksBeforeExamples:
218
- Enabled: true
219
255
  Description: Checks for before/around/after hooks that come after an example.
256
+ Enabled: true
257
+ VersionAdded: '1.29'
220
258
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/HooksBeforeExamples
221
259
 
222
260
  RSpec/ImplicitBlockExpectation:
223
261
  Description: Check that implicit block expectation syntax is not used.
224
262
  Enabled: true
263
+ VersionAdded: '1.35'
225
264
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitBlockExpectation
226
265
 
227
266
  RSpec/ImplicitExpect:
@@ -231,32 +270,39 @@ RSpec/ImplicitExpect:
231
270
  SupportedStyles:
232
271
  - is_expected
233
272
  - should
273
+ VersionAdded: '1.8'
234
274
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitExpect
235
275
 
236
276
  RSpec/ImplicitSubject:
237
- Enabled: true
238
277
  Description: Checks for usage of implicit subject (`is_expected` / `should`).
278
+ Enabled: true
239
279
  EnforcedStyle: single_line_only
240
280
  SupportedStyles:
241
281
  - single_line_only
242
282
  - single_statement_only
243
283
  - disallow
284
+ VersionAdded: '1.29'
285
+ VersionChanged: '1.30'
244
286
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitSubject
245
287
 
246
288
  RSpec/InstanceSpy:
247
289
  Description: Checks for `instance_double` used with `have_received`.
248
290
  Enabled: true
291
+ VersionAdded: '1.12'
249
292
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InstanceSpy
250
293
 
251
294
  RSpec/InstanceVariable:
252
295
  Description: Checks for instance variable usage in specs.
253
- AssignmentOnly: false
254
296
  Enabled: true
297
+ AssignmentOnly: false
298
+ VersionAdded: '1.0'
299
+ VersionChanged: '1.7'
255
300
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InstanceVariable
256
301
 
257
302
  RSpec/InvalidPredicateMatcher:
258
303
  Description: Checks invalid usage for predicate matcher.
259
304
  Enabled: true
305
+ VersionAdded: '1.16'
260
306
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/InvalidPredicateMatcher
261
307
 
262
308
  RSpec/ItBehavesLike:
@@ -266,36 +312,45 @@ RSpec/ItBehavesLike:
266
312
  SupportedStyles:
267
313
  - it_behaves_like
268
314
  - it_should_behave_like
315
+ VersionAdded: '1.13'
269
316
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ItBehavesLike
270
317
 
271
318
  RSpec/IteratedExpectation:
272
319
  Description: Check that `all` matcher is used instead of iterating over an array.
273
320
  Enabled: true
321
+ VersionAdded: '1.14'
274
322
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IteratedExpectation
275
323
 
276
324
  RSpec/LeadingSubject:
277
325
  Description: Enforce that subject is the first definition in the test.
278
326
  Enabled: true
327
+ VersionAdded: '1.7'
328
+ VersionChanged: '1.14'
279
329
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeadingSubject
280
330
 
281
331
  RSpec/LeakyConstantDeclaration:
282
332
  Description: Checks that no class, module, or constant is declared.
283
333
  Enabled: true
334
+ VersionAdded: '1.35'
284
335
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LeakyConstantDeclaration
285
336
 
286
337
  RSpec/LetBeforeExamples:
287
338
  Description: Checks for `let` definitions that come after an example.
288
339
  Enabled: true
340
+ VersionAdded: '1.16'
341
+ VersionChanged: '1.22'
289
342
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LetBeforeExamples
290
343
 
291
344
  RSpec/LetSetup:
292
345
  Description: Checks unreferenced `let!` calls being used for test setup.
293
346
  Enabled: true
347
+ VersionAdded: '1.7'
294
348
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/LetSetup
295
349
 
296
350
  RSpec/MessageChain:
297
351
  Description: Check that chains of messages are not being stubbed.
298
352
  Enabled: true
353
+ VersionAdded: '1.7'
299
354
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageChain
300
355
 
301
356
  RSpec/MessageExpectation:
@@ -305,6 +360,8 @@ RSpec/MessageExpectation:
305
360
  SupportedStyles:
306
361
  - allow
307
362
  - expect
363
+ VersionAdded: '1.7'
364
+ VersionChanged: '1.8'
308
365
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageExpectation
309
366
 
310
367
  RSpec/MessageSpies:
@@ -314,58 +371,70 @@ RSpec/MessageSpies:
314
371
  SupportedStyles:
315
372
  - have_received
316
373
  - receive
374
+ VersionAdded: '1.9'
317
375
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MessageSpies
318
376
 
319
377
  RSpec/MissingExampleGroupArgument:
320
378
  Description: Checks that the first argument to an example group is not empty.
321
379
  Enabled: true
380
+ VersionAdded: '1.28'
322
381
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MissingExampleGroupArgument
323
382
 
324
383
  RSpec/MultipleDescribes:
325
384
  Description: Checks for multiple top level describes.
326
385
  Enabled: true
386
+ VersionAdded: '1.0'
327
387
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleDescribes
328
388
 
329
389
  RSpec/MultipleExpectations:
330
390
  Description: Checks if examples contain too many `expect` calls.
331
391
  Enabled: true
332
392
  Max: 1
393
+ VersionAdded: '1.7'
394
+ VersionChanged: '1.21'
333
395
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleExpectations
334
396
 
335
397
  RSpec/MultipleSubjects:
336
398
  Description: Checks if an example group defines `subject` multiple times.
337
399
  Enabled: true
400
+ VersionAdded: '1.16'
338
401
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleSubjects
339
402
 
340
403
  RSpec/NamedSubject:
341
404
  Description: Checks for explicitly referenced test subjects.
342
405
  Enabled: true
343
406
  IgnoreSharedExamples: true
407
+ VersionAdded: 1.5.3
344
408
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NamedSubject
345
409
 
346
410
  RSpec/NestedGroups:
347
411
  Description: Checks for nested example groups.
348
412
  Enabled: true
349
413
  Max: 3
414
+ VersionAdded: '1.7'
415
+ VersionChanged: '1.10'
350
416
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NestedGroups
351
417
 
352
418
  RSpec/NotToNot:
353
419
  Description: Checks for consistent method usage for negating expectations.
420
+ Enabled: true
354
421
  EnforcedStyle: not_to
355
422
  SupportedStyles:
356
423
  - not_to
357
424
  - to_not
358
- Enabled: true
425
+ VersionAdded: '1.4'
359
426
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NotToNot
360
427
 
361
428
  RSpec/OverwritingSetup:
362
- Enabled: true
363
429
  Description: Checks if there is a let/subject that overwrites an existing one.
430
+ Enabled: true
431
+ VersionAdded: '1.14'
364
432
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/OverwritingSetup
365
433
 
366
434
  RSpec/Pending:
367
- Enabled: false
368
435
  Description: Checks for any pending or skipped examples.
436
+ Enabled: false
437
+ VersionAdded: '1.25'
369
438
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Pending
370
439
 
371
440
  RSpec/PredicateMatcher:
@@ -377,109 +446,154 @@ RSpec/PredicateMatcher:
377
446
  SupportedStyles:
378
447
  - inflected
379
448
  - explicit
449
+ SafeAutoCorrect: false
450
+ VersionAdded: '1.16'
380
451
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/PredicateMatcher
381
452
 
382
453
  RSpec/ReceiveCounts:
383
- Enabled: true
384
454
  Description: Check for `once` and `twice` receive counts matchers usage.
455
+ Enabled: true
456
+ VersionAdded: '1.26'
385
457
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveCounts
386
458
 
387
459
  RSpec/ReceiveNever:
388
- Enabled: true
389
460
  Description: Prefer `not_to receive(...)` over `receive(...).never`.
461
+ Enabled: true
462
+ VersionAdded: '1.28'
390
463
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReceiveNever
391
464
 
392
465
  RSpec/RepeatedDescription:
393
- Enabled: true
394
466
  Description: Check for repeated description strings in example groups.
467
+ Enabled: true
468
+ VersionAdded: '1.9'
395
469
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedDescription
396
470
 
397
471
  RSpec/RepeatedExample:
398
- Enabled: true
399
472
  Description: Check for repeated examples within example groups.
473
+ Enabled: true
474
+ VersionAdded: '1.10'
400
475
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExample
401
476
 
402
477
  RSpec/RepeatedExampleGroupBody:
403
- Enabled: true
404
478
  Description: Check for repeated describe and context block body.
479
+ Enabled: true
480
+ VersionAdded: '1.38'
405
481
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExampleGroupBody
406
482
 
407
483
  RSpec/RepeatedExampleGroupDescription:
408
- Enabled: true
409
484
  Description: Check for repeated example group descriptions.
485
+ Enabled: true
486
+ VersionAdded: '1.38'
410
487
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/RepeatedExampleGroupDescription
411
488
 
412
489
  RSpec/ReturnFromStub:
413
- Enabled: true
414
490
  Description: Checks for consistent style of stub's return setting.
491
+ Enabled: true
415
492
  EnforcedStyle: and_return
416
493
  SupportedStyles:
417
494
  - and_return
418
495
  - block
496
+ VersionAdded: '1.16'
497
+ VersionChanged: '1.22'
419
498
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReturnFromStub
420
499
 
421
500
  RSpec/ScatteredLet:
422
501
  Description: Checks for let scattered across the example group.
423
502
  Enabled: true
424
- StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredLet
503
+ VersionAdded: '1.14'
425
504
  VersionChanged: '1.39'
505
+ StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredLet
426
506
 
427
507
  RSpec/ScatteredSetup:
428
508
  Description: Checks for setup scattered across multiple hooks in an example group.
429
509
  Enabled: true
510
+ VersionAdded: '1.10'
430
511
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredSetup
431
512
 
432
513
  RSpec/SharedContext:
433
514
  Description: Checks for proper shared_context and shared_examples usage.
434
515
  Enabled: true
516
+ VersionAdded: '1.13'
435
517
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SharedContext
436
518
 
437
519
  RSpec/SharedExamples:
438
520
  Description: Enforces use of string to titleize shared examples.
439
521
  Enabled: true
522
+ VersionAdded: '1.25'
440
523
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SharedExamples
441
524
 
442
525
  RSpec/SingleArgumentMessageChain:
443
526
  Description: Checks that chains of messages contain more than one element.
444
527
  Enabled: true
528
+ VersionAdded: '1.9'
529
+ VersionChanged: '1.10'
445
530
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SingleArgumentMessageChain
446
531
 
447
532
  RSpec/SubjectStub:
448
533
  Description: Checks for stubbed test subjects.
449
534
  Enabled: true
535
+ VersionAdded: '1.7'
450
536
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SubjectStub
451
537
 
452
538
  RSpec/UnspecifiedException:
453
539
  Description: Checks for a specified error in checking raised errors.
454
540
  Enabled: true
541
+ VersionAdded: '1.30'
455
542
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/UnspecifiedException
456
543
 
544
+ RSpec/VariableDefinition:
545
+ Description: Checks that memoized helpers names are symbols or strings.
546
+ Enabled: true
547
+ EnforcedStyle: symbols
548
+ SupportedStyles:
549
+ - symbols
550
+ - strings
551
+ VersionAdded: '1.40'
552
+ StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableDefinition
553
+
554
+ RSpec/VariableName:
555
+ Description: Checks that memoized helper names use the configured style.
556
+ Enabled: true
557
+ EnforcedStyle: snake_case
558
+ SupportedStyles:
559
+ - snake_case
560
+ - camelCase
561
+ VersionAdded: '1.40'
562
+ StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VariableName
563
+
457
564
  RSpec/VerifiedDoubles:
458
565
  Description: Prefer using verifying doubles over normal doubles.
459
566
  Enabled: true
460
567
  IgnoreNameless: true
461
568
  IgnoreSymbolicNames: false
569
+ VersionAdded: 1.2.1
570
+ VersionChanged: '1.5'
462
571
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubles
463
572
 
464
573
  RSpec/VoidExpect:
465
574
  Description: This cop checks void `expect()`.
466
575
  Enabled: true
576
+ VersionAdded: '1.16'
467
577
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VoidExpect
468
578
 
469
579
  RSpec/Yield:
470
580
  Description: This cop checks for calling a block within a stub.
471
581
  Enabled: true
582
+ VersionAdded: '1.32'
472
583
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Yield
473
584
 
474
585
  Capybara/CurrentPathExpectation:
475
586
  Description: Checks that no expectations are set on Capybara's `current_path`.
476
587
  Enabled: true
588
+ VersionAdded: '1.18'
477
589
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/CurrentPathExpectation
478
590
 
479
591
  Capybara/FeatureMethods:
480
592
  Description: Checks for consistent method usage in feature specs.
481
593
  Enabled: true
482
594
  EnabledMethods: []
595
+ VersionAdded: '1.17'
596
+ VersionChanged: '1.25'
483
597
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/FeatureMethods
484
598
 
485
599
  Capybara/VisibilityMatcher:
@@ -491,6 +605,7 @@ Capybara/VisibilityMatcher:
491
605
  FactoryBot/AttributeDefinedStatically:
492
606
  Description: Always declare attribute values as blocks.
493
607
  Enabled: true
608
+ VersionAdded: '1.28'
494
609
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/AttributeDefinedStatically
495
610
 
496
611
  FactoryBot/CreateList:
@@ -500,11 +615,13 @@ FactoryBot/CreateList:
500
615
  SupportedStyles:
501
616
  - create_list
502
617
  - n_times
618
+ VersionAdded: '1.25'
503
619
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/CreateList
504
620
 
505
621
  FactoryBot/FactoryClassName:
506
622
  Description: Use string value when setting the class attribute explicitly.
507
623
  Enabled: true
624
+ VersionAdded: '1.37'
508
625
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/FactoryClassName
509
626
 
510
627
  Rails/HttpStatus:
@@ -514,4 +631,5 @@ Rails/HttpStatus:
514
631
  SupportedStyles:
515
632
  - numeric
516
633
  - symbolic
634
+ VersionAdded: '1.23'
517
635
  StyleGuide: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HttpStatus
@@ -17,6 +17,7 @@ require_relative 'rubocop/rspec/concept'
17
17
  require_relative 'rubocop/rspec/example_group'
18
18
  require_relative 'rubocop/rspec/example'
19
19
  require_relative 'rubocop/rspec/hook'
20
+ require_relative 'rubocop/rspec/variable'
20
21
  require_relative 'rubocop/cop/rspec/cop'
21
22
  require_relative 'rubocop/rspec/align_let_brace'
22
23
  require_relative 'rubocop/rspec/factory_bot'
@@ -18,35 +18,50 @@ module RuboCop
18
18
  #
19
19
  # # bad
20
20
  # expect(page).to have_selector('.foo', visible: false)
21
- #
22
- # # bad
23
- # expect(page).to have_selector('.foo', visible: true)
24
- #
25
- # # good
26
- # expect(page).to have_selector('.foo', visible: :all)
27
- #
28
- # # good
29
- # expect(page).to have_selector('.foo', visible: :hidden)
21
+ # expect(page).to have_css('.foo', visible: true)
22
+ # expect(page).to have_link('my link', visible: false)
30
23
  #
31
24
  # # good
32
25
  # expect(page).to have_selector('.foo', visible: :visible)
26
+ # expect(page).to have_css('.foo', visible: :all)
27
+ # expect(page).to have_link('my link', visible: :hidden)
33
28
  #
34
29
  class VisibilityMatcher < Cop
35
30
  MSG_FALSE = 'Use `:all` or `:hidden` instead of `false`.'
36
31
  MSG_TRUE = 'Use `:visible` instead of `true`.'
32
+ CAPYBARA_MATCHER_METHODS = %i[
33
+ have_selector
34
+ have_css
35
+ have_xpath
36
+ have_link
37
+ have_button
38
+ have_field
39
+ have_select
40
+ have_table
41
+ have_checked_field
42
+ have_unchecked_field
43
+ have_text
44
+ have_content
45
+ ].freeze
37
46
 
38
47
  def_node_matcher :visible_true?, <<~PATTERN
39
- (send nil? :have_selector ... (hash <$(pair (sym :visible) true) ...>))
48
+ (send nil? #capybara_matcher? ... (hash <$(pair (sym :visible) true) ...>))
40
49
  PATTERN
41
50
 
42
51
  def_node_matcher :visible_false?, <<~PATTERN
43
- (send nil? :have_selector ... (hash <$(pair (sym :visible) false) ...>))
52
+ (send nil? #capybara_matcher? ... (hash <$(pair (sym :visible) false) ...>))
44
53
  PATTERN
45
54
 
46
55
  def on_send(node)
47
56
  visible_false?(node) { |arg| add_offense(arg, message: MSG_FALSE) }
48
57
  visible_true?(node) { |arg| add_offense(arg, message: MSG_TRUE) }
49
58
  end
59
+
60
+ private
61
+
62
+ def capybara_matcher?(method_name)
63
+ CAPYBARA_MATCHER_METHODS.include? method_name
64
+ end
50
65
  end
51
66
  end
52
67
  end
@@ -2,28 +2,8 @@
2
2
 
3
3
  module RuboCop
4
4
  module Cop
5
- WorkaroundCop = Cop.dup
6
-
7
- # Clone of the the normal RuboCop::Cop::Cop class so we can rewrite
8
- # the inherited method without breaking functionality
9
- class WorkaroundCop
10
- # Remove the Cop.inherited method to be a noop. Our RSpec::Cop
11
- # class will invoke the inherited hook instead
12
- class << self
13
- undef inherited
14
- def inherited(*) end
15
- end
16
-
17
- # Special case `Module#<` so that the rspec support rubocop exports
18
- # is compatible with our subclass
19
- def self.<(other)
20
- other.equal?(RuboCop::Cop::Cop) || super
21
- end
22
- end
23
- private_constant(:WorkaroundCop)
24
-
25
5
  module RSpec
26
- # @abstract parent class to rspec cops
6
+ # @abstract parent class to RSpec cops
27
7
  #
28
8
  # The criteria for whether rubocop-rspec analyzes a certain ruby file
29
9
  # is configured via `AllCops/RSpec`. For example, if you want to
@@ -31,13 +11,13 @@ module RuboCop
31
11
  # then you could add this to your configuration:
32
12
  #
33
13
  # @example configuring analyzed paths
34
- #
35
- # AllCops:
36
- # RSpec:
37
- # Patterns:
38
- # - '_test.rb$'
39
- # - '(?:^|/)test/'
40
- class Cop < WorkaroundCop
14
+ # # .rubocop.yml
15
+ # # AllCops:
16
+ # # RSpec:
17
+ # # Patterns:
18
+ # # - '_test.rb$'
19
+ # # - '(?:^|/)test/'
20
+ class Cop < ::RuboCop::Cop::Cop
41
21
  include RuboCop::RSpec::Language
42
22
  include RuboCop::RSpec::Language::NodePattern
43
23
 
@@ -3,10 +3,11 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
- # Checks that spec file paths are consistent with the test subject.
6
+ # Checks that spec file paths are consistent and well-formed.
7
7
  #
8
- # Checks the path of the spec file and enforces that it reflects the
9
- # described class/module and its optionally called out method.
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,6 +46,16 @@ module RuboCop
41
46
  # # good
42
47
  # my_class_spec.rb # describe MyClass, '#method'
43
48
  #
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
+ #
44
59
  class FilePath < Cop
45
60
  include RuboCop::RSpec::TopLevelDescribe
46
61
 
@@ -70,9 +85,15 @@ module RuboCop
70
85
  end
71
86
 
72
87
  def glob_for((described_class, method_name))
88
+ return glob_for_spec_suffix_only? if spec_suffix_only?
89
+
73
90
  "#{expected_path(described_class)}#{name_glob(method_name)}*_spec.rb"
74
91
  end
75
92
 
93
+ def glob_for_spec_suffix_only?
94
+ '*_spec.rb'
95
+ end
96
+
76
97
  def name_glob(name)
77
98
  return unless name&.str_type?
78
99
 
@@ -105,12 +126,17 @@ module RuboCop
105
126
  def filename_ends_with?(glob)
106
127
  filename =
107
128
  RuboCop::PathUtil.relative_path(processed_source.buffer.name)
129
+ .gsub('../', '')
108
130
  File.fnmatch?("*#{glob}", filename)
109
131
  end
110
132
 
111
133
  def relevant_rubocop_rspec_file?(_file)
112
134
  true
113
135
  end
136
+
137
+ def spec_suffix_only?
138
+ cop_config['SpecSuffixOnly']
139
+ end
114
140
  end
115
141
  end
116
142
  end
@@ -70,6 +70,7 @@ module RuboCop
70
70
  'to describe HTTP status code.'
71
71
 
72
72
  attr_reader :node
73
+
73
74
  def initialize(node)
74
75
  @node = node
75
76
  end
@@ -110,6 +111,7 @@ module RuboCop
110
111
  ALLOWED_STATUSES = %i[error success missing redirect].freeze
111
112
 
112
113
  attr_reader :node
114
+
113
115
  def initialize(node)
114
116
  @node = node
115
117
  end
@@ -34,6 +34,15 @@ module RuboCop
34
34
  # it { cool_predicate }
35
35
  # end
36
36
  #
37
+ # # good
38
+ # context Array do
39
+ # it { is_expected.to respond_to :each }
40
+ # end
41
+ #
42
+ # context Hash do
43
+ # it { is_expected.to respond_to :each }
44
+ # end
45
+ #
37
46
  class RepeatedExampleGroupBody < Cop
38
47
  MSG = 'Repeated %<group>s block body on line(s) %<loc>s'
39
48
 
@@ -43,6 +52,7 @@ module RuboCop
43
52
 
44
53
  def_node_matcher :metadata, '(block (send _ _ _ $...) ...)'
45
54
  def_node_matcher :body, '(block _ args $...)'
55
+ def_node_matcher :const_arg, '(block (send _ _ $const ...) ...)'
46
56
 
47
57
  def_node_matcher :skip_or_pending?, <<-PATTERN
48
58
  (block <(send nil? {:skip :pending}) ...>)
@@ -75,7 +85,7 @@ module RuboCop
75
85
  end
76
86
 
77
87
  def signature_keys(group)
78
- [metadata(group), body(group)]
88
+ [metadata(group), body(group), const_arg(group)]
79
89
  end
80
90
 
81
91
  def message(group, repeats)
@@ -47,6 +47,7 @@ module RuboCop
47
47
  'to titleize shared examples.'
48
48
 
49
49
  attr_reader :node
50
+
50
51
  def initialize(node)
51
52
  @node = node
52
53
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'set'
4
+
3
5
  module RuboCop
4
6
  module Cop
5
7
  module RSpec
@@ -75,70 +77,46 @@ module RuboCop
75
77
 
76
78
  def on_block(node)
77
79
  return unless example_group?(node)
80
+ return if (processed_example_groups & node.ancestors).any?
81
+
82
+ processed_example_groups << node
83
+ @explicit_subjects = find_all_explicit_subjects(node)
78
84
 
79
- find_subject_stub(node) do |stub|
85
+ find_subject_expectations(node) do |stub|
80
86
  add_offense(stub)
81
87
  end
82
88
  end
83
89
 
84
90
  private
85
91
 
86
- # Find subjects within tree and then find (send) nodes for that subject
87
- #
88
- # @param node [RuboCop::Node] example group
89
- #
90
- # @yield [RuboCop::Node] message expectations for subject
91
- def find_subject_stub(node, &block)
92
- find_subject(node) do |subject_name, context|
93
- find_subject_expectation(context, subject_name, &block)
94
- end
92
+ def processed_example_groups
93
+ @processed_example_groups ||= Set.new
95
94
  end
96
95
 
97
- # Find a subject message expectation
98
- #
99
- # @param node [RuboCop::Node]
100
- # @param subject_name [Symbol] name of subject
101
- #
102
- # @yield [RuboCop::Node] message expectation
103
- def find_subject_expectation(node, subject_name, &block)
104
- # Do not search node if it is an example group with its own subject.
105
- return if example_group?(node) && redefines_subject?(node)
106
-
107
- # Yield the current node if it is a message expectation.
108
- yield(node) if message_expectation?(node, subject_name)
96
+ def find_all_explicit_subjects(node)
97
+ node.each_descendant(:block).with_object({}) do |child, h|
98
+ name = subject(child)
99
+ next unless name
109
100
 
110
- # Recurse through node's children looking for a message expectation.
111
- node.each_child_node do |child|
112
- find_subject_expectation(child, subject_name, &block)
113
- end
114
- end
101
+ outer_example_group = child.each_ancestor.find do |a|
102
+ example_group?(a)
103
+ end
115
104
 
116
- # Check if node's children contain a subject definition
117
- #
118
- # @param node [RuboCop::Node]
119
- #
120
- # @return [Boolean]
121
- def redefines_subject?(node)
122
- node.each_child_node.any? do |child|
123
- subject(child) || redefines_subject?(child)
105
+ h[outer_example_group] ||= []
106
+ h[outer_example_group] << name
124
107
  end
125
108
  end
126
109
 
127
- # Find a subject definition
128
- #
129
- # @param node [RuboCop::Node]
130
- # @param parent [RuboCop::Node,nil]
131
- #
132
- # @yieldparam subject_name [Symbol] name of subject being defined
133
- # @yieldparam parent [RuboCop::Node] parent of subject definition
134
- def find_subject(node, parent: nil, &block)
135
- # An implicit subject is defined by RSpec when no subject is declared
136
- subject_name = subject(node) || :subject
110
+ def find_subject_expectations(node, subject_names = [], &block)
111
+ subject_names = @explicit_subjects[node] if @explicit_subjects[node]
137
112
 
138
- yield(subject_name, parent) if parent
113
+ expectation_detected = (subject_names + [:subject]).any? do |name|
114
+ message_expectation?(node, name)
115
+ end
116
+ return yield(node) if expectation_detected
139
117
 
140
118
  node.each_child_node do |child|
141
- find_subject(child, parent: node, &block)
119
+ find_subject_expectations(child, subject_names, &block)
142
120
  end
143
121
  end
144
122
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Checks that memoized helpers names are symbols or strings.
7
+ #
8
+ # @example EnforcedStyle: symbols (default)
9
+ # # bad
10
+ # let('user_name') { 'Adam' }
11
+ # subject('user') { create_user }
12
+ #
13
+ # # good
14
+ # let(:user_name) { 'Adam' }
15
+ # subject(:user) { create_user }
16
+ #
17
+ # @example EnforcedStyle: strings
18
+ # # bad
19
+ # let(:user_name) { 'Adam' }
20
+ # subject(:user) { create_user }
21
+ #
22
+ # # good
23
+ # let('user_name') { 'Adam' }
24
+ # subject('user') { create_user }
25
+ class VariableDefinition < Cop
26
+ include ConfigurableEnforcedStyle
27
+ include RuboCop::RSpec::Variable
28
+
29
+ MSG = 'Use %<style>s for variable names.'
30
+
31
+ def on_send(node)
32
+ variable_definition?(node) do |variable|
33
+ if style_violation?(variable)
34
+ add_offense(variable, message: format(MSG, style: style))
35
+ end
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def style_violation?(variable)
42
+ style == :symbols && string?(variable) ||
43
+ style == :strings && symbol?(variable)
44
+ end
45
+
46
+ def string?(node)
47
+ node.str_type? || node.dstr_type?
48
+ end
49
+
50
+ def symbol?(node)
51
+ node.sym_type? || node.dsym_type?
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Checks that memoized helper names use the configured style.
7
+ #
8
+ # @example EnforcedStyle: snake_case (default)
9
+ # # bad
10
+ # let(:userName) { 'Adam' }
11
+ # subject(:userName) { 'Adam' }
12
+ #
13
+ # # good
14
+ # let(:user_name) { 'Adam' }
15
+ # subject(:user_name) { 'Adam' }
16
+ #
17
+ # @example EnforcedStyle: camelCase
18
+ # # bad
19
+ # let(:user_name) { 'Adam' }
20
+ # subject(:user_name) { 'Adam' }
21
+ #
22
+ # # good
23
+ # let(:userName) { 'Adam' }
24
+ # subject(:userName) { 'Adam' }
25
+ class VariableName < Cop
26
+ include ConfigurableNaming
27
+ include RuboCop::RSpec::Variable
28
+
29
+ MSG = 'Use %<style>s for variable names.'
30
+
31
+ def on_send(node)
32
+ variable_definition?(node) do |variable|
33
+ return if variable.dstr_type? || variable.dsym_type?
34
+
35
+ check_name(node, variable.value, variable.loc.expression)
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def message(style)
42
+ format(MSG, style: style)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -86,6 +86,8 @@ require_relative 'rspec/shared_examples'
86
86
  require_relative 'rspec/single_argument_message_chain'
87
87
  require_relative 'rspec/subject_stub'
88
88
  require_relative 'rspec/unspecified_exception'
89
+ require_relative 'rspec/variable_definition'
90
+ require_relative 'rspec/variable_name'
89
91
  require_relative 'rspec/verified_doubles'
90
92
  require_relative 'rspec/void_expect'
91
93
  require_relative 'rspec/yield'
@@ -21,7 +21,7 @@ module RuboCop
21
21
 
22
22
  # Decorator of a YARD code object for working with documented rspec cops
23
23
  class CodeObject
24
- COP_CLASS_NAMES = %w[RuboCop::Cop RuboCop::Cop::RSpec::Cop].freeze
24
+ COP_CLASS_NAME = 'RuboCop::Cop::RSpec::Cop'
25
25
  RSPEC_NAMESPACE = 'RuboCop::Cop::RSpec'
26
26
 
27
27
  def initialize(yardoc)
@@ -68,11 +68,7 @@ module RuboCop
68
68
  end
69
69
 
70
70
  def cop_subclass?
71
- # YARD superclass resolution is a bit flaky: All classes loaded before
72
- # RuboCop::Cop::WorkaroundCop are shown as having RuboCop::Cop as
73
- # superclass, while all the following classes are listed as having
74
- # RuboCop::Cop::RSpec::Cop as their superclass.
75
- COP_CLASS_NAMES.include?(yardoc.superclass.path)
71
+ yardoc.superclass.path == COP_CLASS_NAME
76
72
  end
77
73
 
78
74
  def abstract?
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module RSpec
5
+ # Helps check offenses with variable definitions
6
+ module Variable
7
+ include Language
8
+ extend RuboCop::NodePattern::Macros
9
+
10
+ def_node_matcher :variable_definition?, <<~PATTERN
11
+ (send #{RSPEC} #{(Helpers::ALL + Subject::ALL).node_pattern_union}
12
+ $({sym str dsym dstr} ...) ...)
13
+ PATTERN
14
+ end
15
+ end
16
+ end
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module RSpec
5
5
  # Version information for the RSpec RuboCop plugin.
6
6
  module Version
7
- STRING = '1.39.0'
7
+ STRING = '1.40.0'
8
8
  end
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-rspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.39.0
4
+ version: 1.40.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Backus
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-05-01 00:00:00.000000000 Z
13
+ date: 2020-06-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rubocop
@@ -194,6 +194,8 @@ files:
194
194
  - lib/rubocop/cop/rspec/single_argument_message_chain.rb
195
195
  - lib/rubocop/cop/rspec/subject_stub.rb
196
196
  - lib/rubocop/cop/rspec/unspecified_exception.rb
197
+ - lib/rubocop/cop/rspec/variable_definition.rb
198
+ - lib/rubocop/cop/rspec/variable_name.rb
197
199
  - lib/rubocop/cop/rspec/verified_doubles.rb
198
200
  - lib/rubocop/cop/rspec/void_expect.rb
199
201
  - lib/rubocop/cop/rspec/yield.rb
@@ -215,6 +217,7 @@ files:
215
217
  - lib/rubocop/rspec/language/node_pattern.rb
216
218
  - lib/rubocop/rspec/node.rb
217
219
  - lib/rubocop/rspec/top_level_describe.rb
220
+ - lib/rubocop/rspec/variable.rb
218
221
  - lib/rubocop/rspec/version.rb
219
222
  - lib/rubocop/rspec/wording.rb
220
223
  homepage: https://github.com/rubocop-hq/rubocop-rspec