93 lines
2.6 KiB
Go
93 lines
2.6 KiB
Go
package admin
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"orchestra/internal/authz"
|
|
"orchestra/internal/domain"
|
|
"orchestra/internal/store"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestReadinessRequiresRouterAndReturnsJSON(t *testing.T) {
|
|
s, err := store.Open(t.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
h := (&Server{Store: s, RouterReady: false}).Readiness
|
|
r := httptest.NewRequest(http.MethodGet, "/readyz", nil)
|
|
w := httptest.NewRecorder()
|
|
h(w, r)
|
|
if w.Code != http.StatusServiceUnavailable {
|
|
t.Fatalf("status=%d body=%s", w.Code, w.Body)
|
|
}
|
|
if got := w.Header().Get("Content-Type"); got != "application/json" {
|
|
t.Fatalf("content type=%q", got)
|
|
}
|
|
var body struct {
|
|
Ready bool `json:"ready"`
|
|
Checks []Probe `json:"checks"`
|
|
}
|
|
if err := json.Unmarshal(w.Body.Bytes(), &body); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if body.Ready || len(body.Checks) != 2 || body.Checks[1].Name != "router" || body.Checks[1].Ready {
|
|
t.Fatalf("readiness=%+v", body)
|
|
}
|
|
}
|
|
|
|
func TestReadinessSucceedsWhenStoreAndRouterReady(t *testing.T) {
|
|
s, err := store.Open(t.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
w := httptest.NewRecorder()
|
|
(&Server{Store: s, RouterReady: true}).Readiness(w, httptest.NewRequest(http.MethodGet, "/readyz", nil))
|
|
if w.Code != http.StatusOK || !strings.Contains(w.Body.String(), `"ready":true`) {
|
|
t.Fatalf("status=%d body=%s", w.Code, w.Body)
|
|
}
|
|
}
|
|
|
|
func TestDiagnosticsRequiresFullControl(t *testing.T) {
|
|
s, err := store.Open(t.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
h := (&Server{Store: s}).Diagnostics
|
|
r := httptest.NewRequest("GET", "/v1/admin/diagnostics", nil)
|
|
r.Header.Set("X-Orchestra-Surface", string(authz.MCP))
|
|
w := httptest.NewRecorder()
|
|
h(w, r)
|
|
if w.Code != 403 || !strings.Contains(w.Body.String(), `"code":"forbidden"`) {
|
|
t.Fatalf("status=%d body=%s", w.Code, w.Body)
|
|
}
|
|
}
|
|
|
|
func TestSubscribeEmitsCursorAndEvent(t *testing.T) {
|
|
s, err := store.Open(t.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
p, _ := json.Marshal(map[string]any{"source": "test", "external_id": "1", "project": "p"})
|
|
if err := s.Append(domain.Event{ID: "e", TaskID: "t", Type: "TaskCreated", Version: 1, Payload: p}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
h := (&Server{Store: s}).Subscribe
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
r := httptest.NewRequest("GET", "/v1/events/subscribe?since=0", nil).WithContext(ctx)
|
|
w := httptest.NewRecorder()
|
|
done := make(chan struct{})
|
|
go func() { h(w, r); close(done) }()
|
|
for !strings.Contains(w.Body.String(), "id: 1") {
|
|
}
|
|
cancel()
|
|
<-done
|
|
if !strings.Contains(w.Body.String(), "id: 1") {
|
|
t.Fatalf("body=%s", w.Body)
|
|
}
|
|
}
|