daemon: integrate QoL slices 1-5 (model/rename/catalog, history deletes, stats, repo prepare+imageUsed+built) — 95.3% cover green
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
package main
|
||||
|
||||
// api_stats_test.go — REST shape of /api/sessions/:id/stats and /api/stats.
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAPISessionStatsShape(t *testing.T) {
|
||||
ts, store := newTestServer(t)
|
||||
appendAgentEnd(t, store, "s1", 1, `{"usage":{"inputTokens":1200,"outputTokens":340,"totalCost":0.25}}`)
|
||||
appendAgentEnd(t, store, "s1", 2, `{}`)
|
||||
|
||||
code, body := apiReq(t, http.MethodGet, ts.URL+"/api/sessions/s1/stats", testToken, "")
|
||||
if code != http.StatusOK {
|
||||
t.Fatalf("stats status = %d", code)
|
||||
}
|
||||
var stats map[string]any
|
||||
if err := json.Unmarshal([]byte(body), &stats); err != nil {
|
||||
t.Fatalf("decode: %v", err)
|
||||
}
|
||||
if stats["turns"].(float64) != 2 ||
|
||||
stats["inputTokens"].(float64) != 1200 ||
|
||||
stats["outputTokens"].(float64) != 340 ||
|
||||
stats["totalCost"].(float64) != 0.25 {
|
||||
t.Fatalf("stats = %v", stats)
|
||||
}
|
||||
if _, ok := stats["sessionsCount"]; ok {
|
||||
t.Fatalf("per-session stats must not carry sessionsCount: %v", stats)
|
||||
}
|
||||
|
||||
// unknown session: 200 with zeros (matches events endpoint behavior)
|
||||
code, body = apiReq(t, http.MethodGet, ts.URL+"/api/sessions/ghost/stats", testToken, "")
|
||||
if code != http.StatusOK {
|
||||
t.Fatalf("ghost status = %d", code)
|
||||
}
|
||||
var ghost map[string]any
|
||||
if err := json.Unmarshal([]byte(body), &ghost); err != nil {
|
||||
t.Fatalf("decode ghost: %v", err)
|
||||
}
|
||||
if len(ghost) != 4 || ghost["turns"].(float64) != 0 {
|
||||
t.Fatalf("ghost stats = %v, want four zero fields", ghost)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPIStatsTotalsAndOnlineCount(t *testing.T) {
|
||||
ts, store := newTestServer(t)
|
||||
appendAgentEnd(t, store, "s1", 1, `{"usage":{"inputTokens":1200000,"outputTokens":340000,"totalCost":4.2}}`)
|
||||
appendAgentEnd(t, store, "s2", 1, `{"usage":{"inputTokens":50,"outputTokens":10,"totalCost":0}}`)
|
||||
|
||||
get := func() map[string]any {
|
||||
t.Helper()
|
||||
code, body := apiReq(t, http.MethodGet, ts.URL+"/api/stats", testToken, "")
|
||||
if code != http.StatusOK {
|
||||
t.Fatalf("/api/stats status = %d", code)
|
||||
}
|
||||
var m map[string]any
|
||||
if err := json.Unmarshal([]byte(body), &m); err != nil {
|
||||
t.Fatalf("decode: %v", err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
totals := get()
|
||||
if totals["turns"].(float64) != 2 ||
|
||||
totals["inputTokens"].(float64) != 1200050 ||
|
||||
totals["outputTokens"].(float64) != 340010 ||
|
||||
totals["totalCost"].(float64) != 4.2 ||
|
||||
totals["sessionsCount"].(float64) != 2 {
|
||||
t.Fatalf("totals = %v", totals)
|
||||
}
|
||||
if totals["onlineCount"].(float64) != 0 {
|
||||
t.Fatalf("onlineCount = %v, want 0 with no agents", totals["onlineCount"])
|
||||
}
|
||||
|
||||
// one registered agent connection must show up as online
|
||||
ws := dialAgent(t, ts)
|
||||
if err := ws.WriteJSON(helloFrame("s-live")); err != nil {
|
||||
t.Fatalf("hello: %v", err)
|
||||
}
|
||||
if _, _, err := ws.ReadMessage(); err != nil { // welcome
|
||||
t.Fatalf("welcome: %v", err)
|
||||
}
|
||||
online := get()
|
||||
if online["onlineCount"].(float64) != 1 {
|
||||
t.Fatalf("onlineCount = %v, want 1 after hello", online["onlineCount"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPIStatsClosedStore500(t *testing.T) {
|
||||
ts, store := newTestServer(t)
|
||||
if err := store.Close(); err != nil {
|
||||
t.Fatalf("close store: %v", err)
|
||||
}
|
||||
if code, _ := apiReq(t, http.MethodGet, ts.URL+"/api/stats", testToken, ""); code != http.StatusInternalServerError {
|
||||
t.Fatal("stats with broken store must 500")
|
||||
}
|
||||
if code, _ := apiReq(t, http.MethodGet, ts.URL+"/api/sessions/s1/stats", testToken, ""); code != http.StatusInternalServerError {
|
||||
t.Fatal("session stats with broken store must 500")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user