chore(scripts): 提交分解弹窗E2E验证辅助脚本(cdp_driver + review)
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
"""CDP e2e 续:预算管理页 → 年度分解弹窗实测"""
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
import urllib.request
|
||||
import websocket
|
||||
|
||||
CDP_HTTP = "http://127.0.0.1:9222"
|
||||
|
||||
|
||||
def http_get(path):
|
||||
with urllib.request.urlopen(CDP_HTTP + path, timeout=5) as r:
|
||||
return json.loads(r.read().decode())
|
||||
|
||||
|
||||
class CDP:
|
||||
def __init__(self, ws_url):
|
||||
self.ws = websocket.create_connection(ws_url, timeout=30)
|
||||
self.msg_id = 0
|
||||
|
||||
def call(self, method, params=None):
|
||||
self.msg_id += 1
|
||||
mid = self.msg_id
|
||||
self.ws.send(json.dumps({"id": mid, "method": method, "params": params or {}}))
|
||||
while True:
|
||||
resp = json.loads(self.ws.recv())
|
||||
if resp.get("id") == mid:
|
||||
if "error" in resp:
|
||||
raise RuntimeError(f"{method}: {resp['error']}")
|
||||
return resp.get("result", {})
|
||||
if resp.get("method") in ("Page.loadEventFired", "Page.frameStoppedLoading"):
|
||||
pass
|
||||
|
||||
def eval(self, expr):
|
||||
r = self.call("Runtime.evaluate", {"expression": expr, "returnByValue": True, "awaitPromise": True})
|
||||
if r.get("exceptionDetails"):
|
||||
return "EXC: " + json.dumps(r["exceptionDetails"], ensure_ascii=False)[:200]
|
||||
return r.get("result", {}).get("value")
|
||||
|
||||
def close(self):
|
||||
try:
|
||||
self.ws.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def new_page(url):
|
||||
ver = http_get("/json/version")
|
||||
bws = CDP(ver["webSocketDebuggerUrl"])
|
||||
t = bws.call("Target.createTarget", {"url": url})
|
||||
tid = t["targetId"]
|
||||
bws.close()
|
||||
time.sleep(2)
|
||||
for p in http_get("/json"):
|
||||
if p["id"] == tid:
|
||||
return tid, p["webSocketDebuggerUrl"]
|
||||
return tid, None
|
||||
|
||||
|
||||
def main():
|
||||
tid, ws = new_page("https://cma.sxbh.ltd/")
|
||||
if not ws:
|
||||
print("FAIL: no ws")
|
||||
sys.exit(1)
|
||||
c = CDP(ws)
|
||||
c.call("Page.enable")
|
||||
c.call("Runtime.enable")
|
||||
time.sleep(6)
|
||||
|
||||
# 点击侧边栏"预算管理"
|
||||
r = c.eval("""(() => {
|
||||
const els = Array.from(document.querySelectorAll('a, li, span, div'));
|
||||
const target = els.find(e => e.innerText && e.innerText.trim() === '预算管理' && e.offsetParent !== null);
|
||||
if (!target) return 'NO_MENU';
|
||||
target.click();
|
||||
return 'CLICKED';
|
||||
})()""")
|
||||
print("MENU_CLICK:", r)
|
||||
time.sleep(4)
|
||||
print("URL_NOW:", c.eval("location.href"))
|
||||
body = c.eval("document.body ? document.body.innerText.slice(0,400) : ''")
|
||||
print("BODY:", body.replace("\n", " | ")[:400])
|
||||
|
||||
# 检查是否有 预算管理 页面关键元素:年份选择 + 年度分解按钮
|
||||
btns = c.eval("""Array.from(document.querySelectorAll('button')).map((b,idx)=>({idx, text:(b.innerText||'').trim().slice(0,20)})).filter(x=>x.text)""")
|
||||
print("BUTTONS:", json.dumps(btns, ensure_ascii=False))
|
||||
|
||||
c.close()
|
||||
print("TARGET:", tid)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user