Files
grlx-lsp/internal/lsp/hover_test.go
Tai Groot 96be450cb2 test(lsp): improve handler test coverage from 22% to 68%
- Add completion_test.go: tests for top-level, ingredient.method,
  property, requisite type, and step ID completions
- Add hover_test.go: tests for markdown generation, word extraction,
  and edge cases
- Add diagnostics_test.go: tests for nil recipe, parse errors, empty
  ingredient, requisite validation, range helpers
- Update all dependencies to latest versions
- Add target/ to .gitignore (stale Rust build artifacts)
2026-03-08 12:52:04 +00:00

129 lines
2.9 KiB
Go

package lsp
import (
"testing"
"github.com/gogrlx/grlx-lsp/internal/schema"
)
func TestBuildMethodMarkdown(t *testing.T) {
m := &schema.Method{
Name: "managed",
Description: "Download and manage a file from a source",
Properties: []schema.Property{
{Key: "name", Type: "string", Required: true, Description: "The file path"},
{Key: "source", Type: "string", Required: true, Description: "Source URL"},
{Key: "mode", Type: "string", Required: false, Description: "File permissions"},
},
}
md := buildMethodMarkdown("file", m)
// Should contain header
if !contains(md, "### file.managed") {
t.Error("expected markdown header with ingredient.method")
}
// Should contain description
if !contains(md, "Download and manage a file") {
t.Error("expected description in markdown")
}
// Should contain properties table
if !contains(md, "| Property |") {
t.Error("expected properties table")
}
if !contains(md, "| `name` |") {
t.Error("expected name property in table")
}
if !contains(md, "| `source` |") {
t.Error("expected source property in table")
}
// Required properties should show "yes"
if !contains(md, "| yes |") {
t.Error("expected 'yes' for required properties")
}
}
func TestBuildMethodMarkdownNoProperties(t *testing.T) {
m := &schema.Method{
Name: "cleaned",
Description: "Clean package cache",
}
md := buildMethodMarkdown("pkg", m)
if !contains(md, "### pkg.cleaned") {
t.Error("expected header")
}
// Should not contain a table
if contains(md, "| Property |") {
t.Error("should not have property table for method with no properties")
}
}
func TestBuildMethodMarkdownNoDescription(t *testing.T) {
m := &schema.Method{
Name: "test",
Properties: []schema.Property{
{Key: "name", Type: "string", Required: true},
},
}
md := buildMethodMarkdown("foo", m)
if !contains(md, "### foo.test") {
t.Error("expected header")
}
if !contains(md, "| `name` |") {
t.Error("expected name property")
}
}
func TestIsWordChar(t *testing.T) {
tests := []struct {
b byte
want bool
}{
{'a', true},
{'z', true},
{'A', true},
{'Z', true},
{'0', true},
{'9', true},
{'_', true},
{'.', true},
{'-', true},
{' ', false},
{':', false},
{'\t', false},
{'(', false},
}
for _, tt := range tests {
got := isWordChar(tt.b)
if got != tt.want {
t.Errorf("isWordChar(%q) = %v, want %v", tt.b, got, tt.want)
}
}
}
func TestWordAtPositionEdgeCases(t *testing.T) {
tests := []struct {
line string
col int
want string
}{
{"", 0, ""},
{"hello", 100, "hello"}, // col beyond line length
{" file.managed:", 2, "file.managed"}, // col 2 is start of word
{"file.managed:", 12, "file.managed"}, // just before colon
{"a", 0, "a"},
{"a", 1, "a"},
}
for _, tt := range tests {
got := wordAtPosition(tt.line, tt.col)
if got != tt.want {
t.Errorf("wordAtPosition(%q, %d) = %q, want %q", tt.line, tt.col, got, tt.want)
}
}
}