package provider import ( "context" "fmt" "net/http" "net/http/httptest" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "nex/backend/internal/conversion" ) func TestNewClient(t *testing.T) { client := NewClient() require.NotNil(t, client) assert.NotNil(t, client.httpClient) assert.Equal(t, 4096, client.streamCfg.InitialBufferSize) assert.Equal(t, 65536, client.streamCfg.MaxBufferSize) assert.Equal(t, 100, client.streamCfg.ChannelBufferSize) } func TestDefaultStreamConfig(t *testing.T) { cfg := DefaultStreamConfig() assert.Equal(t, 4096, cfg.InitialBufferSize) assert.Equal(t, 65536, cfg.MaxBufferSize) assert.Equal(t, 100, cfg.ChannelBufferSize) } func TestClient_Send_Success(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "POST", r.Method) assert.Equal(t, "application/json", r.Header.Get("Content-Type")) assert.Equal(t, "Bearer test-key", r.Header.Get("Authorization")) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) w.Write([]byte(`{"id":"test","model":"gpt-4"}`)) })) defer server.Close() client := NewClient() spec := conversion.HTTPRequestSpec{ URL: server.URL + "/v1/chat/completions", Method: "POST", Headers: map[string]string{ "Authorization": "Bearer test-key", "Content-Type": "application/json", }, Body: []byte(`{"model":"gpt-4","messages":[]}`), } result, err := client.Send(context.Background(), spec) require.NoError(t, err) assert.Equal(t, 200, result.StatusCode) assert.Contains(t, string(result.Body), "test") } func TestClient_Send_ErrorResponse(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusUnauthorized) w.Write([]byte(`{"error":{"message":"Invalid API key"}}`)) })) defer server.Close() client := NewClient() spec := conversion.HTTPRequestSpec{ URL: server.URL + "/v1/chat/completions", Method: "POST", Headers: map[string]string{"Authorization": "Bearer bad-key"}, Body: []byte(`{}`), } result, err := client.Send(context.Background(), spec) require.NoError(t, err) assert.Equal(t, 401, result.StatusCode) } func TestClient_Send_ConnectionError(t *testing.T) { client := NewClient() spec := conversion.HTTPRequestSpec{ URL: "http://localhost:1/v1/chat/completions", Method: "POST", } _, err := client.Send(context.Background(), spec) assert.Error(t, err) } func TestClient_SendStream_CreatesChannel(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/event-stream") w.WriteHeader(http.StatusOK) })) defer server.Close() client := NewClient() spec := conversion.HTTPRequestSpec{ URL: server.URL + "/v1/chat/completions", Method: "POST", Headers: map[string]string{"Authorization": "Bearer test-key"}, Body: []byte(`{}`), } eventChan, err := client.SendStream(context.Background(), spec) require.NoError(t, err) require.NotNil(t, eventChan) for range eventChan { } } func TestClient_SendStream_ErrorResponse(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusInternalServerError) })) defer server.Close() client := NewClient() spec := conversion.HTTPRequestSpec{ URL: server.URL + "/v1/chat/completions", Method: "POST", Headers: map[string]string{"Authorization": "Bearer key"}, Body: []byte(`{}`), } _, err := client.SendStream(context.Background(), spec) assert.Error(t, err) } func TestIsNetworkError(t *testing.T) { tests := []struct { input string want bool }{ {"connection reset by peer", true}, {"broken pipe", true}, {"network is unreachable", true}, {"timeout waiting for response", true}, {"unexpected EOF", true}, {"normal error", false}, {"", false}, } for _, tt := range tests { err := fmt.Errorf("%s", tt.input) assert.Equal(t, tt.want, isNetworkError(err), "isNetworkError(%q)", tt.input) } }