api development
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2025-08-08 21:58:36 +09:00
parent d58302c2c8
commit cc87dcc0fa
157 changed files with 14629 additions and 7 deletions

208
scripts/e2e.sh Executable file
View File

@@ -0,0 +1,208 @@
#!/usr/bin/env bash
set -Eeuo pipefail
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"
GW_HEALTH_PATH="${GW_HEALTH_PATH:-/auth/health}"
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" >&2; exit 1; }; }
require curl; require python3
log(){ echo -e "${C}[$(date +%H:%M:%S)]${NC} $*" >&2; }
ok(){ echo -e "${G}${NC} $*" >&2; }
warn(){ echo -e "${Y}${NC} $*" >&2; }
fail(){ echo -e "${R}${NC} $*" >&2; exit 1; }
json_get(){ python3 - "$1" "$2" <<'PY'
import sys, json, os
f,p=sys.argv[1],sys.argv[2]
if not os.path.exists(f): print(""); sys.exit(0)
try: data=json.load(open(f))
except: print(""); sys.exit(0)
cur=data
for k in p.split('.'):
if isinstance(cur,list):
try:k=int(k)
except: print(""); sys.exit(0)
cur=cur[k] if 0<=k<len(cur) else None
elif isinstance(cur,dict):
cur=cur.get(k)
else: cur=None
if cur is None: break
print("" if cur is None else cur)
PY
}
jwt_get(){ # jwt_get <token> <claim>
python3 - "$1" "$2" <<'PY'
import sys, json, base64
t, claim = sys.argv[1], sys.argv[2]
try:
b = t.split('.')[1]
b += '=' * (-len(b) % 4)
payload = json.loads(base64.urlsafe_b64decode(b).decode())
print(payload.get(claim,""))
except Exception:
print("")
PY
}
http_req(){
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 --connect-timeout 5 --max-time 10 -X "$METHOD" "$URL" -o "$RESP" -w "%{http_code}")
[[ -n "$TOKEN" ]] && args+=(-H "Authorization: Bearer $TOKEN")
[[ -n "$BODY" ]] && args+=(-H "Content-Type: application/json" -d "$BODY")
local CODE; CODE="$(curl "${args[@]}" || true)"
[[ -e "$RESP" ]] || : > "$RESP"
echo "$CODE|$RESP"
}
expect_code(){ [[ "$2" == *"|${1}|"* || "$2" == "${1}|"* || "$2" == *"|${1}" || "$2" == "${1}" ]]; }
wait_http(){
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_http "$1" "$2" "200" "${3:-60}"; }
login_or_register(){ # echo "<user_id>|<access_token>"
local EMAIL="$1" PASS="$2" FULL="$3" ROLE="$4"
local BODY TOK TOKCODE TOKRESP ACCESS USER_ID
# 1) пытаемся логиниться
BODY=$(printf '{"email":"%s","password":"%s"}' "$EMAIL" "$PASS")
TOK="$(http_req POST "$AUTH/v1/token" "" "$BODY")"; TOKCODE="${TOK%%|*}"; TOKRESP="${TOK##*|}"
if expect_code "$TOKCODE" "200"; then
ACCESS="$(json_get "$TOKRESP" "access_token")"
USER_ID="$(jwt_get "$ACCESS" sub)"
[[ -n "$ACCESS" && -n "$USER_ID" ]] || fail "Login parse failed for $EMAIL"
ok "Login ok for $EMAIL"
echo "${USER_ID}|${ACCESS}"; return 0
fi
warn "Login failed for $EMAIL ($TOKCODE) → will register"
# 2) регистрируем
BODY=$(printf '{"email":"%s","password":"%s","full_name":"%s","role":"%s"}' "$EMAIL" "$PASS" "$FULL" "$ROLE")
local REG RESPCODE RESP; REG="$(http_req POST "$AUTH/v1/register" "" "$BODY")"
RESPCODE="${REG%%|*}"; RESP="${REG##*|}"
if expect_code "$RESPCODE" "201|200"; then
ok "Registered $EMAIL"
else
local MSG; MSG="$(json_get "$RESP" "detail")"
if [[ "$RESPCODE" == "400" && "$MSG" == "Email already in use" ]]; then
warn "Already exists: $EMAIL"
else
warn "Register response ($RESPCODE): $(cat "$RESP" 2>/dev/null || true)"
fi
fi
# 3) снова логин
TOK="$(http_req POST "$AUTH/v1/token" "" "$BODY")"; TOKCODE="${TOK%%|*}"; TOKRESP="${TOK##*|}"
expect_code "$TOKCODE" "200" || fail "Token failed (${TOKCODE}): $(cat "$TOKRESP")"
ACCESS="$(json_get "$TOKRESP" "access_token")"
USER_ID="$(jwt_get "$ACCESS" sub)"
[[ -n "$ACCESS" && -n "$USER_ID" ]] || fail "Login parse failed after register for $EMAIL"
echo "${USER_ID}|${ACCESS}"
}
ensure_profile(){ # <token> <gender> <city> <langs_csv> <interests_csv>
local TOKEN="$1" G="$2" CITY="$3" LANGS="$4" INTRS="$5"
[[ -n "$TOKEN" ]] || fail "Empty token in ensure_profile"
local ME MECODE MERESP; ME="$(http_req GET "$PROFILES/v1/profiles/me" "$TOKEN")"
MECODE="${ME%%|*}"; MERESP="${ME##*|}"
if [[ "$MECODE" == "200" ]]; then ok "Profile exists"; return 0
elif [[ "$MECODE" != "404" ]]; then warn "Unexpected /profiles/me $MECODE: $(cat "$MERESP")"; fi
local lj ij; IFS=',' read -r -a _l <<< "$LANGS"; lj="$(printf '%s\n' "${_l[@]}"|sed 's/^/"/;s/$/"/'|paste -sd, -)"
IFS=',' read -r -a _i <<< "$INTRS"; ij="$(printf '%s\n' "${_i[@]}"|sed 's/^/"/;s/$/"/'|paste -sd, -)"
local BODY; BODY=$(cat <<JSON
{"gender":"$G","city":"$CITY","languages":[${lj}],"interests":[${ij}]}
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"
}
main(){
echo -e "${B}=== E2E smoke test start ===${NC}" >&2
echo "BASE_URL: $BASE_URL" >&2; echo >&2
wait_health "gateway" "${BASE_URL}${GW_HEALTH_PATH}"
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"
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 "Admin: ${ADMIN_EMAIL}"
IFS='|' read -r ADMIN_ID ADMIN_ACCESS < <(login_or_register "$ADMIN_EMAIL" "$PASS" "Admin" "ADMIN"); ok "Admin id: $ADMIN_ID"
log "Alice: ${ALICE_EMAIL}"
IFS='|' read -r ALICE_ID ALICE_ACCESS < <(login_or_register "$ALICE_EMAIL" "$PASS" "Alice" "CLIENT"); ok "Alice id: $ALICE_ID"
log "Bob: ${BOB_EMAIL}"
IFS='|' read -r BOB_ID BOB_ACCESS < <(login_or_register "$BOB_EMAIL" "$PASS" "Bob" "CLIENT"); ok "Bob id: $BOB_ID"
log "Profiles"
ensure_profile "$ADMIN_ACCESS" "other" "Moscow" "ru,en" "admin,ops"
ensure_profile "$ALICE_ACCESS" "female" "Moscow" "ru,en" "music,travel"
ensure_profile "$BOB_ACCESS" "male" "Moscow" "ru" "sports,reading"
log "Match 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: $PAIR_ID"
log "Chat"
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: $ROOM_ID"
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: $MSG_ID"
log "Payments"
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: $INV_ID"
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 not paid"
ok "Invoice status: $STATUS"
{
echo "=== E2E summary ==="
echo "Admin: ${ADMIN_EMAIL} (id: ${ADMIN_ID})"
echo "Alice: ${ALICE_EMAIL} (id: ${ALICE_ID})"
echo "Bob: ${BOB_EMAIL} (id: ${BOB_ID})"
echo "Pair: ${PAIR_ID}"
echo "Room: ${ROOM_ID} Message: ${MSG_ID}"
echo "Invoice:${INV_ID} Status: ${STATUS}"
} >&2
ok "E2E smoke test finished successfully."
}
main "$@"