Files
Cyrene_v2/backend/services/gateway/api/router_test.go
T
Aska 6811480786 feat(gateway): wire real services into Gateway API handlers
- Router accepts full Dependencies (memory/voice/orchestrator/WShub)
- Memory API: CRUD + search endpoints with PostgreSQL persistence
- Voice API: STT/TTS endpoints
- Admin dashboard: real uptime + service status
- WebSocket chat: routes to AI-Core orchestrator pipeline
- APIAdapter bridges memory domain model to REST interface
- Smoke test: memory CRUD + session creation verified
2026-08-12 12:04:31 +08:00

137 lines
3.3 KiB
Go

package api
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestHealth(t *testing.T) {
r := New(Dependencies{AuthMgr: NewStubAuthManager()})
srv := httptest.NewServer(r)
defer srv.Close()
resp, err := http.Get(srv.URL + "/api/v1/health")
if err != nil {
t.Fatalf("GET health: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Errorf("expected 200, got %d", resp.StatusCode)
}
}
func TestLoginAndProtectedEndpoint(t *testing.T) {
auth := NewStubAuthManager()
r := New(Dependencies{AuthMgr: auth})
srv := httptest.NewServer(r)
defer srv.Close()
// Login
resp, err := http.Post(srv.URL+"/api/v1/auth/login", "application/json",
strings.NewReader(`{"username":"admin","password":"admin"}`))
if err != nil {
t.Fatalf("POST login: %v", err)
}
resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Errorf("login: expected 200, got %d", resp.StatusCode)
}
// Use token for protected endpoint
req, _ := http.NewRequest("GET", srv.URL+"/api/v1/sessions", nil)
req.Header.Set("Authorization", "Bearer stub-token-admin")
resp2, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("GET sessions: %v", err)
}
resp2.Body.Close()
if resp2.StatusCode != http.StatusOK {
t.Errorf("sessions: expected 200, got %d", resp2.StatusCode)
}
}
func TestLoginWrongPassword(t *testing.T) {
auth := NewStubAuthManager()
r := New(Dependencies{AuthMgr: auth})
srv := httptest.NewServer(r)
defer srv.Close()
resp, err := http.Post(srv.URL+"/api/v1/auth/login", "application/json",
strings.NewReader(`{"username":"admin","password":"wrong"}`))
if err != nil {
t.Fatalf("POST login: %v", err)
}
resp.Body.Close()
if resp.StatusCode != http.StatusUnauthorized {
t.Errorf("expected 401, got %d", resp.StatusCode)
}
}
func TestProtectedWithoutToken(t *testing.T) {
auth := NewStubAuthManager()
r := New(Dependencies{AuthMgr: auth})
srv := httptest.NewServer(r)
defer srv.Close()
resp, err := http.Get(srv.URL + "/api/v1/sessions")
if err != nil {
t.Fatalf("GET sessions: %v", err)
}
resp.Body.Close()
if resp.StatusCode != http.StatusUnauthorized {
t.Errorf("expected 401, got %d", resp.StatusCode)
}
}
func TestStubAuthManager(t *testing.T) {
m := NewStubAuthManager()
// Login as admin
token, err := m.Login("admin", "admin")
if err != nil {
t.Fatalf("Login: %v", err)
}
uid, uname, role, err := m.ValidateToken(token)
if err != nil {
t.Fatalf("ValidateToken: %v", err)
}
if uid != "admin" || uname != "admin" || role != "admin" {
t.Errorf("wrong claims: %s/%s/%s", uid, uname, role)
}
// Invalid token
_, _, _, err = m.ValidateToken("bogus")
if err == nil {
t.Error("expected error for bogus token")
}
}
func TestCORSHeaders(t *testing.T) {
r := New(Dependencies{AuthMgr: NewStubAuthManager()})
srv := httptest.NewServer(r)
defer srv.Close()
req, _ := http.NewRequest("OPTIONS", srv.URL+"/api/v1/health", nil)
req.Header.Set("Origin", "http://localhost:5173")
resp, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("OPTIONS: %v", err)
}
resp.Body.Close()
if resp.StatusCode != http.StatusNoContent {
t.Errorf("expected 204 for OPTIONS, got %d", resp.StatusCode)
}
if resp.Header.Get("Access-Control-Allow-Origin") == "" {
t.Error("expected CORS header")
}
}