You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
9.0 KiB
174 lines
9.0 KiB
|
2 weeks ago
|
import sys
|
||
|
|
import io
|
||
|
|
import requests
|
||
|
|
|
||
|
|
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
|
||
|
|
|
||
|
|
TOKEN = sys.argv[1]
|
||
|
|
BASE = "http://localhost:8080"
|
||
|
|
H = {"Authorization": f"Bearer {TOKEN}"}
|
||
|
|
OPP_ID = 999999999001
|
||
|
|
results = []
|
||
|
|
|
||
|
|
|
||
|
|
def check(name, resp, expect_code=0):
|
||
|
|
try:
|
||
|
|
d = resp.json()
|
||
|
|
ok = d.get("code") == expect_code
|
||
|
|
results.append((name, "OK" if ok else "FAIL", d.get("code"), str(d.get("message", ""))[:80]))
|
||
|
|
except Exception:
|
||
|
|
results.append((name, "FAIL", "parse_err", resp.text[:80]))
|
||
|
|
|
||
|
|
|
||
|
|
def check_page(name, resp):
|
||
|
|
try:
|
||
|
|
d = resp.json()
|
||
|
|
ok = d.get("code") == 0
|
||
|
|
data = d.get("data", {}) or {}
|
||
|
|
has_content = "content" in data
|
||
|
|
has_total = "total" in data
|
||
|
|
status = "OK" if (ok and has_content and has_total) else "FAIL"
|
||
|
|
results.append((name, status, d.get("code"), f"content:{has_content} total:{has_total}"))
|
||
|
|
except Exception:
|
||
|
|
results.append((name, "FAIL", "parse_err", resp.text[:80]))
|
||
|
|
|
||
|
|
|
||
|
|
# ===== 列表 =====
|
||
|
|
check_page("POST /api/opportunity/page",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/page", headers=H, data={"pageNum": 1, "pageSize": 5}))
|
||
|
|
check_page("POST /api/opportunity/page?viewType=pool",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/page", headers=H, data={"pageNum": 1, "pageSize": 5, "viewType": "pool"}))
|
||
|
|
|
||
|
|
# ===== 新建 =====
|
||
|
|
r = requests.post(f"{BASE}/api/opportunity", headers=H, data={"opportunityName": "端到端回归", "oppSource": "opp_source_02"})
|
||
|
|
check("POST /api/opportunity 新建", r)
|
||
|
|
|
||
|
|
# ===== 详情 + 编辑 =====
|
||
|
|
check("GET /api/opportunity/detail",
|
||
|
|
requests.get(f"{BASE}/api/opportunity/detail", headers=H, params={"id": OPP_ID}))
|
||
|
|
check("POST /api/opportunity/edit",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/edit", headers=H,
|
||
|
|
data={"id": OPP_ID, "oppName": "端到端编辑验证", "remark": "e2e"}))
|
||
|
|
|
||
|
|
# ===== 状态机 =====
|
||
|
|
# 新建初始状态为"推进中",按实际出边顺序测:
|
||
|
|
# 推进中 -> pause -> resume -> handover -> release-pool -> claim -> release-pool -> assign -> close -> reopen
|
||
|
|
r_sm = requests.post(f"{BASE}/api/opportunity", headers=H,
|
||
|
|
data={"opportunityName": "sm-e2e", "oppSource": "opp_source_02"})
|
||
|
|
sm = r_sm.json().get("data") if r_sm.json().get("code") == 0 else None
|
||
|
|
if sm:
|
||
|
|
check("POST /pause (推进中->暂缓中)",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/pause", headers=H, data={"id": sm, "pauseReason": "e2e"}))
|
||
|
|
check("POST /resume (暂缓中->推进中)",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/resume", headers=H, data={"id": sm}))
|
||
|
|
check("POST /handover (推进中自环)",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/handover", headers=H,
|
||
|
|
data={"id": sm, "expectedOwnerUserId": "739564171091247104",
|
||
|
|
"newOwnerUserId": "739564171091247104"}))
|
||
|
|
check("POST /release-pool (推进中->待领取)",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/release-pool", headers=H, data={"id": sm, "poolReason": "e2e"}))
|
||
|
|
check("POST /claim (待领取->推进中)",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/claim", headers=H, data={"id": sm}))
|
||
|
|
# release-pool 再次入池,然后 assign
|
||
|
|
requests.post(f"{BASE}/api/opportunity/release-pool", headers=H, data={"id": sm, "poolReason": "e2e-assign"})
|
||
|
|
check("POST /assign (待领取->推进中)",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/assign", headers=H,
|
||
|
|
data={"id": sm, "userId": "739564171091247104"}))
|
||
|
|
check("POST /close (推进中->已关闭)",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/close", headers=H, data={"id": sm, "closeReason": "e2e"}))
|
||
|
|
check("POST /reopen (已关闭->推进中)",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/reopen", headers=H, data={"id": sm, "reopenReason": "e2e"}))
|
||
|
|
else:
|
||
|
|
for n in ["pause", "resume", "handover", "release-pool", "claim", "assign", "close", "reopen"]:
|
||
|
|
results.append((f"POST /{n}", "SKIP", "skip", "新建失败跳过"))
|
||
|
|
|
||
|
|
# ===== 方案卡 / 阶段 =====
|
||
|
|
check("GET /api/opportunity/scheme-card/list",
|
||
|
|
requests.get(f"{BASE}/api/opportunity/scheme-card/list", headers=H, params={"oppId": OPP_ID}))
|
||
|
|
check("GET /api/opportunity/stage/progress",
|
||
|
|
requests.get(f"{BASE}/api/opportunity/stage/progress", headers=H, params={"oppId": OPP_ID}))
|
||
|
|
|
||
|
|
# ===== 子域 =====
|
||
|
|
check("GET /customer/list",
|
||
|
|
requests.get(f"{BASE}/api/opportunity/customer/list", headers=H, params={"oppId": OPP_ID}))
|
||
|
|
check_page("POST /follow/page",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/follow/page", headers=H,
|
||
|
|
data={"oppId": OPP_ID, "pageNum": 1, "pageSize": 5}))
|
||
|
|
r3 = requests.post(f"{BASE}/api/opportunity/follow/add", headers=H, data={
|
||
|
|
"oppId": OPP_ID, "followContent": "e2e跟进", "followTime": "2026-08-27 16:00:00",
|
||
|
|
"followWay": "PHONE", "customerId": 1})
|
||
|
|
check("POST /follow/add", r3)
|
||
|
|
fid = r3.json().get("data") if r3.json().get("code") == 0 else None
|
||
|
|
|
||
|
|
detail2 = requests.get(f"{BASE}/api/opportunity/detail", headers=H, params={"id": OPP_ID}).json()
|
||
|
|
lvft = detail2.get("data", {}).get("lastValidFollowTime", "")
|
||
|
|
lvft_ok = "2026-08-27" in str(lvft) if lvft else False
|
||
|
|
results.append(("last_valid_follow_time刷新", "OK" if lvft_ok else "FAIL", 0, f"={lvft}"))
|
||
|
|
|
||
|
|
if fid:
|
||
|
|
check("POST /follow/delete",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/follow/delete", headers=H, params={"id": fid}))
|
||
|
|
log_resp = requests.post(f"{BASE}/api/opportunity/oplog/page", headers=H,
|
||
|
|
data={"oppId": OPP_ID, "pageNum": 1, "pageSize": 10}).json()
|
||
|
|
logs = log_resp.get("data", {}).get("content", [])
|
||
|
|
has_log = any(l.get("opKind") == "ROW_DELETE" for l in logs)
|
||
|
|
results.append(("deleteFollow写ROW_DELETE oplog", "OK" if has_log else "FAIL", 0, f"logs={len(logs)}"))
|
||
|
|
|
||
|
|
check_page("POST /site-survey/page",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/site-survey/page", headers=H,
|
||
|
|
data={"oppId": OPP_ID, "pageNum": 1, "pageSize": 5}))
|
||
|
|
check("GET /attachment/list",
|
||
|
|
requests.get(f"{BASE}/api/opportunity/attachment/list", headers=H, params={"oppId": OPP_ID}))
|
||
|
|
check("GET /team/list",
|
||
|
|
requests.get(f"{BASE}/api/opportunity/team/list", headers=H, params={"oppId": OPP_ID}))
|
||
|
|
check_page("POST /oplog/page",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/oplog/page", headers=H,
|
||
|
|
data={"oppId": OPP_ID, "pageNum": 1, "pageSize": 5}))
|
||
|
|
|
||
|
|
# ===== 协作 =====
|
||
|
|
check("POST /focus",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/focus", headers=H, params={"oppId": OPP_ID}))
|
||
|
|
check("POST /unfocus",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/unfocus", headers=H, params={"oppId": OPP_ID}))
|
||
|
|
check("POST /view-touch",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/view-touch", headers=H, params={"oppId": OPP_ID}))
|
||
|
|
check("POST /board/stage-summary",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/board/stage-summary", headers=H))
|
||
|
|
check("POST /board/cards",
|
||
|
|
requests.post(f"{BASE}/api/opportunity/board/cards", headers=H, data={"stageId": 0, "offset": 0, "limit": 5}))
|
||
|
|
|
||
|
|
# ===== 规则族 =====
|
||
|
|
check_page("POST /api/rule/opp-stage-template/page",
|
||
|
|
requests.post(f"{BASE}/api/rule/opp-stage-template/page", headers=H, data={"pageNum": 1, "pageSize": 5}))
|
||
|
|
check_page("POST /api/rule/opp-scheme-template/page",
|
||
|
|
requests.post(f"{BASE}/api/rule/opp-scheme-template/page", headers=H, data={"pageNum": 1, "pageSize": 5}))
|
||
|
|
check_page("POST /api/rule/opp-pool-rule/page",
|
||
|
|
requests.post(f"{BASE}/api/rule/opp-pool-rule/page", headers=H, data={"pageNum": 1, "pageSize": 5}))
|
||
|
|
check("GET /api/rule/opp-stage-template/versions",
|
||
|
|
requests.get(f"{BASE}/api/rule/opp-stage-template/versions", headers=H, params={"id": 747831302652166144}))
|
||
|
|
check("GET /api/rule/opp-scheme-template/versions",
|
||
|
|
requests.get(f"{BASE}/api/rule/opp-scheme-template/versions", headers=H, params={"id": 747831301075107840}))
|
||
|
|
check("GET /api/rule/opp-pool-rule/versions",
|
||
|
|
requests.get(f"{BASE}/api/rule/opp-pool-rule/versions", headers=H, params={"id": 999}))
|
||
|
|
|
||
|
|
# ===== 附件上限校验 =====
|
||
|
|
for i in range(10):
|
||
|
|
requests.post(f"{BASE}/api/opportunity/attachment/add", headers=H,
|
||
|
|
data={"oppId": OPP_ID, "fileId": 50000 + i, "bizType": "FOLLOW_UP", "bizId": 555})
|
||
|
|
over = requests.post(f"{BASE}/api/opportunity/attachment/add", headers=H,
|
||
|
|
data={"oppId": OPP_ID, "fileId": 59999, "bizType": "FOLLOW_UP", "bizId": 555})
|
||
|
|
d2 = over.json()
|
||
|
|
results.append(("附件10个上限校验", "OK" if d2.get("code") != 0 else "FAIL",
|
||
|
|
d2.get("code"), d2.get("message", "")[:50]))
|
||
|
|
|
||
|
|
# ===== 输出 =====
|
||
|
|
passed = sum(1 for _, s, _, _ in results if s == "OK")
|
||
|
|
failed = sum(1 for _, s, _, _ in results if s == "FAIL")
|
||
|
|
skipped = sum(1 for _, s, _, _ in results if s == "SKIP")
|
||
|
|
print(f"\n{'=' * 65}")
|
||
|
|
print(f"端到端回归:OK={passed} FAIL={failed} SKIP={skipped} 共{len(results)}条")
|
||
|
|
print(f"{'=' * 65}")
|
||
|
|
for name, status, code, msg in results:
|
||
|
|
icon = {"OK": "[OK] ", "FAIL": "[FAIL]", "SKIP": "[SKIP]"}[status]
|
||
|
|
print(f"{icon} {name} | code:{code} | {msg}")
|