Files
descrybe/apps/api/internal/httpapi/admin_readiness_test.go
T

90 lines
2.9 KiB
Go
Raw Normal View History

package httpapi
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/alexedwards/scs/v2"
"github.com/descrybe/descrybe-v2/apps/api/internal/auth"
"github.com/descrybe/descrybe-v2/apps/api/internal/config"
"github.com/google/uuid"
)
func TestHandleAdminReadinessNilPool(t *testing.T) {
t.Parallel()
s := &Server{}
req := httptest.NewRequest(http.MethodGet, "/api/admin/readiness", nil)
rec := httptest.NewRecorder()
s.handleAdminReadiness(rec, req)
if rec.Code != http.StatusServiceUnavailable {
t.Fatalf("status=%d want 503 body=%s", rec.Code, rec.Body.String())
}
}
// TestRouterAdminReadinessMounted locks the P1-15 SPA contract: after session +
// platform-admin gates, GET /api/admin/readiness must reach the handler (503 with
// nil pool), not chi 404. Unauthed probes alone cannot prove the mount — any
// /api/admin/* returns 401 from RequireSession whether or not /readiness exists.
func TestRouterAdminReadinessMounted(t *testing.T) {
t.Parallel()
sm := scs.New()
sm.Cookie.Name = "descrybe_session"
uid := uuid.MustParse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
s := &Server{
Config: config.Config{
CSRFCookieName: "descrybe_csrf",
WebOrigin: "http://localhost:5173",
},
Sessions: sm,
Auth: &auth.Service{},
testPlatformAdmin: func(_ context.Context, got uuid.UUID) (bool, error) {
return got == uid, nil
},
}
var token string
seed := LoadSession(sm)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
sm.Put(r.Context(), auth.SessionUserIDKey, uid.String())
w.WriteHeader(http.StatusNoContent)
}))
seedRec := httptest.NewRecorder()
seed.ServeHTTP(seedRec, httptest.NewRequest(http.MethodGet, "/seed", nil))
for _, c := range seedRec.Result().Cookies() {
if c.Name == sm.Cookie.Name {
token = c.Value
}
}
if token == "" {
t.Fatal("expected session cookie from seed request")
}
h := s.Router()
unauth := httptest.NewRecorder()
h.ServeHTTP(unauth, httptest.NewRequest(http.MethodGet, "/api/admin/readiness", nil))
if unauth.Code != http.StatusUnauthorized {
t.Fatalf("unauth status=%d want 401 body=%s", unauth.Code, unauth.Body.String())
}
mounted := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/api/admin/readiness", nil)
req.AddCookie(&http.Cookie{Name: sm.Cookie.Name, Value: token})
h.ServeHTTP(mounted, req)
if mounted.Code == http.StatusNotFound {
t.Fatalf("readiness not mounted: status=404 body=%s", mounted.Body.String())
}
if mounted.Code != http.StatusServiceUnavailable {
t.Fatalf("mounted status=%d want 503 (nil pool) body=%s", mounted.Code, mounted.Body.String())
}
missing := httptest.NewRecorder()
missReq := httptest.NewRequest(http.MethodGet, "/api/admin/does-not-exist", nil)
missReq.AddCookie(&http.Cookie{Name: sm.Cookie.Name, Value: token})
h.ServeHTTP(missing, missReq)
if missing.Code != http.StatusNotFound {
t.Fatalf("unknown admin path status=%d want 404 body=%s", missing.Code, missing.Body.String())
}
}