chore(scripts): 提交分解弹窗E2E验证辅助脚本(cdp_driver + review)

This commit is contained in:
Hermes CI Fix
2026-08-31 17:05:21 +08:00
parent c45dc554ed
commit 2241a89fd1
2 changed files with 172 additions and 0 deletions
@@ -0,0 +1,79 @@
"""budget-decompose-dialog-fix 独立复核:API 级实测 auto-decompose 全链路"""
import json
import sys
import urllib.request
BASE = "http://127.0.0.1:8010"
def post(path, body, token=None, method="POST"):
req = urllib.request.Request(
BASE + path,
data=json.dumps(body).encode("utf-8"),
method=method,
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {token}" if token else "",
},
)
try:
with urllib.request.urlopen(req, timeout=30) as resp:
return resp.status, json.loads(resp.read().decode("utf-8"))
except urllib.error.HTTPError as e:
try:
return e.code, json.loads(e.read().decode("utf-8"))
except Exception:
return e.code, {"detail": e.read().decode("utf-8", "ignore")}
def main():
# 1. 登录(账套模式 entity_id=1
status, login = post("/api/cma/auth/login", {"username": "admin", "password": "admin123", "entity_id": 1})
token = login.get("token") or login.get("access_token")
if status != 200 or not token:
print("FAIL login:", status, login)
sys.exit(1)
print("PASS 登录成功, token 前缀:", token[:12], "...")
# 2. 调用 auto-decomposeequal 均分)
status, r = post("/api/cma/budget/auto-decompose", {"year": 2026, "method": "equal", "version": "v1.0"}, token)
print("auto-decompose status:", status)
if status != 200:
print(" detail:", r.get("detail", r))
print("FAIL auto-decompose 非200(可能该年无年度预算数据)")
sys.exit(2)
print(" message:", r.get("message"))
results = r.get("results") or []
print(" created:", r.get("created"), " results数:", len(results))
for res in results[:5]:
print(" -", res.get("kpi_code"), res.get("kpi_name"),
"annual=", res.get("annual_budget"), "method=", res.get("method"),
"monthly_count=", len(res.get("monthly") or []))
if not results:
print("FAIL results 为空")
sys.exit(3)
# 3. 验证每条结果字段完整(前端表格依赖)
required = ["kpi_code", "kpi_name", "annual_budget", "method", "monthly"]
for res in results:
missing = [k for k in required if k not in res]
if missing:
print("FAIL 结果缺字段:", missing, res)
sys.exit(4)
if not res.get("monthly"):
print("FAIL monthly 为空:", res.get("kpi_code"))
sys.exit(5)
print("PASS 所有结果字段完整(kpi_code/kpi_name/annual_budget/method/monthly")
# 4. 幂等抽查:再调一次,结果一致
status2, r2 = post("/api/cma/budget/auto-decompose", {"year": 2026, "method": "equal", "version": "v1.0"}, token)
snap1 = {res["kpi_id"]: tuple(res.get("monthly") or []) for res in results}
snap2 = {res["kpi_id"]: tuple(res.get("monthly") or []) for res in (r2.get("results") or [])}
print("PASS 二次调用幂等一致" if snap1 == snap2 else "WARN 二次调用结果不同(非幂等)")
print("\nRESULT: API 全链路通过")
if __name__ == "__main__":
main()