Repository: Shopify/ruby-lsp (Ruby)

Issue:
Test running with `--name` filter is not working for minitest spec syntax
### Description

### Ruby LSP Information


### Ruby LSP Information

#### VS Code Version

1.102.1

#### Ruby LSP Extension Version

0.9.31

#### Ruby LSP Server Version

0.26.1

#### Ruby LSP Add-ons

- Ruby LSP Rails (0.4.8)
- RuboCop (unknown)

#### Ruby Version

3.3.5

#### Ruby Version Manager

none

#### Installed Extensions

<details>
<summary>Click to expand</summary>

- copilot (1.346.0)
- copilot-chat (0.29.1)
- markdown-mermaid (1.28.0)
- ruby-lsp (0.9.31)
- vscode-github-actions (0.27.2)
- vscode-pgsql (1.6.0)
- vscode-pull-request-github (0.114.3)
- vsliveshare (1.0.5948)
</details>

#### Ruby LSP Settings

<details>
<summary>Click to expand</summary>

##### Workspace

```json
{}
```

##### User

```json
{
  "enabledFeatures": {
    "codeActions": true,
    "diagnostics": true,
    "documentHighlights": true,
    "documentLink": true,
    "documentSymbols": true,
    "foldingRanges": true,
    "formatting": true,
    "hover": true,
    "inlayHint": true,
    "onTypeFormatting": true,
    "selectionRanges": true,
    "semanticHighlighting": true,
    "completion": true,
    "codeLens": true,
    "definition": true,
    "workspaceSymbol": true,
    "signatureHelp": true,
    "typeHierarchy": true
  },
  "featuresConfiguration": {},
  "addonSettings": {},
  "rubyVersionManager": {
    "identifier": "auto"
  },
  "customRubyCommand": "",
  "formatter": "auto",
  "linters": null,
  "bundleGemfile": "",
  "testTimeout": 30,
  "branch": "",
  "pullDiagnosticsOn": "both",
  "useBundlerCompose": false,
  "bypassTypechecker": false,
  "rubyExecutablePath": "",
  "indexing": {},
  "erbSupport": true,
  "featureFlags": {},
  "sigOpacityLevel": "1"
}
```

</details>


### Reproduction steps

I noticed ever since the new test explorer that we cannot run tests anymore in our code base using VS Code. I've been running them manually since but thought I would take a quick look to see what happened.

It appears things changed from running tests based on line numbers to instead filtering tests by regexp, and something there is not working right.

Consider the following test file, written in minitest using spec syntax:
```ruby
describe(SomeClass, :model) do
  describe("#some_method") do
    it("does something") do
      assert(true)
    end
  end
end
```

If I try to run this using VS Code, the following command is issued:
```
bundle exec ruby -r/usr/local/bundle/gems/ruby-lsp-0.26.1/lib/ruby_lsp/test_reporters/minitest_reporter.rb -r/usr/local/bundle/gems/ruby-lsp-0.26.1/lib/ruby_lsp/test_reporters/test_unit_reporter.rb -Itest /workspace/test/some_class_test.rb --name "/^SomeClass::#some_method\$/"
```

The actual name of the test though, is `SomeClass::model::#some_method#test_0001_does something`, meaning the `--name` filter wont match.


Discussion:
Thank you for reporting! #3688 will fix it.
@vinistock Just wondering if this was ever released? I'm still seeing the same problem 
It got released with [v0.26.2](https://github.com/Shopify/ruby-lsp/releases/tag/v0.26.2).



Patch:
diff --git a/lib/ruby_lsp/listeners/spec_style.rb b/lib/ruby_lsp/listeners/spec_style.rb
index 532a3f5fbc..950f8ad042 100644
--- a/lib/ruby_lsp/listeners/spec_style.rb
+++ b/lib/ruby_lsp/listeners/spec_style.rb
@@ -117,10 +117,7 @@ def handle_describe(node)
 
       #: (Prism::CallNode) -> void
       def handle_example(node)
-        # Minitest formats the descriptions into test method names by using the count of examples with the description
-        # We are not guaranteed to discover examples in the exact order using static analysis, so we use the line number
-        # instead. Note that anonymous examples mixed with meta-programming will not be handled correctly
-        description = extract_description(node) || "anonymous"
+        description = extract_it_description(node)
         line = node.location.start_line - 1
         parent = latest_group
         return unless parent.is_a?(Requests::Support::TestItem)
@@ -141,16 +138,37 @@ def handle_example(node)
 
       #: (Prism::CallNode) -> String?
       def extract_description(node)
+        arguments = node.arguments&.arguments
+        return unless arguments
+
+        parts = arguments.map { |arg| extract_argument_content(arg) }
+        return if parts.empty?
+
+        parts.join("::")
+      end
+
+      #: (Prism::CallNode) -> String
+      def extract_it_description(node)
+        # Minitest formats the descriptions into test method names by using the count of examples with the description
+        # We are not guaranteed to discover examples in the exact order using static analysis, so we use the line number
+        # instead. Note that anonymous examples mixed with meta-programming will not be handled correctly
         first_argument = node.arguments&.arguments&.first
-        return unless first_argument
+        return "anonymous" unless first_argument
+
+        extract_argument_content(first_argument) || "anonymous"
+      end
 
-        case first_argument
+      #: (Prism::Node) -> String?
+      def extract_argument_content(arg)
+        case arg
         when Prism::StringNode
-          first_argument.content
+          arg.content
+        when Prism::SymbolNode
+          arg.value
         when Prism::ConstantReadNode, Prism::ConstantPathNode
-          constant_name(first_argument)
+          constant_name(arg)
         else
-          first_argument.slice
+          arg.slice
         end
       end
 


Test patch:
diff --git a/test/requests/discover_tests_test.rb b/test/requests/discover_tests_test.rb
index f610c3b5b0..c3a96fec29 100644
--- a/test/requests/discover_tests_test.rb
+++ b/test/requests/discover_tests_test.rb
@@ -745,6 +745,30 @@ def test_other_thing; end
       end
     end
 
+    def test_spec_using_describe_with_additional_descriptions
+      source = <<~RUBY
+        describe(Foo, :extra_1, :extra_2) do
+          describe("#some_method") do
+            it("does something") do
+              assert(true)
+            end
+          end
+        end
+      RUBY
+
+      with_minitest_spec_configured(source) do |items|
+        assert_equal(["Foo::extra_1::extra_2"], items.map { |i| i[:id] })
+        assert_equal(
+          ["Foo::extra_1::extra_2::#some_method"],
+          items.dig(0, :children).map { |i| i[:id] },
+        )
+        assert_equal(
+          ["Foo::extra_1::extra_2::#some_method#test_0002_does something"],
+          items.dig(0, :children).dig(0, :children).map { |i| i[:id] },
+        )
+      end
+    end
+
     private
 
     def create_test_discovery_addon