Skip to content

Commit be302df

Browse files
committed
Add test command resolution
1 parent f17a66b commit be302df

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

lib/ruby_lsp/ruby_lsp_rails/addon.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ def create_discover_tests_listener(response_builder, dispatcher, uri)
9393
RailsTestStyle.new(@rails_runner_client, response_builder, @global_state, dispatcher, uri)
9494
end
9595

96+
# @override
97+
#: (Array[Hash[Symbol, untyped]]) -> Array[String]
98+
def resolve_test_commands(items)
99+
RailsTestStyle.resolve_test_commands(items)
100+
end
101+
96102
# Creates a new CodeLens listener. This method is invoked on every CodeLens request
97103
# @override
98104
#: (ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens] response_builder, URI::Generic uri, Prism::Dispatcher dispatcher) -> void

lib/ruby_lsp/ruby_lsp_rails/rails_test_style.rb

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,52 @@
44
module RubyLsp
55
module Rails
66
class RailsTestStyle < Listeners::TestDiscovery
7+
BASE_COMMAND = "#{RbConfig.ruby} bin/rails test" #: String
8+
9+
class << self
10+
#: (Array[Hash[Symbol, untyped]]) -> Array[String]
11+
def resolve_test_commands(items)
12+
commands = []
13+
queue = items.dup
14+
15+
full_files = []
16+
17+
until queue.empty?
18+
item = T.must(queue.shift)
19+
tags = Set.new(item[:tags])
20+
next unless tags.include?("framework:rails")
21+
22+
children = item[:children]
23+
uri = URI(item[:uri])
24+
path = uri.full_path
25+
next unless path
26+
27+
if tags.include?("test_dir")
28+
if children.empty?
29+
full_files.concat(Dir.glob(
30+
"#{path}/**/{*_test,test_*}.rb",
31+
File::Constants::FNM_EXTGLOB | File::Constants::FNM_PATHNAME,
32+
))
33+
end
34+
elsif tags.include?("test_file")
35+
full_files << path if children.empty?
36+
elsif tags.include?("test_group")
37+
commands << "#{BASE_COMMAND} #{path} --name \"/#{Shellwords.escape(item[:id])}(#|::)/\""
38+
else
39+
full_files << "#{path}:#{item.dig(:range, :start, :line) + 1}"
40+
end
41+
42+
queue.concat(children)
43+
end
44+
45+
unless full_files.empty?
46+
commands << "#{BASE_COMMAND} #{full_files.join(" ")}"
47+
end
48+
49+
commands
50+
end
51+
end
52+
753
#: (RunnerClient client, ResponseBuilders::TestCollection response_builder, GlobalState global_state, Prism::Dispatcher dispatcher, URI::Generic uri) -> void
854
def initialize(client, response_builder, global_state, dispatcher, uri)
955
super(response_builder, global_state, dispatcher, uri)

test/ruby_lsp_rails/rails_test_style_test.rb

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,96 @@ class SpecialCharsTest < ActiveSupport::TestCase
133133
end
134134
end
135135

136+
test "resolve test command entire files" do
137+
Dir.stubs(:glob).returns(["/other/test/fake_test.rb", "/other/test/fake_test2.rb"])
138+
139+
with_server do |server|
140+
sleep(0.1) while RubyLsp::Addon.addons.first.instance_variable_get(:@rails_runner_client).is_a?(NullClient)
141+
142+
server.process_message({
143+
id: 1,
144+
method: "rubyLsp/resolveTestCommands",
145+
params: {
146+
items: [
147+
{
148+
id: "file:///test/server_test.rb",
149+
uri: "file:///test/server_test.rb",
150+
label: "/test/server_test.rb",
151+
tags: ["test_file", "framework:rails"],
152+
children: [],
153+
},
154+
{
155+
id: "file:///other/test",
156+
uri: "file:///other/test",
157+
label: "/other/test",
158+
tags: ["test_dir", "framework:rails"],
159+
children: [],
160+
},
161+
],
162+
},
163+
})
164+
165+
result = pop_result(server)
166+
response = result.response
167+
168+
assert_equal(
169+
[
170+
"#{RailsTestStyle::BASE_COMMAND} /test/server_test.rb /other/test/fake_test.rb /other/test/fake_test2.rb",
171+
],
172+
response[:commands],
173+
)
174+
end
175+
end
176+
177+
test "resolve test command group test" do
178+
with_server do |server|
179+
sleep(0.1) while RubyLsp::Addon.addons.first.instance_variable_get(:@rails_runner_client).is_a?(NullClient)
180+
181+
server.process_message({
182+
id: 1,
183+
method: "rubyLsp/resolveTestCommands",
184+
params: {
185+
items: [
186+
{
187+
id: "GroupTest",
188+
uri: "file:///test/group_test.rb",
189+
label: "GroupTest",
190+
range: {
191+
start: { line: 0, character: 0 },
192+
end: { line: 30, character: 3 },
193+
},
194+
tags: ["framework:rails", "test_group"],
195+
children: [
196+
{
197+
id: "GroupTest#test_example",
198+
uri: "file:///test/group_test.rb",
199+
label: "test_example",
200+
range: {
201+
start: { line: 1, character: 2 },
202+
end: { line: 10, character: 3 },
203+
},
204+
tags: ["framework:rails"],
205+
children: [],
206+
},
207+
],
208+
},
209+
],
210+
},
211+
})
212+
213+
result = pop_result(server)
214+
response = result.response
215+
216+
assert_equal(
217+
[
218+
"#{RailsTestStyle::BASE_COMMAND} /test/group_test.rb --name \"/GroupTest(#|::)/\"",
219+
"#{RailsTestStyle::BASE_COMMAND} /test/group_test.rb:2",
220+
],
221+
response[:commands],
222+
)
223+
end
224+
end
225+
136226
private
137227

138228
def with_active_support_declarative_tests(source, file: "/fake.rb", &block)

0 commit comments

Comments
 (0)