#!/usr/bin/env python3 """CDP E2E Test v2: 使用真实JWT Token进行前端端到端测试""" import json, time, base64, urllib.request REAL_TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODE5Njg1MDAsImlhdCI6MTc3OTM3NjUwMCwidXNlcl9pZCI6ImFkbWluIn0.dHdo1NciPDC8-yR0P-CHv2x0hsh3-G2sHOr9E8VBvws' print('=== CDP E2E Test v2 ===') # Open page req = urllib.request.Request('http://127.0.0.1:9225/json/new?url=http://localhost:5199/', method='PUT') resp = urllib.request.urlopen(req, timeout=10) page = json.loads(resp.read()) ws_url = page['webSocketDebuggerUrl'] page_id = page['id'] print(f'Page: {page_id}') from websocket import create_connection ws = create_connection(ws_url, timeout=10) def cdp(method, params=None, msg_id=1): ws.send(json.dumps({'id': msg_id, 'method': method, 'params': params or {}})) def recv_all(timeout=3): ws.settimeout(timeout) msgs = [] try: while True: msgs.append(ws.recv()) except: pass return msgs def find_result(msgs, msg_id): for m in msgs: try: d = json.loads(m) if d.get('id') == msg_id: return d.get('result', {}) except: pass return None # Enable domains cdp('Page.enable', {}, 1) cdp('Runtime.enable', {}, 2) cdp('Network.enable', {}, 3) cdp('Log.enable', {}, 4) recv_all(1) # Inject real token print('\n--- Inject Token ---') cdp('Runtime.evaluate', { 'expression': 'localStorage.setItem("token", "%s"); localStorage.setItem("user_id", "admin"); "OK"' % REAL_TOKEN, 'returnByValue': True }, 50) recv_all(2) # Reload print('\n--- Reload Page ---') cdp('Page.navigate', {'url': 'http://localhost:5199/'}, 60) time.sleep(4) all_msgs = recv_all(5) # Analyze print('\n--- Console Analysis ---') errors = [] for m in all_msgs: try: d = json.loads(m) except: continue method = d.get('method', '') params = d.get('params', {}) if method == 'Log.entryAdded': entry = params.get('entry', {}) lvl = entry.get('level', 'log') text = str(entry.get('text', ''))[:200] if lvl == 'error': errors.append(text) print(f' [{lvl}] {text}') elif method == 'Runtime.consoleAPICalled': args = params.get('args', []) lvl = params.get('type', 'log') texts = [str(a.get('value', '') or a.get('description', ''))[:150] for a in args] combined = ' '.join(texts) if lvl == 'error': errors.append(combined) print(f' [{lvl}] {combined}') elif method == 'Runtime.exceptionThrown': exc = params.get('exceptionDetails', {}) text = exc.get('text', '') errors.append(text) print(f' [EXCEPTION] {text}') # Network print('\n--- Network API Calls ---') for m in all_msgs: try: d = json.loads(m) except: continue method = d.get('method', '') params = d.get('params', {}) if method == 'Network.responseReceived': resp = params.get('response', {}) url = resp.get('url', '') status = resp.get('status', 0) if '/api/' in url: print(f' [{status}] {url[-80:]}') elif method == 'Network.loadingFailed': print(f' [FAIL] {params.get("errorText","?")}') # Runtime checks print('\n--- Runtime State ---') checks = [ 'localStorage.getItem("token") ? "TOKEN_OK:" + localStorage.getItem("token").slice(0,20) + "..." : "NO_TOKEN"', 'localStorage.getItem("user_id") || "none"', 'document.title', 'document.querySelectorAll("[class*=\\"message\\"]").length + " message elements"', '(function(){try{var s=document.querySelector("#root");return s?s.children.length+" root children":"no root"}catch(e){return e.message}})()', ] for idx, expr in enumerate(checks): cdp('Runtime.evaluate', {'expression': expr, 'returnByValue': True}, 200 + idx) recv_msgs = recv_all(2) r = find_result(recv_msgs, 200 + idx) if r: val = r.get('result', {}).get('value', '?') print(f' {val}') # Screenshot print('\n--- Screenshot ---') cdp('Page.captureScreenshot', {'format': 'png'}, 300) recv_msgs = recv_all(5) r = find_result(recv_msgs, 300) if r and r.get('data'): img = base64.b64decode(r['data']) with open('/tmp/cyrene_e2e_v2.png', 'wb') as f: f.write(img) print(f' Saved: {len(img)} bytes') if errors: print(f'\n=== {len(errors)} ERRORS ===') for e in errors: print(f' - {e[:200]}') else: print('\n=== ZERO ERRORS ===') ws.close() print('[DONE]')