rubocop-rspec_parity 1.3.2 → 1.3.3
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 +5 -0
- data/lib/rubocop/cop/rspec_parity/public_method_has_spec.rb +40 -4
- 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: 22422977377471478233dd86ea759dde042e3a099577c0a77b611667f792cbf5
|
|
4
|
+
data.tar.gz: 1082c7d45b3c9da60de09f7a7db0567f63353e623af74f9d26e304a94464d5bf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5396c1d32d186548dd9b58910da704e271c76d818613cfe8b1776394f1c07fc097b8d0b4a5e06e8531b3899733f449ae4c7dd7ca5d2243991c3953a885f00dbe
|
|
7
|
+
data.tar.gz: d0f02db94469e02b4e79dff03b7ae1f9a7555501604f2ecd4f1dd5266844cb94c248815884ea8e053fb75024c045dbed7f4a5cd73574bc957db36b8a32e62c96
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [1.3.3] - 2026-02-20
|
|
4
|
+
|
|
5
|
+
Fixed: `PublicMethodHasSpec` offense message now shows correct method prefix (`#` for instance methods, `.` for class methods) and includes configured `DescribeAliases` in the expected describes
|
|
6
|
+
Fixed: `PublicMethodHasSpec` no longer reports methods in inner classes (class nested inside another class) as needing specs
|
|
7
|
+
|
|
3
8
|
## [1.3.2] - 2026-02-20
|
|
4
9
|
|
|
5
10
|
Fixed: `PublicMethodHasSpec` now recognizes specs that use module wrapping (e.g., `module Foo; RSpec.describe Bar`) instead of fully qualified class names
|
|
@@ -16,7 +16,7 @@ module RuboCop
|
|
|
16
16
|
include SpecFileFinder
|
|
17
17
|
|
|
18
18
|
MSG = "Missing spec for public method `%<method_name>s`. " \
|
|
19
|
-
"Expected
|
|
19
|
+
"Expected %<expected>s in %<spec_path>s"
|
|
20
20
|
|
|
21
21
|
COVERED_DIRECTORIES = %w[models controllers services jobs mailers helpers].freeze
|
|
22
22
|
EXCLUDED_METHODS = %w[initialize].freeze
|
|
@@ -32,6 +32,7 @@ module RuboCop
|
|
|
32
32
|
|
|
33
33
|
def on_def(node)
|
|
34
34
|
return unless checkable_method?(node) && public_method?(node)
|
|
35
|
+
return if inside_inner_class?(node)
|
|
35
36
|
|
|
36
37
|
check_method_has_spec(node, instance_method: !inside_eigenclass?(node))
|
|
37
38
|
end
|
|
@@ -39,6 +40,7 @@ module RuboCop
|
|
|
39
40
|
def on_defs(node)
|
|
40
41
|
return unless checkable_method?(node) && public_class_method?(node)
|
|
41
42
|
return if EXCLUDED_HOOK_METHODS.include?(node.method_name.to_s)
|
|
43
|
+
return if inside_inner_class?(node)
|
|
42
44
|
|
|
43
45
|
check_method_has_spec(node, instance_method: false)
|
|
44
46
|
end
|
|
@@ -75,6 +77,30 @@ module RuboCop
|
|
|
75
77
|
node.each_ancestor.any? { |a| a.sclass_type? && a.children.first&.self_type? }
|
|
76
78
|
end
|
|
77
79
|
|
|
80
|
+
def inside_inner_class?(node)
|
|
81
|
+
enclosing = find_class_or_module(node)
|
|
82
|
+
return false unless enclosing
|
|
83
|
+
|
|
84
|
+
enclosing.each_ancestor.any? { |a| a.class_type? && class_has_methods?(a) }
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def class_has_methods?(class_node)
|
|
88
|
+
return false unless class_node.body
|
|
89
|
+
|
|
90
|
+
children = class_node.body.begin_type? ? class_node.body.children : [class_node.body]
|
|
91
|
+
children.any? { |child| child.def_type? || child.defs_type? || eigenclass_with_methods?(child) }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def eigenclass_with_methods?(node)
|
|
95
|
+
return false unless node.sclass_type? && node.children.first&.self_type?
|
|
96
|
+
|
|
97
|
+
body = node.body
|
|
98
|
+
return false unless body
|
|
99
|
+
|
|
100
|
+
body_children = body.begin_type? ? body.children : [body]
|
|
101
|
+
body_children.any?(&:def_type?)
|
|
102
|
+
end
|
|
103
|
+
|
|
78
104
|
def should_check_file?
|
|
79
105
|
path = processed_source.file_path
|
|
80
106
|
return false if path.nil? || !path.include?("/app/") || path.end_with?("_spec.rb")
|
|
@@ -175,7 +201,7 @@ module RuboCop
|
|
|
175
201
|
return
|
|
176
202
|
end
|
|
177
203
|
|
|
178
|
-
add_method_offense(node, method_name, spec_paths.first)
|
|
204
|
+
add_method_offense(node, method_name, spec_paths.first, instance_method: instance_method)
|
|
179
205
|
end
|
|
180
206
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
181
207
|
|
|
@@ -191,13 +217,23 @@ module RuboCop
|
|
|
191
217
|
end
|
|
192
218
|
end
|
|
193
219
|
|
|
194
|
-
def add_method_offense(node, method_name, spec_path)
|
|
220
|
+
def add_method_offense(node, method_name, spec_path, instance_method:)
|
|
221
|
+
prefix = instance_method ? "#" : "."
|
|
222
|
+
expected = expected_describes(prefix, method_name)
|
|
195
223
|
add_offense(
|
|
196
224
|
node.loc.keyword.join(node.loc.name),
|
|
197
|
-
message: format(MSG, method_name: method_name, spec_path: relative_spec_path(spec_path))
|
|
225
|
+
message: format(MSG, method_name: method_name, expected: expected, spec_path: relative_spec_path(spec_path))
|
|
198
226
|
)
|
|
199
227
|
end
|
|
200
228
|
|
|
229
|
+
def expected_describes(prefix, method_name)
|
|
230
|
+
describes = ["describe '#{prefix}#{method_name}'"]
|
|
231
|
+
describe_aliases_for("#{prefix}#{method_name}").each do |alias_desc|
|
|
232
|
+
describes << "describe '#{alias_desc}'"
|
|
233
|
+
end
|
|
234
|
+
describes.join(" or ")
|
|
235
|
+
end
|
|
236
|
+
|
|
201
237
|
def method_tested_in_spec?(spec_path, method_name, instance_method)
|
|
202
238
|
spec_content = File.read(spec_path)
|
|
203
239
|
prefix = instance_method ? "#" : "."
|