summaryrefslogtreecommitdiff
path: root/internal/lsp/codeaction_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-08-18 09:28:48 +0300
committerPaul Buetow <paul@buetow.org>2025-08-18 09:28:48 +0300
commit96ace6c7019a914e21b25fa94ddfc4ee9239c2fb (patch)
tree30550bcab30c91e917a4d8b3feccda829a364437 /internal/lsp/codeaction_test.go
parent6d29ac7e4b2604b5c7df50f33f8ef2357709faf2 (diff)
refactor(lsp,llm,hexailsp,appconfig): split long funcs; add tests
- Extract helpers to keep funcs <=50 lines; no behavior changes - Add tests for prompt removal, code actions, and LLM request builders - Table-drive TestInParamList; run gofmt
Diffstat (limited to 'internal/lsp/codeaction_test.go')
-rw-r--r--internal/lsp/codeaction_test.go63
1 files changed, 63 insertions, 0 deletions
diff --git a/internal/lsp/codeaction_test.go b/internal/lsp/codeaction_test.go
new file mode 100644
index 0000000..e9abbb8
--- /dev/null
+++ b/internal/lsp/codeaction_test.go
@@ -0,0 +1,63 @@
+package lsp
+
+import (
+ "context"
+ "encoding/json"
+ "testing"
+ "hexai/internal/llm"
+)
+
+type fakeLLM struct{ resp string; err error }
+
+func (f fakeLLM) Chat(_ context.Context, _ []llm.Message, _ ...llm.RequestOption) (string, error) {
+ return f.resp, f.err
+}
+func (f fakeLLM) Name() string { return "fake" }
+func (f fakeLLM) DefaultModel() string { return "fake-model" }
+
+func TestBuildRewriteCodeAction_ReturnsEdit(t *testing.T) {
+ s := newTestServer()
+ s.llmClient = fakeLLM{resp: "REWRITTEN"}
+ p := CodeActionParams{TextDocument: TextDocumentIdentifier{URI: "file:///t.go"}, Range: Range{Start: Position{Line: 1, Character: 2}, End: Position{Line: 3, Character: 4}}}
+ sel := ";rewrite;\nold code"
+ ca := s.buildRewriteCodeAction(p, sel)
+ if ca == nil { t.Fatalf("expected code action") }
+ if ca.Edit == nil || len(ca.Edit.Changes) == 0 { t.Fatalf("expected workspace edit with changes") }
+ edits := ca.Edit.Changes[p.TextDocument.URI]
+ if len(edits) != 1 { t.Fatalf("expected 1 edit, got %d", len(edits)) }
+ if edits[0].Range != p.Range { t.Fatalf("edit range mismatch: got %+v want %+v", edits[0].Range, p.Range) }
+ if edits[0].NewText == "" { t.Fatalf("expected non-empty replacement text") }
+}
+
+func TestBuildRewriteCodeAction_NoInstruction(t *testing.T) {
+ s := newTestServer()
+ s.llmClient = fakeLLM{resp: "IGNORED"}
+ p := CodeActionParams{TextDocument: TextDocumentIdentifier{URI: "file:///t.go"}, Range: Range{}}
+ sel := "no instruction here"
+ if ca := s.buildRewriteCodeAction(p, sel); ca != nil { t.Fatalf("expected nil action when no instruction present") }
+}
+
+func TestBuildDiagnosticsCodeAction_ReturnsEdit(t *testing.T) {
+ s := newTestServer()
+ s.llmClient = fakeLLM{resp: "FIXED"}
+ p := CodeActionParams{TextDocument: TextDocumentIdentifier{URI: "file:///t.go"}, Range: Range{Start: Position{Line: 10}, End: Position{Line: 12, Character: 5}}}
+ ctx := CodeActionContext{Diagnostics: []Diagnostic{
+ {Range: Range{Start: Position{Line: 11}, End: Position{Line: 11, Character: 10}}, Message: "inside"},
+ {Range: Range{Start: Position{Line: 2}, End: Position{Line: 3}}, Message: "outside"},
+ }}
+ raw, _ := json.Marshal(ctx)
+ p.Context = json.RawMessage(raw)
+ sel := "some selected code"
+ ca := s.buildDiagnosticsCodeAction(p, sel)
+ if ca == nil { t.Fatalf("expected diagnostics code action") }
+ if ca.Edit == nil || len(ca.Edit.Changes) == 0 { t.Fatalf("expected workspace edit") }
+}
+
+func TestBuildDiagnosticsCodeAction_NoDiagnostics(t *testing.T) {
+ s := newTestServer()
+ s.llmClient = fakeLLM{resp: "FIXED"}
+ p := CodeActionParams{TextDocument: TextDocumentIdentifier{URI: "file:///t.go"}, Range: Range{}}
+ // empty context
+ p.Context = json.RawMessage(nil)
+ if ca := s.buildDiagnosticsCodeAction(p, "sel"); ca != nil { t.Fatalf("expected nil action when no diagnostics") }
+}