126 lines
3.9 KiB
Go
126 lines
3.9 KiB
Go
// ©AngelaMos | 2026
|
|
// client_test.go
|
|
|
|
package ai
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
)
|
|
|
|
const ideationJSON = `{"summary":"s","why":"w","angles":["a","b","c"],"format":"video"}`
|
|
|
|
func TestOpenAICompatGenerate(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if got := r.Header.Get("Authorization"); got != "Bearer k" {
|
|
t.Errorf("Authorization = %q, want Bearer k", got)
|
|
}
|
|
body, _ := json.Marshal(map[string]any{
|
|
"choices": []map[string]any{{"message": map[string]any{"role": "assistant", "content": ideationJSON}}},
|
|
})
|
|
_, _ = w.Write(body)
|
|
}))
|
|
defer srv.Close()
|
|
|
|
c := newOpenAICompat("openai", srv.Client(), srv.URL, "gpt-4o-mini", "k")
|
|
res, err := c.Generate(context.Background(), IdeationRequest{Titles: []string{"t"}})
|
|
if err != nil {
|
|
t.Fatalf("Generate: %v", err)
|
|
}
|
|
if res.Summary != "s" || res.Format != FormatVideo || len(res.Angles) != 3 {
|
|
t.Errorf("got %+v", res)
|
|
}
|
|
if c.Name() != "openai" {
|
|
t.Errorf("Name = %q", c.Name())
|
|
}
|
|
}
|
|
|
|
func TestOpenAICompatNoKeyNoAuth(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if got := r.Header.Get("Authorization"); got != "" {
|
|
t.Errorf("Authorization = %q, want empty (qwen has no key)", got)
|
|
}
|
|
body, _ := json.Marshal(map[string]any{
|
|
"choices": []map[string]any{{"message": map[string]any{"content": ideationJSON}}},
|
|
})
|
|
_, _ = w.Write(body)
|
|
}))
|
|
defer srv.Close()
|
|
|
|
c := newOpenAICompat("qwen", srv.Client(), srv.URL, "qwen2.5:7b", "")
|
|
if _, err := c.Generate(context.Background(), IdeationRequest{Titles: []string{"t"}}); err != nil {
|
|
t.Fatalf("Generate: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestOpenAICompatNoChoices(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
_, _ = w.Write([]byte(`{"choices":[]}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
c := newOpenAICompat("openai", srv.Client(), srv.URL, "m", "k")
|
|
if _, err := c.Generate(context.Background(), IdeationRequest{}); err == nil {
|
|
t.Error("expected error on empty choices")
|
|
}
|
|
}
|
|
|
|
func TestOpenAICompatStatusError(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
_, _ = w.Write([]byte(`{"error":"bad key"}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
c := newOpenAICompat("openai", srv.Client(), srv.URL, "m", "k")
|
|
if _, err := c.Generate(context.Background(), IdeationRequest{}); err == nil {
|
|
t.Error("expected error on 401")
|
|
}
|
|
}
|
|
|
|
func TestAnthropicGenerate(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if got := r.Header.Get("x-api-key"); got != "k" {
|
|
t.Errorf("x-api-key = %q, want k", got)
|
|
}
|
|
if got := r.Header.Get("anthropic-version"); got != "2023-06-01" {
|
|
t.Errorf("anthropic-version = %q, want 2023-06-01", got)
|
|
}
|
|
body, _ := json.Marshal(map[string]any{
|
|
"stop_reason": "end_turn",
|
|
"content": []map[string]any{{"type": "text", "text": ideationJSON}},
|
|
})
|
|
_, _ = w.Write(body)
|
|
}))
|
|
defer srv.Close()
|
|
|
|
c := newAnthropic(srv.Client(), srv.URL, "claude-sonnet-4-6", "k")
|
|
res, err := c.Generate(context.Background(), IdeationRequest{Titles: []string{"t"}})
|
|
if err != nil {
|
|
t.Fatalf("Generate: %v", err)
|
|
}
|
|
if res.Summary != "s" || res.Format != FormatVideo {
|
|
t.Errorf("got %+v", res)
|
|
}
|
|
if c.Name() != ProviderAnthropic {
|
|
t.Errorf("Name = %q", c.Name())
|
|
}
|
|
}
|
|
|
|
func TestAnthropicRefusal(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
_, _ = w.Write([]byte(`{"stop_reason":"refusal","content":[]}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
c := newAnthropic(srv.Client(), srv.URL, "claude-sonnet-4-6", "k")
|
|
_, err := c.Generate(context.Background(), IdeationRequest{})
|
|
if !errors.Is(err, ErrRefused) {
|
|
t.Errorf("err = %v, want ErrRefused", err)
|
|
}
|
|
}
|