claude-web-chat/fragments_test.go
djuka 9d0e507689
All checks were successful
Tests / unit-tests (push) Successful in 41s
Popravljen CLI mod: stream-json input, concurrent write fix, lepsi tool prikaz
- Koristi --input-format stream-json za multi-turn razgovor
- Koristi --include-partial-messages za streaming chunk-ove
- Filtrira CLAUDECODE i CLAUDE_CODE_ENTRYPOINT env varijable
- Svi WS write-ovi idu kroz jedan kanal (nema concurrent write panic)
- Tool call prikaz: Read prikazuje putanju, Bash prikazuje komandu, itd
- result polje moze biti string ili objekat (oba obradjena)
- Subscriber/broadcast model za real-time push

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

163 lines
4.2 KiB
Go

package main
import (
"strings"
"testing"
)
func TestFragmentUserMessage(t *testing.T) {
f := FragmentUserMessage("Hello <world>")
if !strings.Contains(f, "message-user") {
t.Error("missing message-user class")
}
if !strings.Contains(f, "Hello &lt;world&gt;") {
t.Error("should escape HTML")
}
if !strings.Contains(f, `hx-swap-oob="beforeend"`) {
t.Error("missing OOB swap")
}
}
func TestFragmentAssistantStart(t *testing.T) {
f := FragmentAssistantStart("msg-1")
if !strings.Contains(f, `id="msg-1"`) {
t.Error("missing message ID")
}
if !strings.Contains(f, "message-assistant") {
t.Error("missing message-assistant class")
}
}
func TestFragmentAssistantChunk(t *testing.T) {
f := FragmentAssistantChunk("msg-1", "chunk<text>")
if !strings.Contains(f, `id="msg-1"`) {
t.Error("missing message ID")
}
if !strings.Contains(f, "chunk&lt;text&gt;") {
t.Error("should escape HTML")
}
}
func TestFragmentAssistantComplete(t *testing.T) {
f := FragmentAssistantComplete("msg-1", "<p>Hello</p>")
if !strings.Contains(f, `id="msg-1"`) {
t.Error("missing message ID")
}
if !strings.Contains(f, "<p>Hello</p>") {
t.Error("should include raw HTML content")
}
}
func TestFragmentToolCall(t *testing.T) {
f := FragmentToolCall("Read", `{"file_path":"/tmp/test.go"}`)
if !strings.Contains(f, "message-tool") {
t.Error("missing message-tool class")
}
if !strings.Contains(f, "Read") {
t.Error("missing tool name")
}
if !strings.Contains(f, "/tmp/test.go") {
t.Error("should show file path, not raw JSON")
}
if strings.Contains(f, "file_path") {
t.Error("should not show JSON key name for Read")
}
}
func TestFragmentToolCallBash(t *testing.T) {
f := FragmentToolCall("Bash", `{"command":"git status"}`)
if !strings.Contains(f, "<code>") {
t.Error("Bash command should be in code tag")
}
if !strings.Contains(f, "git status") {
t.Error("should show command")
}
}
func TestFragmentToolCallGrep(t *testing.T) {
f := FragmentToolCall("Grep", `{"pattern":"TODO","path":"/root/projects"}`)
if !strings.Contains(f, "TODO") {
t.Error("should show pattern")
}
if !strings.Contains(f, "/root/projects") {
t.Error("should show path")
}
}
func TestFragmentToolCallEdit(t *testing.T) {
f := FragmentToolCall("Edit", `{"file_path":"/tmp/main.go","old_string":"foo","new_string":"bar"}`)
if !strings.Contains(f, "/tmp/main.go") {
t.Error("should show file path")
}
}
func TestFragmentToolCallFallback(t *testing.T) {
f := FragmentToolCall("UnknownTool", `{"key1":"value1","key2":"value2"}`)
if !strings.Contains(f, "key1") || !strings.Contains(f, "value1") {
t.Error("fallback should show key=value pairs")
}
}
func TestFragmentToolCallNonJSON(t *testing.T) {
f := FragmentToolCall("Something", "plain text input")
if !strings.Contains(f, "plain text input") {
t.Error("should show plain text for non-JSON")
}
}
func TestFragmentToolCallTruncation(t *testing.T) {
longInput := strings.Repeat("x", 300)
f := FragmentToolCall("Something", longInput)
if !strings.Contains(f, "...") {
t.Error("should truncate long input")
}
}
func TestFragmentSystemMessage(t *testing.T) {
f := FragmentSystemMessage("Connected")
if !strings.Contains(f, "message-system") {
t.Error("missing message-system class")
}
if !strings.Contains(f, "Connected") {
t.Error("missing text")
}
}
func TestFragmentTypingIndicator(t *testing.T) {
show := FragmentTypingIndicator(true)
if !strings.Contains(show, "typing-indicator") {
t.Error("missing typing indicator")
}
hide := FragmentTypingIndicator(false)
if !strings.Contains(hide, `id="typing-indicator"`) {
t.Error("missing ID")
}
}
func TestFragmentStatus(t *testing.T) {
connected := FragmentStatus(true)
if !strings.Contains(connected, "connected") {
t.Error("missing connected class")
}
disconnected := FragmentStatus(false)
if strings.Contains(disconnected, `class="status connected"`) {
t.Error("should not have connected class when disconnected")
}
}
func TestFragmentClearInput(t *testing.T) {
f := FragmentClearInput()
if !strings.Contains(f, `id="message-input"`) {
t.Error("missing input ID")
}
}
func TestFragmentCombine(t *testing.T) {
combined := FragmentCombine("a", "b", "c")
if combined != "a\nb\nc" {
t.Errorf("got %q", combined)
}
}