1package chat
2
3import (
4 "encoding/json"
5 "testing"
6
7 "github.com/charmbracelet/crush/internal/ui/styles"
8)
9
10func TestHumanizedToolName(t *testing.T) {
11 t.Parallel()
12
13 tests := []struct {
14 name string
15 input string
16 want string
17 }{
18 {name: "snake case", input: "mcp_github_get", want: "Mcp Github Get"},
19 {name: "kebab case", input: "web-fetch", want: "Web Fetch"},
20 {name: "mixed", input: "job_output-tool", want: "Job Output Tool"},
21 }
22
23 for _, tt := range tests {
24 t.Run(tt.name, func(t *testing.T) {
25 t.Parallel()
26 if got := humanizedToolName(tt.input); got != tt.want {
27 t.Fatalf("humanizedToolName() = %q, want %q", got, tt.want)
28 }
29 })
30 }
31}
32
33func TestLooksLikeMarkdown(t *testing.T) {
34 t.Parallel()
35
36 tests := []struct {
37 name string
38 content string
39 want bool
40 }{
41 {name: "header", content: "# Title", want: true},
42 {name: "code fence", content: "```go\nfmt.Println(\"x\")\n```", want: true},
43 {name: "plain", content: "hello world", want: false},
44 }
45
46 for _, tt := range tests {
47 t.Run(tt.name, func(t *testing.T) {
48 t.Parallel()
49 if got := looksLikeMarkdown(tt.content); got != tt.want {
50 t.Fatalf("looksLikeMarkdown() = %v, want %v", got, tt.want)
51 }
52 })
53 }
54}
55
56func TestRenderToolResultTextContent(t *testing.T) {
57 t.Parallel()
58
59 sty := styles.CharmtonePantera()
60 styPtr := &sty
61 widths := toolResultContentWidths{Body: 80, Diff: 82}
62
63 t.Run("json branch", func(t *testing.T) {
64 t.Parallel()
65 content := `{"a":1}`
66 var result json.RawMessage
67 if err := json.Unmarshal([]byte(content), &result); err != nil {
68 t.Fatalf("json.Unmarshal() error = %v", err)
69 }
70 prettyResult, err := json.MarshalIndent(result, "", " ")
71 if err != nil {
72 t.Fatalf("json.MarshalIndent() error = %v", err)
73 }
74 expected := styPtr.Tool.Body.Render(toolOutputCodeContent(styPtr, "result.json", string(prettyResult), 0, widths.Body, false))
75 got := renderToolResultTextContent(styPtr, content, widths, false)
76 if got != expected {
77 t.Fatal("renderToolResultTextContent() did not choose JSON rendering")
78 }
79 })
80
81 t.Run("diff branch before markdown", func(t *testing.T) {
82 t.Parallel()
83 content := `diff --git a/README.md b/README.md
84--- a/README.md
85+++ b/README.md
86@@ -1 +1 @@
87-# Old
88+# New
89`
90 expected := toolOutputDiffContentFromUnified(styPtr, content, widths.Diff, false)
91 got := renderToolResultTextContent(styPtr, content, widths, false)
92 if got != expected {
93 t.Fatal("renderToolResultTextContent() did not choose diff rendering")
94 }
95 })
96
97 t.Run("markdown branch", func(t *testing.T) {
98 t.Parallel()
99 content := "# Title\n\nBody"
100 expected := styPtr.Tool.Body.Render(toolOutputCodeContent(styPtr, "result.md", content, 0, widths.Body, false))
101 got := renderToolResultTextContent(styPtr, content, widths, false)
102 if got != expected {
103 t.Fatal("renderToolResultTextContent() did not choose markdown rendering")
104 }
105 })
106
107 t.Run("plain branch", func(t *testing.T) {
108 t.Parallel()
109 content := "plain text"
110 expected := styPtr.Tool.Body.Render(toolOutputPlainContent(styPtr, content, widths.Body, false))
111 got := renderToolResultTextContent(styPtr, content, widths, false)
112 if got != expected {
113 t.Fatal("renderToolResultTextContent() did not choose plain rendering")
114 }
115 })
116}