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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe061c7b11557dedba1714eeb2df39a1030bf990a509501dda39781277557aca
4
- data.tar.gz: aff7a164338bc4f5b23a9aacf1a3b04c91e040f18bccd7cbdbdc0e931b6bb8b5
3
+ metadata.gz: 22422977377471478233dd86ea759dde042e3a099577c0a77b611667f792cbf5
4
+ data.tar.gz: 1082c7d45b3c9da60de09f7a7db0567f63353e623af74f9d26e304a94464d5bf
5
5
  SHA512:
6
- metadata.gz: b1989fb64fc261fb90ce9a3f0a8493715cf7f36015679424dd1a5e746f8cb47682901222c8f1ca078ccc310441a03b8c7671b77e331ae659933d863cfab55449
7
- data.tar.gz: 8e173ee1fd7e2aa65e29efe31ed30d5c05fac453579d79bcf3e53c8a7ad9617de435be3cd7b86ae4d5e3cc46815c913bffa939ac36ff3321944b5d2796443267
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 describe '#%<method_name>s' or describe '.%<method_name>s' in %<spec_path>s"
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 ? "#" : "."
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module RSpecParity
5
- VERSION = "1.3.2"
5
+ VERSION = "1.3.3"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-rspec_parity
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Povilas Jurcys