mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
220 lines
6.3 KiB
Bash
Executable File
220 lines
6.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# run-tests.sh — Run Sprout test suite
|
|
# =============================================================================
|
|
# Usage:
|
|
# ./scripts/run-tests.sh # run all tests (default)
|
|
# ./scripts/run-tests.sh unit # unit tests only (no infra needed)
|
|
# ./scripts/run-tests.sh integration # integration tests only
|
|
# ./scripts/run-tests.sh all # explicit all
|
|
# =============================================================================
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
MODE="${1:-all}"
|
|
TIMEOUT=60 # seconds to wait for services if starting them
|
|
DB_USER="${SPROUT_DB_USER:-sprout}"
|
|
DB_PASS="${SPROUT_DB_PASS:-sprout_dev}"
|
|
DB_NAME="${SPROUT_DB_NAME:-sprout}"
|
|
DOCKER_DB_HOST="${SPROUT_DOCKER_DB_HOST:-mysql}"
|
|
DOCKER_NETWORK="${SPROUT_DOCKER_NETWORK:-sprout-net}"
|
|
MYSQL_CLIENT_IMAGE="${SPROUT_DB_CLIENT_IMAGE:-mysql:8.0}"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
log() { echo -e "${BLUE}[run-tests]${NC} $*"; }
|
|
success(){ echo -e "${GREEN}[run-tests]${NC} ✅ $*"; }
|
|
warn() { echo -e "${YELLOW}[run-tests]${NC} ⚠️ $*"; }
|
|
error() { echo -e "${RED}[run-tests]${NC} ❌ $*" >&2; }
|
|
section(){ echo -e "\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"; echo -e "${CYAN} $*${NC}"; echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"; }
|
|
|
|
cd "${REPO_ROOT}"
|
|
|
|
run_mysql_in_container() {
|
|
docker run --rm -i --network "${DOCKER_NETWORK}" \
|
|
-e MYSQL_PWD="${DB_PASS}" \
|
|
"${MYSQL_CLIENT_IMAGE}" \
|
|
mysql -h"${DOCKER_DB_HOST}" -u"${DB_USER}" "${DB_NAME}" "$@"
|
|
}
|
|
|
|
# ---- Load .env if present ---------------------------------------------------
|
|
|
|
if [[ -f ".env" ]]; then
|
|
log "Loading .env..."
|
|
set -o allexport
|
|
# shellcheck disable=SC1091
|
|
source .env
|
|
set +o allexport
|
|
else
|
|
# Use defaults matching docker-compose.yml
|
|
export DATABASE_URL="mysql://sprout:sprout_dev@localhost:3306/sprout"
|
|
export REDIS_URL="redis://localhost:6379"
|
|
export TYPESENSE_API_KEY="sprout_dev_key"
|
|
export TYPESENSE_URL="http://localhost:8108"
|
|
fi
|
|
|
|
# ---- Track results ----------------------------------------------------------
|
|
|
|
declare -a PASSED=()
|
|
declare -a FAILED=()
|
|
|
|
run_test_step() {
|
|
local name="$1"
|
|
shift
|
|
log "Running: ${name}"
|
|
if "$@"; then
|
|
success "${name} passed"
|
|
PASSED+=("${name}")
|
|
else
|
|
error "${name} FAILED"
|
|
FAILED+=("${name}")
|
|
fi
|
|
}
|
|
|
|
# ---- Check / start infra (for integration tests) ----------------------------
|
|
|
|
services_healthy() {
|
|
local mysql_ok redis_ok
|
|
mysql_ok=$(docker inspect --format='{{.State.Health.Status}}' sprout-mysql 2>/dev/null || echo "not_found")
|
|
redis_ok=$(docker inspect --format='{{.State.Health.Status}}' sprout-redis 2>/dev/null || echo "not_found")
|
|
[[ "${mysql_ok}" == "healthy" && "${redis_ok}" == "healthy" ]]
|
|
}
|
|
|
|
ensure_services() {
|
|
if services_healthy; then
|
|
success "Services already healthy"
|
|
return 0
|
|
fi
|
|
|
|
warn "Services not running — starting them..."
|
|
docker compose up -d
|
|
|
|
local elapsed=0
|
|
local interval=3
|
|
while ! services_healthy; do
|
|
if [[ ${elapsed} -ge ${TIMEOUT} ]]; then
|
|
error "Timed out waiting for services (${TIMEOUT}s)"
|
|
return 1
|
|
fi
|
|
sleep "${interval}"
|
|
elapsed=$((elapsed + interval))
|
|
echo -n "."
|
|
done
|
|
echo ""
|
|
success "Services healthy"
|
|
|
|
# Ensure migrations are current
|
|
ensure_migrations
|
|
}
|
|
|
|
ensure_migrations() {
|
|
log "Ensuring migrations are current..."
|
|
local migration_dir="${REPO_ROOT}/migrations"
|
|
|
|
if [[ ! -d "${migration_dir}" ]]; then
|
|
warn "No migrations directory. Skipping."
|
|
return 0
|
|
fi
|
|
|
|
if command -v sqlx &>/dev/null; then
|
|
DATABASE_URL="${DATABASE_URL}" sqlx migrate run --source "${migration_dir}" 2>/dev/null \
|
|
&& success "Migrations current" \
|
|
|| warn "sqlx migrate run failed — DB may be out of date"
|
|
else
|
|
# Fallback: apply all SQL files (idempotent if schema uses IF NOT EXISTS)
|
|
shopt -s nullglob
|
|
local sql_files=("${migration_dir}"/*.sql)
|
|
shopt -u nullglob
|
|
for sql_file in "${sql_files[@]}"; do
|
|
run_mysql_in_container < "${sql_file}" &>/dev/null || true
|
|
done
|
|
success "Migrations applied (mysql fallback)"
|
|
fi
|
|
}
|
|
|
|
# ---- Unit tests (no infra needed) -------------------------------------------
|
|
|
|
run_unit_tests() {
|
|
section "Unit Tests (no infra required)"
|
|
|
|
run_test_step "sprout-core tests" \
|
|
cargo test -p sprout-core --lib -- --nocapture
|
|
|
|
run_test_step "sprout-auth unit tests" \
|
|
cargo test -p sprout-auth --lib -- --nocapture
|
|
}
|
|
|
|
# ---- DB / integration tests (infra required) --------------------------------
|
|
|
|
run_integration_tests() {
|
|
section "Integration Tests (requires running services)"
|
|
|
|
ensure_services
|
|
|
|
run_test_step "sprout-db tests" \
|
|
cargo test -p sprout-db -- --nocapture
|
|
|
|
run_test_step "sprout-auth integration tests" \
|
|
cargo test -p sprout-auth --test '*' -- --nocapture 2>/dev/null || \
|
|
run_test_step "sprout-auth (no integration tests found)" true
|
|
|
|
run_test_step "workspace integration tests" \
|
|
cargo test --test '*' -- --nocapture 2>/dev/null || \
|
|
run_test_step "workspace integration tests (none found)" true
|
|
}
|
|
|
|
# ---- Main -------------------------------------------------------------------
|
|
|
|
START_TIME=$(date +%s)
|
|
|
|
case "${MODE}" in
|
|
unit)
|
|
run_unit_tests
|
|
;;
|
|
integration)
|
|
run_integration_tests
|
|
;;
|
|
all|*)
|
|
run_unit_tests
|
|
run_integration_tests
|
|
;;
|
|
esac
|
|
|
|
END_TIME=$(date +%s)
|
|
ELAPSED=$((END_TIME - START_TIME))
|
|
|
|
# ---- Summary ----------------------------------------------------------------
|
|
|
|
section "Test Summary"
|
|
echo ""
|
|
echo -e " Duration: ${ELAPSED}s"
|
|
echo ""
|
|
|
|
if [[ ${#PASSED[@]} -gt 0 ]]; then
|
|
echo -e " ${GREEN}Passed (${#PASSED[@]}):${NC}"
|
|
for t in "${PASSED[@]}"; do
|
|
echo -e " ${GREEN}✅${NC} ${t}"
|
|
done
|
|
fi
|
|
|
|
if [[ ${#FAILED[@]} -gt 0 ]]; then
|
|
echo ""
|
|
echo -e " ${RED}Failed (${#FAILED[@]}):${NC}"
|
|
for t in "${FAILED[@]}"; do
|
|
echo -e " ${RED}❌${NC} ${t}"
|
|
done
|
|
echo ""
|
|
exit 1
|
|
fi
|
|
|
|
echo ""
|
|
success "All tests passed! 🎉"
|
|
exit 0
|