rubocop-rspec_parity 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +18 -1
- data/lib/rubocop/cop/rspec_parity/public_method_has_spec.rb +22 -2
- data/lib/rubocop/rspec_parity/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c258389ca56666df76d2865c8fee4ecca3dec132d02b7295d6e245747dbc4896
|
|
4
|
+
data.tar.gz: 02612dbd491de04d9819742f61bcdb47933837a6b3211d9888765e9eea94ef36
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6fb8521af37136c1449fc5292fcc7658966f42f538197081d5a9ff53985dc4901c70e5e17c7a93c3204c8be0dc179c10c909ec2499ced966251d7ffc124e14e9
|
|
7
|
+
data.tar.gz: d18fc9c48f6063187c20472ada669bbf374192687dce5ae7e91d5bfceb2dc7b282340e623e72165363ad398d4e8cb43251dc8ef7820306cab73279ef71c92c41
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [2.0.1] - 2026-06-18
|
|
4
|
+
|
|
5
|
+
Fixed: `PublicMethodHasSpec` relaxed validation for single-public-method classes (e.g. service objects) no longer passes when the spec's only method-style `describe`/`context` covers a different method — if a method describe is present it must describe the actual public method.
|
|
6
|
+
|
|
3
7
|
## [2.0.0] - 2026-06-18
|
|
4
8
|
|
|
5
9
|
Added: `SufficientContexts` now pinpoints which branch is untested — its message names one uncovered branch and the `# rspec_parity:covers <branch>` annotation to add, and the bundled `rspec-parity-cover` executable lists all of a method's gaps as paste-ready context stubs. Annotations are opt-in (new `CoversAnnotations` config key, default `true`).
|
data/README.md
CHANGED
|
@@ -249,7 +249,24 @@ context 'when staff' do # rspec_parity:covers user.staff?
|
|
|
249
249
|
end
|
|
250
250
|
```
|
|
251
251
|
|
|
252
|
-
Re-run and the message advances to the next uncovered branch. Annotations are opt-in and only ever raise coverage — they never create a new violation
|
|
252
|
+
Re-run and the message advances to the next uncovered branch. Annotations are opt-in and only ever raise coverage — they never create a new violation. A mistyped label is reported with a did-you-mean suggestion.
|
|
253
|
+
|
|
254
|
+
Each annotation covers exactly one branch, and the normal expectation is one annotation per context — one context, one scenario, one branch. In rare cases a single context genuinely exercises several branches at once; you can then list more than one branch on it, either as separate comments or with a `;`-separated list:
|
|
255
|
+
|
|
256
|
+
```ruby
|
|
257
|
+
context 'when fully privileged' do
|
|
258
|
+
# rspec_parity:covers user.admin?
|
|
259
|
+
# rspec_parity:covers user.staff?
|
|
260
|
+
it { is_expected.to be_allowed }
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# or, equivalently, on one line:
|
|
264
|
+
context 'when fully privileged' do # rspec_parity:covers user.admin?; user.staff?
|
|
265
|
+
it { is_expected.to be_allowed }
|
|
266
|
+
end
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Reach for this only when the branches really are covered together — multiple annotations on a context that only tests one path inflate coverage and defeat the point of the check.
|
|
253
270
|
|
|
254
271
|
Long conditions can push the comment past `Layout/LineLength`; exempt these comments rather than editing the label:
|
|
255
272
|
|
|
@@ -219,8 +219,9 @@ module RuboCop
|
|
|
219
219
|
|
|
220
220
|
# Check if relaxed validation applies
|
|
221
221
|
if matches_skip_path? && count_public_methods(node) == 1
|
|
222
|
-
# For single-method classes in configured paths,
|
|
223
|
-
|
|
222
|
+
# For single-method classes in configured paths, the method describe is optional —
|
|
223
|
+
# but if one is present, it must describe the actual public method, not a private/random one.
|
|
224
|
+
return if relaxed_spec_valid?(spec_paths, class_name, method_name, instance_method, flexible_prefix)
|
|
224
225
|
elsif spec_paths.any? do |sp|
|
|
225
226
|
spec_covers_method?(sp, method_name, instance_method, flexible_prefix: flexible_prefix)
|
|
226
227
|
end
|
|
@@ -233,6 +234,25 @@ module RuboCop
|
|
|
233
234
|
end
|
|
234
235
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
235
236
|
|
|
237
|
+
# Relaxed validation for single-public-method classes in skip paths.
|
|
238
|
+
# Passes when the spec describes the class with examples AND either has no
|
|
239
|
+
# method-style describe/context block at all, or has one that covers the public method.
|
|
240
|
+
def relaxed_spec_valid?(spec_paths, class_name, method_name, instance_method, flexible_prefix)
|
|
241
|
+
return false unless spec_paths.any? { |sp| spec_has_examples?(sp, class_name) }
|
|
242
|
+
return true unless spec_paths.any? { |sp| spec_has_method_describe?(sp) }
|
|
243
|
+
|
|
244
|
+
spec_paths.any? do |sp|
|
|
245
|
+
spec_covers_method?(sp, method_name, instance_method, flexible_prefix: flexible_prefix)
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# Detects a method-style block, e.g. describe '#foo' / context '.bar'
|
|
250
|
+
# (the char right after the quote is a `#` or `.` prefix), as opposed to a
|
|
251
|
+
# plain descriptive string or a class constant.
|
|
252
|
+
def spec_has_method_describe?(spec_path)
|
|
253
|
+
File.read(spec_path).match?(/(?:describe|context)\s+['"][#.][^'"]+['"]/)
|
|
254
|
+
end
|
|
255
|
+
|
|
236
256
|
def spec_covers_method?(spec_path, method_name, instance_method, flexible_prefix: false)
|
|
237
257
|
return true if method_tested_in_spec?(spec_path, method_name, instance_method)
|
|
238
258
|
return true if flexible_prefix && method_tested_in_spec?(spec_path, method_name, !instance_method)
|