rubocop-rspec 1.39.0 → 1.40.0

Sign up to get free protection for your applications and to get access to all the features.
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