Payfrit: - Tab API contract tests (bash + python) — all 13 endpoints - Param validation, response time, cross-env parity checks Grubflip: - API endpoint test stubs — menu, restaurant, order, auth - Ready to activate as Mike deploys endpoints Shared: - test_helpers.sh + test_helpers.py — HTTP helpers, pass/fail/skip, JSON output mode - Master test runner (scripts/run-all.sh) - Infrastructure health checker (disk, RAM, services, SSL certs) Test data: - Grubflip seed SQL (QA test restaurants, menus, orders) - Payfrit tab seeder script All Payfrit tab tests confirmed passing against dev + prod.
101 lines
3.1 KiB
Bash
101 lines
3.1 KiB
Bash
#!/usr/bin/env bash
|
|
# ============================================================
|
|
# test_helpers.sh — Shared test utilities
|
|
# Source this in any test script: source shared/lib/test_helpers.sh
|
|
# ============================================================
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
PASS_COUNT=0
|
|
FAIL_COUNT=0
|
|
SKIP_COUNT=0
|
|
TEST_RESULTS=()
|
|
JSON_MODE=false
|
|
|
|
# Parse --json flag
|
|
for arg in "$@"; do
|
|
[ "$arg" = "--json" ] && JSON_MODE=true
|
|
done
|
|
|
|
pass() {
|
|
local msg="$1"
|
|
((PASS_COUNT++))
|
|
TEST_RESULTS+=("{\"status\":\"pass\",\"test\":\"$msg\"}")
|
|
$JSON_MODE || echo -e " ${GREEN}✅${NC} $msg"
|
|
}
|
|
|
|
fail() {
|
|
local msg="$1"
|
|
local detail="${2:-}"
|
|
((FAIL_COUNT++))
|
|
TEST_RESULTS+=("{\"status\":\"fail\",\"test\":\"$msg\",\"detail\":\"$detail\"}")
|
|
$JSON_MODE || echo -e " ${RED}❌${NC} $msg${detail:+ — $detail}"
|
|
}
|
|
|
|
skip() {
|
|
local msg="$1"
|
|
local reason="${2:-}"
|
|
((SKIP_COUNT++))
|
|
TEST_RESULTS+=("{\"status\":\"skip\",\"test\":\"$msg\",\"reason\":\"$reason\"}")
|
|
$JSON_MODE || echo -e " ${YELLOW}⏭️${NC} $msg${reason:+ — $reason}"
|
|
}
|
|
|
|
section() {
|
|
$JSON_MODE || echo -e "\n${CYAN}━━━ $1 ━━━${NC}"
|
|
}
|
|
|
|
# HTTP helper: returns "status_code|body|time_ms"
|
|
http_get() {
|
|
local url="$1"
|
|
local tmpfile=$(mktemp)
|
|
local http_code time_total body
|
|
http_code=$(curl -sk -o "$tmpfile" -w "%{http_code}" "$url" 2>/dev/null)
|
|
time_total=$(curl -sk -o /dev/null -w "%{time_total}" "$url" 2>/dev/null)
|
|
body=$(cat "$tmpfile")
|
|
rm -f "$tmpfile"
|
|
local ms=$(echo "$time_total * 1000" | bc 2>/dev/null | cut -d'.' -f1)
|
|
echo "${http_code}|${body}|${ms:-0}"
|
|
}
|
|
|
|
http_post() {
|
|
local url="$1"
|
|
local data="${2:-{}}"
|
|
local tmpfile=$(mktemp)
|
|
local http_code
|
|
http_code=$(curl -sk -X POST -o "$tmpfile" -w "%{http_code}" \
|
|
-H "Content-Type: application/json" -d "$data" "$url" 2>/dev/null)
|
|
local body=$(cat "$tmpfile")
|
|
rm -f "$tmpfile"
|
|
echo "${http_code}|${body}"
|
|
}
|
|
|
|
# JSON field extractor (requires python3)
|
|
json_field() {
|
|
local json="$1"
|
|
local field="$2"
|
|
echo "$json" | python3 -c "import sys,json; print(json.load(sys.stdin).get('$field',''))" 2>/dev/null
|
|
}
|
|
|
|
is_valid_json() {
|
|
echo "$1" | python3 -c "import sys,json; json.load(sys.stdin)" 2>/dev/null
|
|
}
|
|
|
|
# Print summary and exit with appropriate code
|
|
test_summary() {
|
|
local total=$((PASS_COUNT + FAIL_COUNT + SKIP_COUNT))
|
|
|
|
if $JSON_MODE; then
|
|
echo "{\"total\":$total,\"pass\":$PASS_COUNT,\"fail\":$FAIL_COUNT,\"skip\":$SKIP_COUNT,\"results\":[$(IFS=,; echo "${TEST_RESULTS[*]}")]}"
|
|
else
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo -e " TOTAL: $total | ${GREEN}PASS: $PASS_COUNT${NC} | ${RED}FAIL: $FAIL_COUNT${NC} | ${YELLOW}SKIP: $SKIP_COUNT${NC}"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
fi
|
|
|
|
[ "$FAIL_COUNT" -eq 0 ] && return 0 || return 1
|
|
}
|