rdev/internal/handlers/sdlc_orchestrator_test.go
jordan 84af398d85
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
refactor: add timeout constants for agent execution tiers
Add TimeoutAgentExecution (22m) to handlers for synchronous SDLC
execution, and TimeoutAgent{Default,Medium,Heavy} (12/22/47m) to
workers for tiered agent task execution. Aligns with SDLC action
complexity tiers and prevents inline duration literals.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-11 10:48:24 -07:00

189 lines
6.0 KiB
Go

package handlers
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/go-chi/chi/v5"
"github.com/orchard9/rdev/internal/domain"
"github.com/orchard9/rdev/internal/sdlc"
"github.com/orchard9/rdev/internal/service"
)
func setupOrchestratorHandler(exec *testSDLCExecutor) (*SDLCOrchestratorHandler, *chi.Mux) {
repo := &testSDLCProjectRepo{
project: &domain.Project{ID: "test-project", PodName: "test-pod"},
}
sdlcSvc := service.NewSDLCService(exec, repo)
orchestrator := service.NewSDLCOrchestratorService(
sdlcSvc,
nil, // no agent registry for handler tests
nil, // no git committer for handler tests
repo,
nil, // no build service for handler tests
nil, // no db for handler tests
)
handler := NewSDLCOrchestratorHandler(orchestrator)
r := chi.NewRouter()
r.Use(testAdminAuth)
handler.Mount(r)
return handler, r
}
func TestSDLCOrchestratorHandler_Execute(t *testing.T) {
exec := &testSDLCExecutor{
classification: &sdlc.Classification{
Action: sdlc.ActionIdle,
Feature: "auth-flow",
Message: "No action needed",
},
}
_, router := setupOrchestratorHandler(exec)
body, _ := json.Marshal(service.ExecuteRequest{Feature: "auth-flow"})
req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/execute", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d: %s", w.Code, w.Body.String())
}
}
func TestSDLCOrchestratorHandler_Execute_MissingFeature(t *testing.T) {
exec := &testSDLCExecutor{}
_, router := setupOrchestratorHandler(exec)
body, _ := json.Marshal(service.ExecuteRequest{})
req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/execute", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusBadRequest {
t.Errorf("expected status 400, got %d: %s", w.Code, w.Body.String())
}
}
func TestSDLCOrchestratorHandler_Execute_InvalidBody(t *testing.T) {
exec := &testSDLCExecutor{}
_, router := setupOrchestratorHandler(exec)
req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/execute", bytes.NewReader([]byte("not json")))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusBadRequest {
t.Errorf("expected status 400, got %d: %s", w.Code, w.Body.String())
}
}
func TestSDLCOrchestratorHandler_Execute_FeatureNotFound(t *testing.T) {
exec := &testSDLCExecutor{err: sdlc.ErrFeatureNotFound}
_, router := setupOrchestratorHandler(exec)
body, _ := json.Marshal(service.ExecuteRequest{Feature: "nonexistent"})
req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/execute", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusNotFound {
t.Errorf("expected status 404, got %d: %s", w.Code, w.Body.String())
}
}
func TestSDLCOrchestratorHandler_Execute_Transition(t *testing.T) {
exec := &testSDLCExecutor{
classification: &sdlc.Classification{
Action: sdlc.ActionTransition,
Feature: "auth-flow",
TransitionTo: sdlc.PhaseSpecified,
},
}
_, router := setupOrchestratorHandler(exec)
body, _ := json.Marshal(service.ExecuteRequest{Feature: "auth-flow"})
req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/execute", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d: %s", w.Code, w.Body.String())
}
}
func TestSDLCOrchestratorHandler_Resolve(t *testing.T) {
exec := &testSDLCExecutor{
classification: &sdlc.Classification{
Action: sdlc.ActionIdle,
Feature: "auth-flow",
},
}
_, router := setupOrchestratorHandler(exec)
body, _ := json.Marshal(service.ResolveRequest{Feature: "auth-flow"})
req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/resolve", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("expected status 200, got %d: %s", w.Code, w.Body.String())
}
}
func TestSDLCOrchestratorHandler_Resolve_MissingFeature(t *testing.T) {
exec := &testSDLCExecutor{}
_, router := setupOrchestratorHandler(exec)
body, _ := json.Marshal(service.ResolveRequest{})
req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/resolve", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusBadRequest {
t.Errorf("expected status 400, got %d: %s", w.Code, w.Body.String())
}
}
func TestSDLCOrchestratorHandler_Commit(t *testing.T) {
exec := &testSDLCExecutor{}
_, router := setupOrchestratorHandler(exec)
body, _ := json.Marshal(service.CommitRequest{Feature: "auth-flow", Message: "implement auth"})
req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/commit", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
// Expected 500 because git committer is nil in test setup
if w.Code != http.StatusInternalServerError {
t.Errorf("expected status 500 (no git committer), got %d: %s", w.Code, w.Body.String())
}
}
func TestSDLCOrchestratorHandler_Commit_MissingMessage(t *testing.T) {
exec := &testSDLCExecutor{}
_, router := setupOrchestratorHandler(exec)
body, _ := json.Marshal(service.CommitRequest{Feature: "auth-flow"})
req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/commit", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusBadRequest {
t.Errorf("expected status 400, got %d: %s", w.Code, w.Body.String())
}
}