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}")