test(e2e): add spawn workflow end-to-end tests
This commit is contained in:
617
tests/e2e_spawn.sh
Executable file
617
tests/e2e_spawn.sh
Executable file
@@ -0,0 +1,617 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# E2E test script for the AMC spawn workflow.
|
||||
# Tests the full flow from API call to Zellij pane creation.
|
||||
#
|
||||
# Usage:
|
||||
# ./tests/e2e_spawn.sh # Safe mode (no actual spawning)
|
||||
# ./tests/e2e_spawn.sh --spawn # Full test including real agent spawn
|
||||
|
||||
SERVER_URL="http://localhost:7400"
|
||||
TEST_PROJECT="amc" # Must exist in ~/projects/
|
||||
AUTH_TOKEN=""
|
||||
SPAWN_MODE=false
|
||||
PASSED=0
|
||||
FAILED=0
|
||||
SKIPPED=0
|
||||
|
||||
# Parse args
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--spawn) SPAWN_MODE=true ;;
|
||||
*) echo "Unknown arg: $arg"; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
log_test() { echo -e "\n${GREEN}[TEST]${NC} $1"; }
|
||||
log_pass() { echo -e "${GREEN}[PASS]${NC} $1"; ((PASSED++)); }
|
||||
log_fail() { echo -e "${RED}[FAIL]${NC} $1"; ((FAILED++)); }
|
||||
log_skip() { echo -e "${YELLOW}[SKIP]${NC} $1"; ((SKIPPED++)); }
|
||||
|
||||
# Track spawned panes for cleanup
|
||||
SPAWNED_PANE_NAMES=()
|
||||
|
||||
cleanup() {
|
||||
if [[ ${#SPAWNED_PANE_NAMES[@]} -gt 0 ]]; then
|
||||
log_info "Cleaning up spawned panes..."
|
||||
for pane_name in "${SPAWNED_PANE_NAMES[@]}"; do
|
||||
# Best-effort: close panes we spawned during tests
|
||||
zellij --session infra action close-pane --name "$pane_name" 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Pre-flight checks
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
preflight() {
|
||||
log_test "Pre-flight checks"
|
||||
|
||||
# curl available?
|
||||
if ! command -v curl &>/dev/null; then
|
||||
log_error "curl not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# jq available?
|
||||
if ! command -v jq &>/dev/null; then
|
||||
log_error "jq not found (required for JSON assertions)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Server running?
|
||||
if ! curl -sf "${SERVER_URL}/api/health" >/dev/null 2>&1; then
|
||||
log_error "Server not running at ${SERVER_URL}"
|
||||
log_error "Start with: python -m amc_server.server"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test project exists?
|
||||
if [[ ! -d "$HOME/projects/${TEST_PROJECT}" ]]; then
|
||||
log_error "Test project '${TEST_PROJECT}' not found at ~/projects/${TEST_PROJECT}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_pass "Pre-flight checks passed"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Extract auth token from dashboard HTML
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
extract_auth_token() {
|
||||
log_test "Extract auth token from dashboard"
|
||||
|
||||
local html
|
||||
html=$(curl -sf "${SERVER_URL}/")
|
||||
|
||||
AUTH_TOKEN=$(echo "$html" | grep -o 'AMC_AUTH_TOKEN = "[^"]*"' | cut -d'"' -f2)
|
||||
if [[ -z "$AUTH_TOKEN" ]]; then
|
||||
log_error "Could not extract auth token from dashboard HTML"
|
||||
log_error "Check that index.html contains <!-- AMC_AUTH_TOKEN --> placeholder"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_pass "Auth token extracted (${AUTH_TOKEN:0:8}...)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: GET /api/health
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_health_endpoint() {
|
||||
log_test "GET /api/health"
|
||||
|
||||
local response
|
||||
response=$(curl -sf "${SERVER_URL}/api/health")
|
||||
|
||||
local ok
|
||||
ok=$(echo "$response" | jq -r '.ok')
|
||||
if [[ "$ok" != "true" ]]; then
|
||||
log_fail "Health endpoint returned ok=$ok"
|
||||
return
|
||||
fi
|
||||
|
||||
# Must include zellij_available and zellij_session fields
|
||||
local has_zellij_available has_zellij_session
|
||||
has_zellij_available=$(echo "$response" | jq 'has("zellij_available")')
|
||||
has_zellij_session=$(echo "$response" | jq 'has("zellij_session")')
|
||||
|
||||
if [[ "$has_zellij_available" != "true" || "$has_zellij_session" != "true" ]]; then
|
||||
log_fail "Health response missing expected fields: $response"
|
||||
return
|
||||
fi
|
||||
|
||||
local zellij_available
|
||||
zellij_available=$(echo "$response" | jq -r '.zellij_available')
|
||||
log_pass "Health OK (zellij_available=$zellij_available)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: GET /api/projects
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_projects_endpoint() {
|
||||
log_test "GET /api/projects"
|
||||
|
||||
local response
|
||||
response=$(curl -sf "${SERVER_URL}/api/projects")
|
||||
|
||||
local ok
|
||||
ok=$(echo "$response" | jq -r '.ok')
|
||||
if [[ "$ok" != "true" ]]; then
|
||||
log_fail "Projects endpoint returned ok=$ok"
|
||||
return
|
||||
fi
|
||||
|
||||
local project_count
|
||||
project_count=$(echo "$response" | jq '.projects | length')
|
||||
if [[ "$project_count" -lt 1 ]]; then
|
||||
log_fail "No projects returned (expected at least 1)"
|
||||
return
|
||||
fi
|
||||
|
||||
# Verify test project is in the list
|
||||
local has_test_project
|
||||
has_test_project=$(echo "$response" | jq --arg p "$TEST_PROJECT" '[.projects[] | select(. == $p)] | length')
|
||||
if [[ "$has_test_project" -lt 1 ]]; then
|
||||
log_fail "Test project '$TEST_PROJECT' not in projects list"
|
||||
return
|
||||
fi
|
||||
|
||||
log_pass "Projects OK ($project_count projects, '$TEST_PROJECT' present)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: POST /api/projects/refresh
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_projects_refresh() {
|
||||
log_test "POST /api/projects/refresh"
|
||||
|
||||
local response
|
||||
response=$(curl -sf -X POST "${SERVER_URL}/api/projects/refresh")
|
||||
|
||||
local ok
|
||||
ok=$(echo "$response" | jq -r '.ok')
|
||||
if [[ "$ok" != "true" ]]; then
|
||||
log_fail "Projects refresh returned ok=$ok"
|
||||
return
|
||||
fi
|
||||
|
||||
local project_count
|
||||
project_count=$(echo "$response" | jq '.projects | length')
|
||||
log_pass "Projects refresh OK ($project_count projects)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: Spawn without auth (should return 401)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_spawn_no_auth() {
|
||||
log_test "POST /api/spawn without auth (expect 401)"
|
||||
|
||||
local http_code body
|
||||
body=$(curl -s -o /dev/null -w '%{http_code}' -X POST "${SERVER_URL}/api/spawn" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"project":"amc","agent_type":"claude"}')
|
||||
|
||||
if [[ "$body" != "401" ]]; then
|
||||
log_fail "Expected HTTP 401, got $body"
|
||||
return
|
||||
fi
|
||||
|
||||
# Also verify the JSON error code
|
||||
local response
|
||||
response=$(curl -s -X POST "${SERVER_URL}/api/spawn" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"project":"amc","agent_type":"claude"}')
|
||||
|
||||
local code
|
||||
code=$(echo "$response" | jq -r '.code')
|
||||
if [[ "$code" != "UNAUTHORIZED" ]]; then
|
||||
log_fail "Expected code UNAUTHORIZED, got $code"
|
||||
return
|
||||
fi
|
||||
|
||||
log_pass "Correctly rejected unauthorized request (401/UNAUTHORIZED)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: Spawn with wrong token (should return 401)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_spawn_wrong_token() {
|
||||
log_test "POST /api/spawn with wrong token (expect 401)"
|
||||
|
||||
local response
|
||||
response=$(curl -s -X POST "${SERVER_URL}/api/spawn" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer totally-wrong-token" \
|
||||
-d '{"project":"amc","agent_type":"claude"}')
|
||||
|
||||
local code
|
||||
code=$(echo "$response" | jq -r '.code')
|
||||
if [[ "$code" != "UNAUTHORIZED" ]]; then
|
||||
log_fail "Expected UNAUTHORIZED, got $code"
|
||||
return
|
||||
fi
|
||||
|
||||
log_pass "Correctly rejected wrong token (UNAUTHORIZED)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: Spawn with malformed auth (no Bearer prefix)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_spawn_malformed_auth() {
|
||||
log_test "POST /api/spawn with malformed auth header"
|
||||
|
||||
local response
|
||||
response=$(curl -s -X POST "${SERVER_URL}/api/spawn" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Token ${AUTH_TOKEN}" \
|
||||
-d '{"project":"amc","agent_type":"claude"}')
|
||||
|
||||
local code
|
||||
code=$(echo "$response" | jq -r '.code')
|
||||
if [[ "$code" != "UNAUTHORIZED" ]]; then
|
||||
log_fail "Expected UNAUTHORIZED for malformed auth, got $code"
|
||||
return
|
||||
fi
|
||||
|
||||
log_pass "Correctly rejected malformed auth header"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: Spawn with invalid JSON body
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_spawn_invalid_json() {
|
||||
log_test "POST /api/spawn with invalid JSON"
|
||||
|
||||
local response
|
||||
response=$(curl -s -X POST "${SERVER_URL}/api/spawn" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
||||
-d 'not valid json!!!')
|
||||
|
||||
local ok
|
||||
ok=$(echo "$response" | jq -r '.ok')
|
||||
if [[ "$ok" != "false" ]]; then
|
||||
log_fail "Expected ok=false for invalid JSON, got ok=$ok"
|
||||
return
|
||||
fi
|
||||
|
||||
log_pass "Correctly rejected invalid JSON body"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: Spawn with path traversal (should return 400/INVALID_PROJECT)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_spawn_path_traversal() {
|
||||
log_test "POST /api/spawn with path traversal"
|
||||
|
||||
local response
|
||||
response=$(curl -s -X POST "${SERVER_URL}/api/spawn" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
||||
-d '{"project":"../etc/passwd","agent_type":"claude"}')
|
||||
|
||||
local code
|
||||
code=$(echo "$response" | jq -r '.code')
|
||||
if [[ "$code" != "INVALID_PROJECT" ]]; then
|
||||
log_fail "Expected INVALID_PROJECT for path traversal, got $code"
|
||||
return
|
||||
fi
|
||||
|
||||
log_pass "Correctly rejected path traversal (INVALID_PROJECT)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: Spawn with nonexistent project
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_spawn_nonexistent_project() {
|
||||
log_test "POST /api/spawn with nonexistent project"
|
||||
|
||||
local response
|
||||
response=$(curl -s -X POST "${SERVER_URL}/api/spawn" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
||||
-d '{"project":"this-project-does-not-exist-xyz","agent_type":"claude"}')
|
||||
|
||||
local code
|
||||
code=$(echo "$response" | jq -r '.code')
|
||||
if [[ "$code" != "PROJECT_NOT_FOUND" ]]; then
|
||||
log_fail "Expected PROJECT_NOT_FOUND, got $code"
|
||||
return
|
||||
fi
|
||||
|
||||
log_pass "Correctly rejected nonexistent project (PROJECT_NOT_FOUND)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: Spawn with invalid agent type
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_spawn_invalid_agent_type() {
|
||||
log_test "POST /api/spawn with invalid agent type"
|
||||
|
||||
local response
|
||||
response=$(curl -s -X POST "${SERVER_URL}/api/spawn" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
||||
-d "{\"project\":\"${TEST_PROJECT}\",\"agent_type\":\"gpt5\"}")
|
||||
|
||||
local code
|
||||
code=$(echo "$response" | jq -r '.code')
|
||||
if [[ "$code" != "INVALID_AGENT_TYPE" ]]; then
|
||||
log_fail "Expected INVALID_AGENT_TYPE, got $code"
|
||||
return
|
||||
fi
|
||||
|
||||
log_pass "Correctly rejected invalid agent type (INVALID_AGENT_TYPE)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: Spawn with missing project field
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_spawn_missing_project() {
|
||||
log_test "POST /api/spawn with missing project"
|
||||
|
||||
local response
|
||||
response=$(curl -s -X POST "${SERVER_URL}/api/spawn" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
||||
-d '{"agent_type":"claude"}')
|
||||
|
||||
local code
|
||||
code=$(echo "$response" | jq -r '.code')
|
||||
if [[ "$code" != "MISSING_PROJECT" ]]; then
|
||||
log_fail "Expected MISSING_PROJECT, got $code"
|
||||
return
|
||||
fi
|
||||
|
||||
log_pass "Correctly rejected missing project field (MISSING_PROJECT)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: Spawn with backslash in project name
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_spawn_backslash_project() {
|
||||
log_test "POST /api/spawn with backslash in project name"
|
||||
|
||||
local response
|
||||
response=$(curl -s -X POST "${SERVER_URL}/api/spawn" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
||||
-d '{"project":"foo\\bar","agent_type":"claude"}')
|
||||
|
||||
local code
|
||||
code=$(echo "$response" | jq -r '.code')
|
||||
if [[ "$code" != "INVALID_PROJECT" ]]; then
|
||||
log_fail "Expected INVALID_PROJECT for backslash, got $code"
|
||||
return
|
||||
fi
|
||||
|
||||
log_pass "Correctly rejected backslash in project name (INVALID_PROJECT)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: CORS preflight for /api/spawn
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_cors_preflight() {
|
||||
log_test "OPTIONS /api/spawn (CORS preflight)"
|
||||
|
||||
local http_code headers
|
||||
headers=$(curl -sI -X OPTIONS "${SERVER_URL}/api/spawn" 2>/dev/null)
|
||||
http_code=$(echo "$headers" | head -1 | grep -o '[0-9][0-9][0-9]' | head -1)
|
||||
|
||||
if [[ "$http_code" != "204" ]]; then
|
||||
log_fail "Expected HTTP 204 for OPTIONS, got $http_code"
|
||||
return
|
||||
fi
|
||||
|
||||
if ! echo "$headers" | grep -qi 'Access-Control-Allow-Methods'; then
|
||||
log_fail "Missing Access-Control-Allow-Methods header"
|
||||
return
|
||||
fi
|
||||
|
||||
if ! echo "$headers" | grep -qi 'Authorization'; then
|
||||
log_fail "Authorization not in Access-Control-Allow-Headers"
|
||||
return
|
||||
fi
|
||||
|
||||
log_pass "CORS preflight OK (204 with correct headers)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: Actual spawn (only with --spawn flag)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_spawn_valid() {
|
||||
if [[ "$SPAWN_MODE" != "true" ]]; then
|
||||
log_skip "Actual spawn test (pass --spawn to enable)"
|
||||
return
|
||||
fi
|
||||
|
||||
log_test "POST /api/spawn with valid project (LIVE)"
|
||||
|
||||
# Check Zellij session first
|
||||
if ! zellij list-sessions 2>/dev/null | grep -q '^infra'; then
|
||||
log_skip "Zellij session 'infra' not found - cannot test live spawn"
|
||||
return
|
||||
fi
|
||||
|
||||
# Count session files before
|
||||
local sessions_dir="$HOME/.local/share/amc/sessions"
|
||||
local count_before=0
|
||||
if [[ -d "$sessions_dir" ]]; then
|
||||
count_before=$(find "$sessions_dir" -name '*.json' -maxdepth 1 2>/dev/null | wc -l | tr -d ' ')
|
||||
fi
|
||||
|
||||
local response
|
||||
response=$(curl -s -X POST "${SERVER_URL}/api/spawn" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
||||
-d "{\"project\":\"${TEST_PROJECT}\",\"agent_type\":\"claude\"}")
|
||||
|
||||
local ok
|
||||
ok=$(echo "$response" | jq -r '.ok')
|
||||
if [[ "$ok" != "true" ]]; then
|
||||
local error_code
|
||||
error_code=$(echo "$response" | jq -r '.code // .error')
|
||||
log_fail "Spawn failed: $error_code"
|
||||
return
|
||||
fi
|
||||
|
||||
# Verify spawn_id is returned
|
||||
local spawn_id
|
||||
spawn_id=$(echo "$response" | jq -r '.spawn_id')
|
||||
if [[ -z "$spawn_id" || "$spawn_id" == "null" ]]; then
|
||||
log_fail "No spawn_id in response"
|
||||
return
|
||||
fi
|
||||
|
||||
# Track for cleanup
|
||||
SPAWNED_PANE_NAMES+=("claude-${TEST_PROJECT}")
|
||||
|
||||
# Verify session_file_found field
|
||||
local session_found
|
||||
session_found=$(echo "$response" | jq -r '.session_file_found')
|
||||
log_info "session_file_found=$session_found, spawn_id=${spawn_id:0:8}..."
|
||||
|
||||
log_pass "Spawn successful (spawn_id=${spawn_id:0:8}...)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: Rate limiting (only with --spawn flag)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_rate_limiting() {
|
||||
if [[ "$SPAWN_MODE" != "true" ]]; then
|
||||
log_skip "Rate limiting test (pass --spawn to enable)"
|
||||
return
|
||||
fi
|
||||
|
||||
log_test "Rate limiting on rapid spawn"
|
||||
|
||||
# Immediately try to spawn the same project again
|
||||
local response
|
||||
response=$(curl -s -X POST "${SERVER_URL}/api/spawn" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
||||
-d "{\"project\":\"${TEST_PROJECT}\",\"agent_type\":\"claude\"}")
|
||||
|
||||
local code
|
||||
code=$(echo "$response" | jq -r '.code')
|
||||
if [[ "$code" == "RATE_LIMITED" ]]; then
|
||||
log_pass "Rate limiting active (RATE_LIMITED returned)"
|
||||
else
|
||||
local ok
|
||||
ok=$(echo "$response" | jq -r '.ok')
|
||||
log_warn "Rate limiting not triggered (ok=$ok, code=$code) - cooldown may have expired"
|
||||
log_pass "Rate limiting test completed (non-deterministic)"
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test: Dashboard shows agent after spawn (only with --spawn flag)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
test_dashboard_shows_agent() {
|
||||
if [[ "$SPAWN_MODE" != "true" ]]; then
|
||||
log_skip "Dashboard agent visibility test (pass --spawn to enable)"
|
||||
return
|
||||
fi
|
||||
|
||||
log_test "Dashboard /api/state includes spawned agent"
|
||||
|
||||
# Give the session a moment to register
|
||||
sleep 2
|
||||
|
||||
local response
|
||||
response=$(curl -sf "${SERVER_URL}/api/state")
|
||||
|
||||
local session_count
|
||||
session_count=$(echo "$response" | jq '.sessions | length')
|
||||
|
||||
if [[ "$session_count" -gt 0 ]]; then
|
||||
log_pass "Dashboard shows $session_count session(s)"
|
||||
else
|
||||
log_warn "No sessions visible yet (agent may still be starting)"
|
||||
log_pass "Dashboard state endpoint responsive"
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Main
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
main() {
|
||||
echo "========================================="
|
||||
echo " AMC Spawn Workflow E2E Tests"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
if [[ "$SPAWN_MODE" == "true" ]]; then
|
||||
log_warn "SPAWN MODE: will create real Zellij panes"
|
||||
else
|
||||
log_info "Safe mode (no actual spawning). Pass --spawn to test live spawn."
|
||||
fi
|
||||
|
||||
preflight
|
||||
extract_auth_token
|
||||
|
||||
# Read-only endpoint tests
|
||||
test_health_endpoint
|
||||
test_projects_endpoint
|
||||
test_projects_refresh
|
||||
|
||||
# Auth / validation tests (no side effects)
|
||||
test_spawn_no_auth
|
||||
test_spawn_wrong_token
|
||||
test_spawn_malformed_auth
|
||||
test_spawn_invalid_json
|
||||
test_spawn_path_traversal
|
||||
test_spawn_nonexistent_project
|
||||
test_spawn_invalid_agent_type
|
||||
test_spawn_missing_project
|
||||
test_spawn_backslash_project
|
||||
|
||||
# CORS
|
||||
test_cors_preflight
|
||||
|
||||
# Live spawn tests (only with --spawn)
|
||||
test_spawn_valid
|
||||
test_rate_limiting
|
||||
test_dashboard_shows_agent
|
||||
|
||||
# Summary
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo " Results: ${PASSED} passed, ${FAILED} failed, ${SKIPPED} skipped"
|
||||
echo "========================================="
|
||||
|
||||
if [[ "$FAILED" -gt 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user