f99010fae1
CI / lint (push) Failing after 1s
CI / frontend (push) Failing after 1s
CI / scripts (push) Failing after 1s
CI / Go Test (ubuntu-latest) (push) Failing after 0s
CI / frontend-node-25 (push) Failing after 1s
CI / docs (push) Failing after 0s
CI / coverage (push) Failing after 0s
CI / e2e (push) Failing after 0s
Docker / build-and-push (push) Failing after 1s
CI / integration (push) Failing after 4m43s
CI / Go Test (windows-latest) (push) Has been cancelled
CI / Desktop Unit Tests (Windows) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Linux (arm64)) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Linux) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Windows) (push) Has been cancelled
Desktop Artifacts (macOS) / Desktop Build (macOS (aarch64)) (push) Has been cancelled
Desktop Artifacts (macOS) / Desktop Build (macOS (x86_64)) (push) Has been cancelled
81 lines
2.1 KiB
Go
81 lines
2.1 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"testing"
|
|
|
|
"go.kenn.io/agentsview/internal/db"
|
|
)
|
|
|
|
// readOnlyUsageSpy stubs the Store interface and returns
|
|
// db.ErrReadOnly from the three usage queries. It lets us
|
|
// verify the handlers map the sentinel error to 501 Not
|
|
// Implemented without spinning up a real PG instance.
|
|
type readOnlyUsageSpy struct {
|
|
db.Store
|
|
}
|
|
|
|
func (readOnlyUsageSpy) GetDailyUsage(
|
|
_ context.Context, _ db.UsageFilter,
|
|
) (db.DailyUsageResult, error) {
|
|
return db.DailyUsageResult{}, db.ErrReadOnly
|
|
}
|
|
|
|
func (readOnlyUsageSpy) GetTopSessionsByCost(
|
|
_ context.Context, _ db.UsageFilter, _ int,
|
|
) ([]db.TopSessionEntry, error) {
|
|
return nil, db.ErrReadOnly
|
|
}
|
|
|
|
func (readOnlyUsageSpy) GetUsageSessionCounts(
|
|
_ context.Context, _ db.UsageFilter,
|
|
) (db.UsageSessionCounts, error) {
|
|
return db.UsageSessionCounts{}, db.ErrReadOnly
|
|
}
|
|
|
|
func (readOnlyUsageSpy) GetUsageMatchingSessionCount(
|
|
_ context.Context, _ db.UsageFilter,
|
|
) (int, error) {
|
|
return 0, db.ErrReadOnly
|
|
}
|
|
|
|
// TestUsageHandlers_ReturnNotImplementedOnReadOnlyStore locks
|
|
// in the Postgres-backend contract: when the underlying Store
|
|
// reports a usage query as unavailable (db.ErrReadOnly), both
|
|
// usage HTTP endpoints must surface 501 Not Implemented rather
|
|
// than silently returning an empty body, which would look like
|
|
// "no usage data" to the user.
|
|
func TestUsageHandlers_ReturnNotImplementedOnReadOnlyStore(
|
|
t *testing.T,
|
|
) {
|
|
s := newRoutedTestServerWithStore(t, readOnlyUsageSpy{})
|
|
|
|
cases := []struct {
|
|
name string
|
|
path string
|
|
}{
|
|
{
|
|
name: "summary",
|
|
path: "/api/v1/usage/summary?" +
|
|
"from=2024-06-01&to=2024-06-03",
|
|
},
|
|
{
|
|
name: "top-sessions",
|
|
path: "/api/v1/usage/top-sessions?" +
|
|
"from=2024-06-01&to=2024-06-03",
|
|
},
|
|
{
|
|
name: "pairwise",
|
|
path: "/api/v1/usage/pairwise-comparison?" +
|
|
"from=2024-06-01&to=2024-06-03&left_dimension=model&left_value=claude-sonnet-4-20250514&right_dimension=project&right_value=beta",
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
w := serveGet(t, s, tc.path)
|
|
assertRecorderStatus(t, w, http.StatusNotImplemented)
|
|
})
|
|
}
|
|
}
|