93 lines
3.7 KiB
Bash
Executable File
93 lines
3.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Phase A 门店后台 API 冒烟(需 backend :8080 + MySQL)
|
||
# 用法:
|
||
# export MYSQL_PASSWORD=... # 先启动 backend
|
||
# export BOSS_PHONE=13800000001
|
||
# export SMS_CODE=123456
|
||
# bash docs/qa-reports/scripts/admin-phase-a-api-smoke.sh
|
||
set -euo pipefail
|
||
|
||
BASE="${API_BASE:-http://127.0.0.1:8080/api}"
|
||
PHONE="${BOSS_PHONE:-}"
|
||
CODE="${SMS_CODE:-123456}"
|
||
|
||
red() { printf '\033[31m%s\033[0m\n' "$*"; }
|
||
green() { printf '\033[32m%s\033[0m\n' "$*"; }
|
||
step() { printf '\n== %s ==\n' "$*"; }
|
||
|
||
need() {
|
||
if [[ -z "${1:-}" ]]; then
|
||
red "缺少 $2"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
need "$PHONE" "BOSS_PHONE(老板/员工手机号)"
|
||
|
||
json_get() {
|
||
python3 -c 'import json,sys; d=json.load(sys.stdin); print(d'"$1"')'
|
||
}
|
||
|
||
step "0) 健康:公开门店列表"
|
||
curl -sf "$BASE/store/list" | python3 -c 'import json,sys; d=json.load(sys.stdin); assert d.get("code")==200; print("ok stores", len(d.get("data") or []))'
|
||
|
||
step "1) 登录"
|
||
LOGIN=$(curl -sf -X POST "$BASE/user/login" -H 'Content-Type: application/json' \
|
||
-d "{\"phone\":\"$PHONE\",\"code\":\"$CODE\"}")
|
||
echo "$LOGIN" | python3 -c 'import json,sys; d=json.load(sys.stdin); assert d.get("code")==200, d; print("role", d["data"]["user"]["role"])'
|
||
TOKEN=$(echo "$LOGIN" | json_get '["data"]["sessionToken"]')
|
||
ROLE=$(echo "$LOGIN" | json_get '["data"]["user"]["role"]')
|
||
AUTH="Authorization: Bearer $TOKEN"
|
||
|
||
if [[ "$ROLE" != "boss" && "$ROLE" != "staff" ]]; then
|
||
red "需要 boss/staff,当前 role=$ROLE"
|
||
exit 1
|
||
fi
|
||
|
||
auth_get() { curl -sf -H "$AUTH" "$@"; }
|
||
auth_post() { curl -sf -H "$AUTH" -H 'Content-Type: application/json' -X POST "$@"; }
|
||
|
||
step "2) customer 门禁:用 customer 应 403(若有)— 跳过;校验 admin store"
|
||
auth_get "$BASE/admin/store" | python3 -c 'import json,sys; d=json.load(sys.stdin); assert d.get("code")==200, d; assert "inviteCode" not in d["data"]; assert "onboardingStatus" in d["data"]; print("store", d["data"].get("name"), "onboarding", d["data"].get("onboardingStatus"))'
|
||
|
||
step "3) 预约列表(含 admin enrichment)"
|
||
auth_get "$BASE/appointment/list?page=1&pageSize=20" | python3 -c '
|
||
import json,sys
|
||
d=json.load(sys.stdin)
|
||
assert d.get("code")==200, d
|
||
rows=d.get("data") or []
|
||
print("appointments", len(rows))
|
||
if rows:
|
||
r=rows[0]
|
||
for k in ("hasReport","customerPhoneMasked","staffName"):
|
||
assert k in r, f"missing {k} in {r.keys()}"
|
||
print("enrichment ok")
|
||
'
|
||
|
||
step "4) 服务客户聚合"
|
||
auth_get "$BASE/admin/service-customers?page=1&pageSize=20" | python3 -c '
|
||
import json,sys
|
||
d=json.load(sys.stdin)
|
||
assert d.get("code")==200, d
|
||
data=d["data"]
|
||
assert "summary" in data and "list" in data
|
||
s=data["summary"]
|
||
for k in ("customerCount","pendingLeadCount","monthVisitCount"):
|
||
assert k in s
|
||
assert "totalBalance" not in s
|
||
print("customers", data.get("total"), "summary", s)
|
||
'
|
||
|
||
step "5) 线索 / 报告 / 排班"
|
||
TODAY=$(date +%F)
|
||
auth_get "$BASE/report/leads?status=pending" | python3 -c 'import json,sys; d=json.load(sys.stdin); assert d.get("code")==200, d; rows=d.get("data") or [];
|
||
assert all("wechatOpenid" not in r for r in rows); print("leads", len(rows))'
|
||
auth_get "$BASE/report/list?page=1&pageSize=20" | python3 -c 'import json,sys; d=json.load(sys.stdin); assert d.get("code")==200, d; rows=d.get("data") or [];
|
||
assert not rows or "updateTime" in rows[0]; print("reports", len(rows))'
|
||
auth_get "$BASE/schedule/day?date=$TODAY" | python3 -c 'import json,sys; d=json.load(sys.stdin); assert d.get("code")==200, d; print("schedule rows", len((d.get("data") or {}).get("rows") or []))'
|
||
|
||
step "6) 员工列表"
|
||
auth_get "$BASE/user/staff-list" | python3 -c 'import json,sys; d=json.load(sys.stdin); assert d.get("code")==200, d; print("staff", len(d.get("data") or []))'
|
||
|
||
green "API smoke PASS"
|