tool_result_content_test.go

  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}