rdev/internal/handlers/health_test.go
jordan 72d16929ca feat: Implement hexagonal architecture with services, webhooks, queue, and telemetry
Major refactoring to hexagonal (ports & adapters) architecture:

- Add service layer (apikey_service, project_service) for business logic
- Add webhook system with dispatcher and delivery tracking
- Add command queue with priority-based processing
- Add rate limiting with sliding window algorithm
- Add audit logging for command execution
- Add OpenTelemetry integration (traces, metrics, spans)
- Add circuit breaker for fault tolerance
- Add cached repository wrapper for performance
- Add comprehensive validation package
- Add Kubernetes client integration for pod management
- Add database migrations (allowed_ips, audit_log, rate_limiting, queue, webhooks)
- Add network policy and PodDisruptionBudget for k8s
- Remove legacy executor and projects/registry packages
- Untrack secrets.yaml (now managed via envault)
- Add coverage.out to .gitignore
- Add e2e test infrastructure with docker-compose
- Add comprehensive documentation (API, architecture, operations, plans)
- Add golangci-lint config and pre-commit hook

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 19:57:46 -07:00

92 lines
2.1 KiB
Go

package handlers
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
)
func TestHealthHandler_Health(t *testing.T) {
h := NewHealthHandler("test-service", nil, nil)
req := httptest.NewRequest("GET", "/health", nil)
rec := httptest.NewRecorder()
h.Health(rec, req)
if rec.Code != http.StatusOK {
t.Errorf("Health() status = %d, want %d", rec.Code, http.StatusOK)
}
var resp map[string]any
if err := json.NewDecoder(rec.Body).Decode(&resp); err != nil {
t.Fatalf("failed to decode response: %v", err)
}
data, ok := resp["data"].(map[string]any)
if !ok {
t.Fatalf("response missing data field")
}
if data["status"] != "ok" {
t.Errorf("status = %q, want %q", data["status"], "ok")
}
if data["service"] != "test-service" {
t.Errorf("service = %q, want %q", data["service"], "test-service")
}
}
func TestHealthHandler_Ready_NoDependencies(t *testing.T) {
// Handler with no dependencies should always be ready
h := NewHealthHandler("test-service", nil, nil)
req := httptest.NewRequest("GET", "/ready", nil)
rec := httptest.NewRecorder()
h.Ready(rec, req)
if rec.Code != http.StatusOK {
t.Errorf("Ready() status = %d, want %d", rec.Code, http.StatusOK)
}
var resp map[string]any
if err := json.NewDecoder(rec.Body).Decode(&resp); err != nil {
t.Fatalf("failed to decode response: %v", err)
}
data, ok := resp["data"].(map[string]any)
if !ok {
t.Fatalf("response missing data field")
}
if data["status"] != "ready" {
t.Errorf("status = %q, want %q", data["status"], "ready")
}
}
func TestCheckResult_JSON(t *testing.T) {
result := CheckResult{
Healthy: true,
Message: "connected",
Latency: "1ms",
}
data, err := json.Marshal(result)
if err != nil {
t.Fatalf("failed to marshal: %v", err)
}
var decoded CheckResult
if err := json.Unmarshal(data, &decoded); err != nil {
t.Fatalf("failed to unmarshal: %v", err)
}
if decoded.Healthy != result.Healthy {
t.Errorf("Healthy = %v, want %v", decoded.Healthy, result.Healthy)
}
if decoded.Message != result.Message {
t.Errorf("Message = %q, want %q", decoded.Message, result.Message)
}
}