claude-web-chat/claude_cli_test.go
djuka 3283888738
All checks were successful
Tests / unit-tests (push) Successful in 51s
Inicijalna implementacija Claude Web Chat (Faza 1 - CLI mod)
- Login sa session cookie autentifikacijom
- Lista projekata iz filesystem-a
- Chat sa Claude CLI preko WebSocket-a
- Streaming NDJSON parsiranje iz CLI stdout-a
- Sesija zivi nezavisno od browsera (reconnect replay)
- Sidebar sa .md fajlovima i markdown renderovanjem
- Dark tema, htmx + Go templates
- 47 unit testova

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 05:03:40 +00:00

127 lines
3.3 KiB
Go

package main
import (
"encoding/json"
"testing"
)
func TestFilterEnv(t *testing.T) {
env := []string{
"PATH=/usr/bin",
"HOME=/root",
"CLAUDECODE=1",
"OTHER=value",
}
filtered := filterEnv(env, "CLAUDECODE")
if len(filtered) != 3 {
t.Fatalf("got %d entries, want 3", len(filtered))
}
for _, e := range filtered {
if e == "CLAUDECODE=1" {
t.Error("CLAUDECODE should be filtered out")
}
}
}
func TestFilterEnvNotPresent(t *testing.T) {
env := []string{"PATH=/usr/bin", "HOME=/root"}
filtered := filterEnv(env, "CLAUDECODE")
if len(filtered) != 2 {
t.Fatalf("got %d entries, want 2", len(filtered))
}
}
func TestTruncate(t *testing.T) {
tests := []struct {
input string
n int
want string
}{
{"hello", 10, "hello"},
{"hello world", 5, "hello..."},
{"", 5, ""},
}
for _, tt := range tests {
got := truncate(tt.input, tt.n)
if got != tt.want {
t.Errorf("truncate(%q, %d) = %q, want %q", tt.input, tt.n, got, tt.want)
}
}
}
func TestCLIEventParsing(t *testing.T) {
t.Run("assistant message", func(t *testing.T) {
raw := `{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"Hello!"}]}}`
var event CLIEvent
if err := json.Unmarshal([]byte(raw), &event); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if event.Type != "assistant" {
t.Errorf("type = %q", event.Type)
}
if event.Message == nil {
t.Fatal("message is nil")
}
if len(event.Message.Content) != 1 {
t.Fatalf("content length = %d", len(event.Message.Content))
}
if event.Message.Content[0].Text != "Hello!" {
t.Errorf("text = %q", event.Message.Content[0].Text)
}
})
t.Run("content_block_delta", func(t *testing.T) {
raw := `{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"chunk"}}`
var event CLIEvent
if err := json.Unmarshal([]byte(raw), &event); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if event.Type != "content_block_delta" {
t.Errorf("type = %q", event.Type)
}
if event.Delta == nil {
t.Fatal("delta is nil")
}
if event.Delta.Text != "chunk" {
t.Errorf("text = %q", event.Delta.Text)
}
})
t.Run("result event", func(t *testing.T) {
raw := `{"type":"result","subtype":"success","result":{"duration_ms":1234.5,"num_turns":3,"cost_usd":0.05,"session_id":"abc123"}}`
var event CLIEvent
if err := json.Unmarshal([]byte(raw), &event); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if event.Type != "result" {
t.Errorf("type = %q", event.Type)
}
if event.Subtype != "success" {
t.Errorf("subtype = %q", event.Subtype)
}
if event.Result == nil {
t.Fatal("result is nil")
}
if event.Result.SessionID != "abc123" {
t.Errorf("session_id = %q", event.Result.SessionID)
}
})
t.Run("tool_use content", func(t *testing.T) {
raw := `{"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","name":"Read","id":"tool1","input":{"file_path":"/tmp/test.go"}}]}}`
var event CLIEvent
if err := json.Unmarshal([]byte(raw), &event); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if event.Message.Content[0].Type != "tool_use" {
t.Errorf("content type = %q", event.Message.Content[0].Type)
}
if event.Message.Content[0].Name != "Read" {
t.Errorf("name = %q", event.Message.Content[0].Name)
}
})
}