package voiceprovider import ( "context" "encoding/json" "net/http" "net/http/httptest" "testing" "time" ) func TestHTTPClientClassifiesTemporaryAndPermanentResponses(t *testing.T) { tests := []struct { name string status int temporary bool }{ {name: "rate limited", status: http.StatusTooManyRequests, temporary: true}, {name: "unavailable", status: http.StatusServiceUnavailable, temporary: true}, {name: "bad request", status: http.StatusBadRequest, temporary: false}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(test.status) })) defer server.Close() client, err := NewHTTPClient(server.URL, "0123456789abcdef", time.Second) if err != nil { t.Fatal(err) } _, err = client.Start(context.Background(), StartRequest{TaskRef: "task", RoomID: "room", DeviceUserID: "device", AgentUserID: "agent", ConversationID: "conversation"}) if err == nil || IsTemporary(err) != test.temporary { t.Fatalf("error=%v temporary=%v", err, IsTemporary(err)) } }) } } func TestHTTPClientQueriesProviderTaskAndClassifiesNotFound(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/mock/v1/voice-chats:query" || r.Header.Get("X-Mock-Provider-Key") == "" { t.Fatalf("unexpected query request: %s", r.URL.Path) } var input QueryRequest if err := json.NewDecoder(r.Body).Decode(&input); err != nil { t.Fatal(err) } if input.TaskRef == "missing" { w.WriteHeader(http.StatusNotFound) return } _ = json.NewEncoder(w).Encode(QueryResponse{TaskRef: input.TaskRef, Status: "ACTIVE"}) })) defer server.Close() client, err := NewHTTPClient(server.URL, "0123456789abcdef", time.Second) if err != nil { t.Fatal(err) } result, err := client.Query(context.Background(), QueryRequest{TaskRef: "known", ConversationID: "conversation"}) if err != nil || result.Status != "ACTIVE" { t.Fatalf("result=%+v error=%v", result, err) } _, err = client.Query(context.Background(), QueryRequest{TaskRef: "missing", ConversationID: "conversation"}) if !IsNotFound(err) || IsTemporary(err) { t.Fatalf("expected permanent not found, got %v", err) } }