FILE / ScuroNeko/go-deepseek

client_test.go

Исходный файл и его история в репозитории.
FILE 1bb05f093837f713eac4ad5f8addc08afad20755
Files
go-deepseek/client_test.go
T
2026-07-31 14:21:48 +03:00

124 lines
3.7 KiB
Go

package deepseek
import (
"context"
"io"
"net/http"
"strings"
"testing"
)
type roundTripFunc func(*http.Request) (*http.Response, error)
func (f roundTripFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) }
func testAPI(handler roundTripFunc) *Client {
return NewClient().
SetBaseURL("https://api.example.test").
SetHTTPClient(&http.Client{Transport: handler})
}
func testHTTPResponse(body string) *http.Response {
return &http.Response{
StatusCode: http.StatusOK,
Status: "200 OK",
Header: make(http.Header),
Body: io.NopCloser(strings.NewReader(body)),
}
}
func TestRequestUnmarshallBizResponse(t *testing.T) {
tests := []struct {
name string
body string
wantValue string
wantErr string
}{
{name: "success", body: `{"code":0,"data":{"biz_code":0,"biz_data":{"value":"ok"}}}`, wantValue: "ok"},
{name: "outer error", body: `{"code":401,"msg":"unauthorized"}`, wantErr: "unauthorized (401)"},
{name: "business error", body: `{"code":0,"data":{"biz_code":23,"biz_msg":"denied"}}`, wantErr: "denied (23)"},
{name: "invalid JSON", body: `{`, wantErr: "unexpected end of JSON input"},
}
type result struct {
Value string `json:"value"`
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
req := NewRequest[result](http.MethodGet, "test", NoParams)
resp := &http.Response{Body: io.NopCloser(strings.NewReader(tt.body))}
got, err := req.unmarshallBizResponse(resp)
if tt.wantErr != "" {
if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
t.Fatalf("unmarshallBizResponse() error = %v, want containing %q", err, tt.wantErr)
}
return
}
if err != nil {
t.Fatalf("unmarshallBizResponse() error = %v", err)
}
if got.Data.Data.Value != tt.wantValue {
t.Fatalf("value = %q, want %q", got.Data.Data.Value, tt.wantValue)
}
})
}
}
func TestRequestDoWithContext(t *testing.T) {
client := testAPI(func(r *http.Request) (*http.Response, error) {
if r.Method != http.MethodPost {
t.Errorf("method = %q, want POST", r.Method)
}
if r.URL.Path != "/items" {
t.Errorf("path = %q, want /items", r.URL.Path)
}
if got := r.Header.Get("Authorization"); got != "Bearer test-token" {
t.Errorf("Authorization = %q", got)
}
if got := r.Header.Get("x-ds-pow-response"); got != "pow-answer" {
t.Errorf("x-ds-pow-response = %q", got)
}
if got := r.Header.Get("Content-Type"); got != "application/json" {
t.Errorf("Content-Type = %q", got)
}
body, err := io.ReadAll(r.Body)
if err != nil {
t.Errorf("read body: %v", err)
}
if got := string(body); got != `{"name":"value"}` {
t.Errorf("body = %s", got)
}
return testHTTPResponse(`{}`), nil
}).SetToken("test-token")
req := NewRequest[struct{}](http.MethodPost, "items", map[string]string{"name": "value"})
req.powAnswer = "pow-answer"
resp, err := req.DoWithContext(context.Background(), client)
if err != nil {
t.Fatalf("DoWithContext() error = %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Fatalf("status = %d, want 200", resp.StatusCode)
}
}
func TestRequestDoWithCanceledContext(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
client := testAPI(func(r *http.Request) (*http.Response, error) {
if err := r.Context().Err(); err != context.Canceled {
t.Errorf("request context error = %v, want context canceled", err)
}
return nil, r.Context().Err()
})
req := NewRequest[struct{}](http.MethodGet, "test", NoParams)
_, err := req.DoWithContext(ctx, client)
if err == nil || !strings.Contains(err.Error(), context.Canceled.Error()) {
t.Fatalf("DoWithContext() error = %v, want context canceled", err)
}
}