update see calss
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
package httpapi
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func readSourceFile(t *testing.T, name string) string {
|
||||
t.Helper()
|
||||
b, err := os.ReadFile(name)
|
||||
if err != nil {
|
||||
t.Fatalf("read %s: %v", name, err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// Filter parsing must reject bad input before touching the database, so a typo in
|
||||
// the admin UI cannot turn into a full-table scan or a 500.
|
||||
func TestHandleAdminListAICalls_rejectsBadFilters(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := &Server{}
|
||||
cases := map[string]string{
|
||||
"invalid company_id": "?company_id=not-a-uuid",
|
||||
"invalid user_id": "?user_id=123",
|
||||
"invalid job_id": "?job_id=abc",
|
||||
"invalid raw_product_id": "?raw_product_id=xyz",
|
||||
"invalid outcome": "?outcome=maybe",
|
||||
"invalid before cursor": "?before=yesterday",
|
||||
}
|
||||
for name, query := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/admin/ai-calls"+query, nil)
|
||||
rec := httptest.NewRecorder()
|
||||
s.handleAdminListAICalls(rec, req)
|
||||
if rec.Code != http.StatusBadRequest {
|
||||
t.Fatalf("status=%d want 400 body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleAdminGetAICall_rejectsBadID(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := &Server{}
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/admin/ai-calls/nope", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
s.handleAdminGetAICall(rec, req)
|
||||
if rec.Code != http.StatusBadRequest {
|
||||
t.Fatalf("status=%d want 400 body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
// The list endpoint returns previews, never the full bodies — one unfiltered
|
||||
// request must not stream a tenant's whole prompt corpus out of the admin API.
|
||||
func TestAdminAICallsListSQL_selectsPreviewsNotFullBodies(t *testing.T) {
|
||||
t.Parallel()
|
||||
sql := adminAICallsListSQL("TRUE", 1)
|
||||
selectList := sql[strings.Index(sql, "SELECT"):strings.Index(sql, "FROM ai_call_logs")]
|
||||
|
||||
// A bare column followed by a comma is the whole body; the length()/left()
|
||||
// wrappers put a ")" in between.
|
||||
for _, bare := range []string{" l.system_prompt,", " l.user_prompt,", " l.response_text,"} {
|
||||
if strings.Contains(selectList, bare) {
|
||||
t.Fatalf("list selects a full body (%q):\n%s", strings.TrimSpace(bare), selectList)
|
||||
}
|
||||
}
|
||||
for _, want := range []string{
|
||||
"left(l.user_prompt, 240)",
|
||||
"left(l.response_text, 240)",
|
||||
"length(l.system_prompt)",
|
||||
} {
|
||||
if !strings.Contains(selectList, want) {
|
||||
t.Fatalf("list should select %s:\n%s", want, selectList)
|
||||
}
|
||||
}
|
||||
if !strings.Contains(sql, "ORDER BY l.created_at DESC") || !strings.Contains(sql, "LIMIT $1") {
|
||||
t.Fatalf("list must page newest-first with a bound limit:\n%s", sql)
|
||||
}
|
||||
}
|
||||
|
||||
// The detail endpoint is the only place full bodies come from.
|
||||
func TestAdminAICallsDetail_returnsFullBodies(t *testing.T) {
|
||||
t.Parallel()
|
||||
src := readSourceFile(t, "admin_ai_calls_handlers.go")
|
||||
detail := src[strings.Index(src, "func (s *Server) handleAdminGetAICall"):]
|
||||
if !strings.Contains(detail, "l.system_prompt, l.user_prompt, l.response_text") {
|
||||
t.Fatal("detail handler must select the full bodies")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user