package ai import ( "encoding/json" "net/http" "testing" ) func TestBuildRequestBody(t *testing.T) { messages := []Message{ { Role: "user", Content: []ContentBlock{ {Type: "text", Text: "Hello"}, }, }, } tools := []Tool{ { Name: "test_tool", Description: "A test tool", InputSchema: json.RawMessage(`{"type":"object","properties":{}}`), }, } body, err := BuildRequestBody(messages, tools, "You are helpful.", "") if err != nil { t.Fatalf("unexpected error: %v", err) } var parsed map[string]interface{} if err := json.Unmarshal(body, &parsed); err != nil { t.Fatalf("invalid JSON: %v", err) } // Check model if m, ok := parsed["model"].(string); !ok || m != defaultModel { t.Errorf("expected model %s, got %v", defaultModel, parsed["model"]) } // Check stream if s, ok := parsed["stream"].(bool); !ok || !s { t.Errorf("expected stream true, got %v", parsed["stream"]) } // Check system prompt if s, ok := parsed["system"].(string); !ok || s != "You are helpful." { t.Errorf("expected system prompt, got %v", parsed["system"]) } // Check max_tokens if mt, ok := parsed["max_tokens"].(float64); !ok || int(mt) != 8192 { t.Errorf("expected max_tokens 8192, got %v", parsed["max_tokens"]) } // Check messages array exists msgs, ok := parsed["messages"].([]interface{}) if !ok || len(msgs) != 1 { t.Errorf("expected 1 message, got %v", parsed["messages"]) } // Check tools array exists tls, ok := parsed["tools"].([]interface{}) if !ok || len(tls) != 1 { t.Errorf("expected 1 tool, got %v", parsed["tools"]) } } func TestParseSSELine(t *testing.T) { tests := []struct { input string wantType string wantData string }{ {"event: content_block_delta", "event", "content_block_delta"}, {"data: {\"delta\":{\"text\":\"hello\"}}", "data", "{\"delta\":{\"text\":\"hello\"}}"}, {"", "", ""}, {"random line", "", ""}, {"event: message_stop", "event", "message_stop"}, {"data: [DONE]", "data", "[DONE]"}, } for _, tt := range tests { t.Run(tt.input, func(t *testing.T) { gotType, gotData := ParseSSELine(tt.input) if gotType != tt.wantType { t.Errorf("ParseSSELine(%q) type = %q, want %q", tt.input, gotType, tt.wantType) } if gotData != tt.wantData { t.Errorf("ParseSSELine(%q) data = %q, want %q", tt.input, gotData, tt.wantData) } }) } } func TestAuthHeader(t *testing.T) { // Test with API key only (no OAuth) client := NewClaudeClient(nil, "") client.SetAPIKey("sk-test-12345") req, _ := http.NewRequest("POST", "https://example.com", nil) if err := client.setAuthHeader(req); err != nil { t.Fatalf("unexpected error: %v", err) } if got := req.Header.Get("x-api-key"); got != "sk-test-12345" { t.Errorf("expected x-api-key sk-test-12345, got %q", got) } if got := req.Header.Get("Authorization"); got != "" { t.Errorf("expected no Authorization header, got %q", got) } } func TestAuthHeaderNoAuth(t *testing.T) { // No OAuth, no API key — should return error client := NewClaudeClient(nil, "") req, _ := http.NewRequest("POST", "https://example.com", nil) err := client.setAuthHeader(req) if err == nil { t.Error("expected error when no auth method available") } }