#!/bin/bash # Smoke test for the full trading-bot Docker Compose stack. # # Usage: # ./scripts/smoke_test.sh # # Prerequisites: # - Docker Compose stack must be running (docker compose up -d) # # This script: # 1. Waits for services to become healthy # 2. Hits GET /health -> expects 200 # 3. Hits GET /api/portfolio -> expects 401 (unauthenticated) # 4. Hits GET /api/strategies -> expects 401 (unauthenticated) # 5. Checks docker compose ps shows all services running # 6. Exits 0 on success, 1 on failure set -euo pipefail # Configuration API_BASE="${API_BASE:-http://localhost:8000}" DASHBOARD_BASE="${DASHBOARD_BASE:-http://localhost:3000}" MAX_RETRIES="${MAX_RETRIES:-30}" RETRY_INTERVAL="${RETRY_INTERVAL:-2}" PASS=0 FAIL=0 # --------------------------------------------------------------------------- # Helper functions # --------------------------------------------------------------------------- log() { echo "[smoke-test] $*" } pass() { log "PASS: $*" PASS=$((PASS + 1)) } fail() { log "FAIL: $*" FAIL=$((FAIL + 1)) } wait_for_endpoint() { local url="$1" local expected_code="$2" local description="$3" local attempt=0 while [ "$attempt" -lt "$MAX_RETRIES" ]; do attempt=$((attempt + 1)) status_code=$(curl -s -o /dev/null -w "%{http_code}" "$url" 2>/dev/null || echo "000") if [ "$status_code" = "$expected_code" ]; then return 0 fi log "Waiting for $description ($url) ... attempt $attempt/$MAX_RETRIES (got $status_code, want $expected_code)" sleep "$RETRY_INTERVAL" done return 1 } check_endpoint() { local url="$1" local expected_code="$2" local description="$3" status_code=$(curl -s -o /dev/null -w "%{http_code}" "$url" 2>/dev/null || echo "000") if [ "$status_code" = "$expected_code" ]; then pass "$description -> $status_code" else fail "$description -> expected $expected_code, got $status_code" fi } # --------------------------------------------------------------------------- # 1. Wait for the API gateway health endpoint # --------------------------------------------------------------------------- log "Waiting for API gateway to be healthy ..." if wait_for_endpoint "$API_BASE/health" "200" "API health"; then pass "API gateway is healthy" else fail "API gateway did not become healthy within timeout" log "Aborting — cannot run further checks without a healthy API" exit 1 fi # --------------------------------------------------------------------------- # 2. Health check # --------------------------------------------------------------------------- check_endpoint "$API_BASE/health" "200" "GET /health" # --------------------------------------------------------------------------- # 3. Unauthenticated trading endpoints should return 401/403 # --------------------------------------------------------------------------- check_endpoint "$API_BASE/api/portfolio" "401" "GET /api/portfolio (no auth)" check_endpoint "$API_BASE/api/strategies" "401" "GET /api/strategies (no auth)" # --------------------------------------------------------------------------- # 4. Dashboard responds # --------------------------------------------------------------------------- log "Checking dashboard ..." if wait_for_endpoint "$DASHBOARD_BASE/" "200" "Dashboard"; then pass "Dashboard is serving" else fail "Dashboard did not respond" fi # --------------------------------------------------------------------------- # 5. Docker Compose services status # --------------------------------------------------------------------------- log "Checking docker compose service status ..." if command -v docker &>/dev/null; then running_count=$(docker compose ps --format json 2>/dev/null | grep -c '"running"' || echo "0") if [ "$running_count" -gt 0 ]; then pass "docker compose shows $running_count running services" else fail "No running services found in docker compose ps" fi else log "SKIP: docker command not available" fi # --------------------------------------------------------------------------- # Summary # --------------------------------------------------------------------------- echo "" log "================================" log "Results: $PASS passed, $FAIL failed" log "================================" if [ "$FAIL" -gt 0 ]; then exit 1 fi exit 0