Skip to content

Commit a4a837b

Browse files
authored
Ignore examples defined in random modules and classes for spec (#3521)
1 parent 9aa9680 commit a4a837b

File tree

2 files changed

+118
-12
lines changed

2 files changed

+118
-12
lines changed

lib/ruby_lsp/listeners/spec_style.rb

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,20 @@ def on_class_node_enter(node)
4141

4242
#: (Prism::ClassNode) -> void
4343
def on_class_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
44+
@spec_group_id_stack.pop
4445
super
46+
end
47+
48+
#: (Prism::ModuleNode) -> void
49+
def on_module_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
50+
@spec_group_id_stack << nil
51+
super
52+
end
53+
54+
#: (Prism::ModuleNode) -> void
55+
def on_module_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
4556
@spec_group_id_stack.pop
57+
super
4658
end
4759

4860
#: (Prism::CallNode) -> void
@@ -61,6 +73,12 @@ def on_call_node_enter(node)
6173
def on_call_node_leave(node)
6274
return unless node.name == :describe && !node.receiver
6375

76+
current_group = @spec_group_id_stack.last
77+
return unless current_group.is_a?(DescribeGroup)
78+
79+
description = extract_description(node)
80+
return unless description && current_group.id.end_with?(description)
81+
6482
@spec_group_id_stack.pop
6583
end
6684

@@ -76,6 +94,8 @@ def handle_describe(node)
7694
return unless description
7795

7896
parent = latest_group
97+
return unless parent
98+
7999
id = case parent
80100
when Requests::Support::TestItem
81101
"#{parent.id}::#{description}"
@@ -135,26 +155,50 @@ def extract_description(node)
135155
end
136156
end
137157

138-
#: -> (Requests::Support::TestItem | ResponseBuilders::TestCollection)
158+
#: -> (Requests::Support::TestItem | ResponseBuilders::TestCollection)?
139159
def latest_group
160+
# If we haven't found anything yet, then return the response builder
140161
return @response_builder if @spec_group_id_stack.compact.empty?
162+
# If we found something that isn't a group last, then we're inside a random module or class, but not a spec
163+
# group
164+
return unless @spec_group_id_stack.last
141165

142-
first_class_index = @spec_group_id_stack.rindex { |i| i.is_a?(ClassGroup) } || 0
143-
first_class = @spec_group_id_stack[0] #: as !nil
144-
item = @response_builder[first_class.id] #: as !nil
166+
# Specs using at least one class as a group require special handling
167+
closest_class_index = @spec_group_id_stack.rindex { |i| i.is_a?(ClassGroup) }
145168

146-
# Descend into child items from the beginning all the way to the latest class group, ignoring describes
147-
@spec_group_id_stack[1..first_class_index] #: as !nil
148-
.each do |group|
149-
next unless group.is_a?(ClassGroup)
169+
if closest_class_index
170+
first_class_index = @spec_group_id_stack.index { |i| i.is_a?(ClassGroup) } #: as !nil
171+
first_class = @spec_group_id_stack[first_class_index] #: as !nil
172+
item = @response_builder[first_class.id] #: as !nil
150173

151-
item = item[group.id] #: as !nil
174+
# Descend into child items from the beginning all the way to the latest class group, ignoring describes
175+
@spec_group_id_stack[first_class_index + 1..closest_class_index] #: as !nil
176+
.each do |group|
177+
next unless group.is_a?(ClassGroup)
178+
179+
item = item[group.id] #: as !nil
180+
end
181+
182+
# From the class forward, we must take describes into account
183+
@spec_group_id_stack[closest_class_index + 1..] #: as !nil
184+
.each do |group|
185+
next unless group
186+
187+
item = item[group.id] #: as !nil
188+
end
189+
190+
return item
152191
end
153192

154-
# From the class forward, we must take describes into account
155-
@spec_group_id_stack[first_class_index + 1..] #: as !nil
193+
# Specs only using describes
194+
first_group = @spec_group_id_stack.find { |i| i.is_a?(DescribeGroup) }
195+
return unless first_group
196+
197+
item = @response_builder[first_group.id] #: as !nil
198+
199+
@spec_group_id_stack[1..] #: as !nil
156200
.each do |group|
157-
next unless group
201+
next unless group.is_a?(DescribeGroup)
158202

159203
item = item[group.id] #: as !nil
160204
end

test/requests/discover_tests_test.rb

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,68 @@ def test_other_thing; end
607607
end
608608
end
609609

610+
def test_spec_ignores_methods_that_look_like_tests_in_other_namespaces
611+
source = <<~RUBY
612+
class MySpec < Minitest::Spec
613+
it "should do something" do
614+
end
615+
616+
module Foo
617+
def test_something_else; end
618+
619+
it "should do something else" do
620+
end
621+
end
622+
623+
class Bar
624+
def test_other_thing; end
625+
626+
it "another ignored call" do
627+
end
628+
end
629+
end
630+
RUBY
631+
632+
with_minitest_spec_configured(source) do |items|
633+
assert_equal(["MySpec"], items.map { |i| i[:id] })
634+
assert_equal(
635+
["MySpec#test_0001_should do something"],
636+
items.dig(0, :children).map { |i| i[:id] },
637+
)
638+
end
639+
end
640+
641+
def test_spec_using_describe_ignores_methods_that_look_like_tests_in_other_namespaces
642+
source = <<~RUBY
643+
describe "MySpec" do
644+
it "should do something" do
645+
end
646+
647+
module Foo
648+
def test_something_else; end
649+
650+
it "should do something else" do
651+
end
652+
end
653+
654+
class Bar
655+
def test_other_thing; end
656+
657+
it "another ignored call" do
658+
end
659+
end
660+
end
661+
RUBY
662+
663+
with_minitest_spec_configured(source) do |items|
664+
assert_equal(["MySpec"], items.map { |i| i[:id] })
665+
assert_equal(
666+
["MySpec#test_0001_should do something"],
667+
items.dig(0, :children).map { |i| i[:id] },
668+
)
669+
end
670+
end
671+
610672
private
611673

612674
def create_test_discovery_addon

0 commit comments

Comments
 (0)