package handler import ( "context" "errors" "io" "log/slog" "net/http" "net/http/httptest" "strings" "testing" "git.sundynix.cn/Blizzard/Veyra/internal/service" ) func TestLivenessAndReadinessAreIndependent(t *testing.T) { secretError := "password=secret-internal-detail" health := service.NewHealthService(nil, func(context.Context) error { return errors.New(secretError) }) router := NewRouter(health, slog.New(slog.NewTextHandler(io.Discard, nil)), IdentityOptions{}) for _, tc := range []struct { path string status int }{{"/healthz", http.StatusOK}, {"/readyz", http.StatusServiceUnavailable}, {"/api/v1/system/health", http.StatusServiceUnavailable}} { rec := httptest.NewRecorder() router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, tc.path, nil)) if rec.Code != tc.status { t.Fatalf("%s: got %d", tc.path, rec.Code) } if strings.Contains(rec.Body.String(), secretError) { t.Fatal("health endpoint leaked internal error") } if rec.Header().Get("X-Request-ID") == "" { t.Fatal("missing trace ID") } } } func TestReadyWhenBothDependenciesRespond(t *testing.T) { probe := func(context.Context) error { return nil } router := NewRouter(service.NewHealthService(probe, probe), slog.New(slog.NewTextHandler(io.Discard, nil)), IdentityOptions{}) rec := httptest.NewRecorder() router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/readyz", nil)) if rec.Code != http.StatusOK { t.Fatalf("got %d", rec.Code) } } func TestEmbeddedConsoleAndAPIBoundary(t *testing.T) { probe := func(context.Context) error { return nil } router := NewRouter(service.NewHealthService(probe, probe), slog.New(slog.NewTextHandler(io.Discard, nil)), IdentityOptions{}) for _, path := range []string{"/", "/research/candidates"} { rec := httptest.NewRecorder() router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, path, nil)) if rec.Code == http.StatusServiceUnavailable { t.Skip("build management console before testing embedded assets") } if rec.Code != http.StatusOK || !strings.Contains(rec.Body.String(), "