Files
marriage/.history/scripts/e2e_20250808205905.sh
Andrey K. Choi cc87dcc0fa
Some checks failed
continuous-integration/drone/push Build is failing
api development
2025-08-08 21:58:36 +09:00

285 lines
9.9 KiB
Bash

#!/usr/bin/env bash
set -Eeuo pipefail
# ------------------------------------------------------------
# E2E smoke test for the matchmaking microservices (via gateway)
# ------------------------------------------------------------
BASE_URL="${BASE_URL:-http://localhost:8080}"
AUTH="$BASE_URL/auth"
PROFILES="$BASE_URL/profiles"
MATCH="$BASE_URL/match"
CHAT="$BASE_URL/chat"
PAYMENTS="$BASE_URL/payments"
# Где проверять доступность gateway (по умолчанию /auth/health).
GW_HEALTH_PATH="${GW_HEALTH_PATH:-/auth/health}"
# Colors
NC='\033[0m'; B='\033[1m'; G='\033[0;32m'; Y='\033[0;33m'; R='\033[0;31m'; C='\033[0;36m'
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT
require() {
command -v "$1" >/dev/null 2>&1 || { echo -e "${R}ERROR:${NC} '$1' is required"; exit 1; }
}
require curl
require python3
log() { echo -e "${C}[$(date +%H:%M:%S)]${NC} $*"; }
ok() { echo -e "${G}${NC} $*"; }
warn(){ echo -e "${Y}${NC} $*"; }
fail(){ echo -e "${R}${NC} $*"; exit 1; }
json_get() {
# json_get <file> <path>
python3 - "$1" "$2" <<'PY'
import sys, json
f, path = sys.argv[1], sys.argv[2]
with open(f, 'r') as fh:
try:
data = json.load(fh)
except Exception:
print(""); sys.exit(0)
cur = data
for key in path.split('.'):
if isinstance(cur, list):
try:
key = int(key)
except:
print(""); sys.exit(0)
cur = cur[key] if 0 <= key < len(cur) else None
elif isinstance(cur, dict):
cur = cur.get(key)
else:
cur = None
if cur is None:
break
print("" if cur is None else cur)
PY
}
http_req() {
# http_req <METHOD> <URL> [<TOKEN>] [<JSON_BODY>] -> prints HTTP code; body to $RESP
local METHOD="$1"; shift
local URL="$1"; shift
local TOKEN="${1:-}"; shift || true
local BODY="${1:-}"; shift || true
local RESP="${TMP_DIR}/resp_$(date +%s%N).json"
local args=(-sS --max-time 10 -X "$METHOD" "$URL" -o "$RESP" -w "%{http_code}")
if [[ -n "$TOKEN" ]]; then args+=(-H "Authorization: Bearer $TOKEN"); fi
if [[ -n "$BODY" ]]; then args+=(-H "Content-Type: application/json" -d "$BODY"); fi
local CODE
CODE="$(curl "${args[@]}" || true)"
echo "$CODE|$RESP"
}
expect_code() {
# expect_code "<actual>" "<allowed1>|<allowed2>|..."
local ACT="$1"; local ALLOWED="$2"
if [[ "$ALLOWED" == *"|${ACT}|"* || "$ALLOWED" == "${ACT}|"* || "$ALLOWED" == *"|${ACT}" || "$ALLOWED" == "${ACT}" ]]; then
return 0
fi
return 1
}
wait_http() {
# wait_http <NAME> <URL> [<allowed_codes>|default 200] [<tries>|60]
local NAME="$1" URL="$2" ALLOWED="${3:-200}" TRIES="${4:-60}"
log "Waiting ${NAME} at ${URL} (allowed: ${ALLOWED})"
for ((i=1; i<=TRIES; i++)); do
local CODE
CODE="$(curl -s -o /dev/null -w "%{http_code}" "$URL" || true)"
if expect_code "$CODE" "$ALLOWED"; then
ok "${NAME} is ready (${CODE})"
return 0
fi
sleep 1
done
fail "${NAME} not ready in time: ${URL}"
}
wait_health() {
# wait_health <NAME> <URL> [<tries>|60] (expects 200)
wait_http "$1" "$2" "200" "${3:-60}"
}
register_or_login() {
# register_or_login <email> <password> <full_name> <role> -> echoes "<user_id>|<access_token>"
local EMAIL="$1" PASS="$2" FULL="$3" ROLE="$4"
local BODY REG RESPCODE RESP
BODY=$(printf '{"email":"%s","password":"%s","full_name":"%s","role":"%s"}' "$EMAIL" "$PASS" "$FULL" "$ROLE")
REG="$(http_req POST "$AUTH/v1/register" "" "$BODY")"
RESPCODE="${REG%%|*}"; RESP="${REG##*|}"
if expect_code "$RESPCODE" "201|200"; then
ok "Registered user ${EMAIL}"
else
local MSG
MSG="$(json_get "$RESP" "detail")"
if [[ "$RESPCODE" == "400" && "$MSG" == "Email already in use" ]]; then
warn "User ${EMAIL} already exists, will login"
else
warn "Register response ($RESPCODE): $(cat "$RESP" 2>/dev/null || true)"
fi
fi
local TOK TOKCODE TOKRESP
BODY=$(printf '{"email":"%s","password":"%s"}' "$EMAIL" "$PASS")
TOK="$(http_req POST "$AUTH/v1/token" "" "$BODY")"
TOKCODE="${TOK%%|*}"; TOKRESP="${TOK##*|}"
expect_code "$TOKCODE" "200" || fail "Token failed (${TOKCODE}): $(cat "$TOKRESP")"
local ACCESS
ACCESS="$(json_get "$TOKRESP" "access_token")"
[[ -n "$ACCESS" ]] || fail "Empty access token for ${EMAIL}"
local ME MECODE MERESP UID
ME="$(http_req GET "$AUTH/v1/me" "$ACCESS")"
MECODE="${ME%%|*}"; MERESP="${ME##*|}"
expect_code "$MECODE" "200" || fail "/me failed for ${EMAIL} (${MECODE}): $(cat "$MERESP")"
UID="$(json_get "$MERESP" "id")"
[[ -n "$UID" ]] || fail "Failed to parse user id for ${EMAIL}"
echo "${UID}|${ACCESS}"
}
ensure_profile() {
# ensure_profile <access_token> <gender> <city> <langs_csv> <interests_csv>
local TOKEN="$1" G="$2" CITY="$3" LANGS_CSV="$4" INTERESTS_CSV="$5"
local ME MECODE MERESP
ME="$(http_req GET "$PROFILES/v1/profiles/me" "$TOKEN")"
MECODE="${ME%%|*}"; MERESP="${ME##*|}"
if [[ "$MECODE" == "200" ]]; then
ok "Profile already exists"
echo "$MERESP" > "${TMP_DIR}/last_profile.json"
return 0
elif [[ "$MECODE" != "404" ]]; then
warn "Unexpected /profiles/me code ${MECODE}: $(cat "$MERESP")"
fi
IFS=',' read -r -a langs <<< "$LANGS_CSV"
IFS=',' read -r -a intrs <<< "$INTERESTS_CSV"
local langs_json intrs_json
langs_json="$(printf '%s\n' "${langs[@]}" | sed 's/^/"/;s/$/"/' | paste -sd, -)"
intrs_json="$(printf '%s\n' "${intrs[@]}" | sed 's/^/"/;s/$/"/' | paste -sd, -)"
local BODY
BODY=$(cat <<JSON
{"gender":"$G","city":"$CITY","languages":[${langs_json}],"interests":[${intrs_json}]}
JSON
)
local CR CRCODE CRRESP
CR="$(http_req POST "$PROFILES/v1/profiles" "$TOKEN" "$BODY")"
CRCODE="${CR%%|*}"; CRRESP="${CR##*|}"
expect_code "$CRCODE" "201|200" || fail "Create profile failed (${CRCODE}): $(cat "$CRRESP")"
ok "Profile created: $(json_get "$CRRESP" "id")"
echo "$CRRESP" > "${TMP_DIR}/last_profile.json"
}
main() {
echo -e "${B}=== E2E smoke test start ===${NC}"
echo "BASE_URL: $BASE_URL"
echo
# 0) Wait for gateway by checking proxied /auth/health (root / может отдавать 404/403)
wait_health "gateway" "${BASE_URL}${GW_HEALTH_PATH}"
# 1) Wait for services (через gateway)
wait_health "auth" "$AUTH/health"
wait_health "profiles" "$PROFILES/health"
wait_health "match" "$MATCH/health"
wait_health "chat" "$CHAT/health"
wait_health "payments" "$PAYMENTS/health"
# 2) Register/login users
TS="$(date +%s)"
ADMIN_EMAIL="${ADMIN_EMAIL:-admin+$TS@agency.dev}"
ALICE_EMAIL="${ALICE_EMAIL:-alice+$TS@agency.dev}"
BOB_EMAIL="${BOB_EMAIL:-bob+$TS@agency.dev}"
PASS="${PASS:-secret123}"
log "Register/login admin: ${ADMIN_EMAIL}"
IFS='|' read -r ADMIN_ID ADMIN_ACCESS < <(register_or_login "$ADMIN_EMAIL" "$PASS" "Admin" "ADMIN")
ok "Admin id: $ADMIN_ID"
log "Register/login Alice: ${ALICE_EMAIL}"
IFS='|' read -r ALICE_ID ALICE_ACCESS < <(register_or_login "$ALICE_EMAIL" "$PASS" "Alice" "CLIENT")
ok "Alice id: $ALICE_ID"
log "Register/login Bob: ${BOB_EMAIL}"
IFS='|' read -r BOB_ID BOB_ACCESS < <(register_or_login "$BOB_EMAIL" "$PASS" "Bob" "CLIENT")
ok "Bob id: $BOB_ID"
# 3) Ensure profiles
log "Ensure profile for Admin"
ensure_profile "$ADMIN_ACCESS" "other" "Moscow" "ru,en" "admin,ops"
log "Ensure profile for Alice"
ensure_profile "$ALICE_ACCESS" "female" "Moscow" "ru,en" "music,travel"
log "Ensure profile for Bob"
ensure_profile "$BOB_ACCESS" "male" "Moscow" "ru" "sports,reading"
# 4) Create match pair
log "Create match pair (Alice ↔ Bob)"
BODY=$(printf '{"user_id_a":"%s","user_id_b":"%s","score":%.2f,"notes":"e2e smoke"}' "$ALICE_ID" "$BOB_ID" 0.87)
PAIR="$(http_req POST "$MATCH/v1/pairs" "$ADMIN_ACCESS" "$BODY")"
PCODE="${PAIR%%|*}"; PRESP="${PAIR##*|}"
expect_code "$PCODE" "201|200" || fail "Create pair failed (${PCODE}): $(cat "$PRESP")"
PAIR_ID="$(json_get "$PRESP" "id")"
ok "Pair created: $PAIR_ID"
# 5) Create chat room and send a message
log "Create chat room (Admin + Alice + Bob)"
BODY=$(printf '{"title":"Alice & Bob","participants":["%s","%s"]}' "$ALICE_ID" "$BOB_ID")
ROOM="$(http_req POST "$CHAT/v1/rooms" "$ADMIN_ACCESS" "$BODY")"
RCODE="${ROOM%%|*}"; RRESP="${ROOM##*|}"
expect_code "$RCODE" "201|200" || fail "Create room failed (${RCODE}): $(cat "$RRESP")"
ROOM_ID="$(json_get "$RRESP" "id")"
ok "Room created: $ROOM_ID"
log "Send message to room"
BODY='{"content":"Hello from admin (e2e)"}'
MSG="$(http_req POST "$CHAT/v1/rooms/$ROOM_ID/messages" "$ADMIN_ACCESS" "$BODY")"
MCODE="${MSG%%|*}"; MRESP="${MSG##*|}"
expect_code "$MCODE" "201|200" || fail "Send message failed (${MCODE}): $(cat "$MRESP")"
MSG_ID="$(json_get "$MRESP" "id")"
ok "Message sent: $MSG_ID"
# 6) Create invoice for Alice and mark paid
log "Create invoice for Alice"
BODY=$(printf '{"client_id":"%s","amount":199.00,"currency":"USD","description":"Consultation (e2e)"}' "$ALICE_ID")
INV="$(http_req POST "$PAYMENTS/v1/invoices" "$ADMIN_ACCESS" "$BODY")"
INVCODE="${INV%%|*}"; INVRESP="${INV##*|}"
expect_code "$INVCODE" "201|200" || fail "Create invoice failed (${INVCODE}): $(cat "$INVRESP")"
INV_ID="$(json_get "$INVRESP" "id")"
ok "Invoice created: $INV_ID"
log "Mark invoice paid"
PAID="$(http_req POST "$PAYMENTS/v1/invoices/$INV_ID/mark-paid" "$ADMIN_ACCESS")"
PDCODE="${PAID%%|*}"; PDRESP="${PAID##*|}"
expect_code "$PDCODE" "200" || fail "Mark paid failed (${PDCODE}): $(cat "$PDRESP")"
STATUS="$(json_get "$PDRESP" "status")"
[[ "$STATUS" == "paid" ]] || fail "Invoice status not 'paid' (got '$STATUS')"
ok "Invoice marked paid"
echo
echo -e "${B}=== E2E summary ===${NC}"
echo -e "Admin: ${G}${ADMIN_EMAIL}${NC} (id: ${ADMIN_ID})"
echo -e "Alice: ${G}${ALICE_EMAIL}${NC} (id: ${ALICE_ID})"
echo -e "Bob: ${G}${BOB_EMAIL}${NC} (id: ${BOB_ID})"
echo -e "Pair: ${C}${PAIR_ID}${NC}"
echo -e "Room: ${C}${ROOM_ID}${NC} Message: ${C}${MSG_ID}${NC}"
echo -e "Invoice:${C}${INV_ID}${NC} Status: ${G}${STATUS}${NC}"
echo
ok "E2E smoke test finished successfully."
}
main "$@"