| |
| """ |
| Teste WebRTC automatizado com Playwright headless |
| """ |
|
|
| import asyncio |
| from playwright.async_api import async_playwright |
| import sys |
|
|
| SERVER_URL = "http://62.107.25.198:47898" |
|
|
| async def test_webrtc(): |
| print("="*60) |
| print("Teste WebRTC com Playwright (Headless)") |
| print("="*60) |
|
|
| async with async_playwright() as p: |
| |
| print("\n[1/6] Iniciando browser headless...") |
| browser = await p.chromium.launch( |
| headless=True, |
| args=[ |
| '--use-fake-ui-for-media-stream', |
| '--use-fake-device-for-media-stream', |
| '--no-sandbox' |
| ] |
| ) |
|
|
| context = await browser.new_context( |
| permissions=['camera', 'microphone'] |
| ) |
|
|
| page = await context.new_page() |
|
|
| |
| console_logs = [] |
| page_errors = [] |
|
|
| page.on("console", lambda msg: console_logs.append(f"[{msg.type}] {msg.text}")) |
| page.on("pageerror", lambda exc: page_errors.append(f"ERROR: {exc}")) |
|
|
| |
| network_logs = [] |
|
|
| def handle_response(response): |
| if '/offer' in response.url: |
| network_logs.append(f"POST /offer → Status: {response.status}") |
| if response.status != 200: |
| network_logs.append(f" Error: {response.status_text}") |
|
|
| page.on("response", handle_response) |
|
|
| |
| print(f"[2/6] Navegando para {SERVER_URL}...") |
| try: |
| await page.goto(SERVER_URL, timeout=10000) |
| print("✓ Página carregada") |
| except Exception as e: |
| print(f"✗ Erro ao carregar página: {e}") |
| await browser.close() |
| return False |
|
|
| |
| print("[3/6] Verificando elementos...") |
| try: |
| await page.wait_for_selector('#btnConnect', timeout=5000) |
| print("✓ Botão 'Conectar' encontrado") |
| except Exception as e: |
| print(f"✗ Erro: {e}") |
| await browser.close() |
| return False |
|
|
| |
| print("[4/6] Configurando captura de eventos ICE...") |
| await page.evaluate(""" |
| window.iceInfo = { |
| candidates: [], |
| states: [], |
| connectionStates: [] |
| }; |
| |
| // Interceptar console.log de ICE candidates |
| const originalLog = console.log; |
| console.log = function(...args) { |
| if (args[0] === 'ICE Candidate:') { |
| window.iceInfo.candidates.push(args[1]); |
| } else if (args[0] === 'ICE State:') { |
| window.iceInfo.states.push(args[1]); |
| } else if (args[0] === 'Estado WebRTC:') { |
| window.iceInfo.connectionStates.push(args[1]); |
| } |
| originalLog.apply(console, args); |
| }; |
| """) |
|
|
| |
| print("[5/6] Clicando em 'Conectar'...") |
| await page.click('#btnConnect') |
|
|
| |
| print("[6/6] Aguardando conexão (15s)...") |
| await asyncio.sleep(15) |
|
|
| |
| ice_info = await page.evaluate("window.iceInfo") |
|
|
| |
| webrtc_state = await page.evaluate(""" |
| (() => { |
| const pc = window.pc; |
| if (!pc) return null; |
| return { |
| connectionState: pc.connectionState, |
| iceConnectionState: pc.iceConnectionState, |
| iceGatheringState: pc.iceGatheringState, |
| signalingState: pc.signalingState |
| }; |
| })() |
| """) |
|
|
| |
| print("\n" + "="*60) |
| print("RESULTADOS") |
| print("="*60) |
|
|
| if webrtc_state: |
| print(f"\nEstados WebRTC:") |
| print(f" Connection: {webrtc_state['connectionState']}") |
| print(f" ICE Connection: {webrtc_state['iceConnectionState']}") |
| print(f" ICE Gathering: {webrtc_state['iceGatheringState']}") |
| print(f" Signaling: {webrtc_state['signalingState']}") |
| else: |
| print("\n✗ Peer connection não foi criada!") |
|
|
| |
| candidates = ice_info.get('candidates', []) |
| print(f"\nCandidatos ICE: {len(candidates)}") |
|
|
| candidate_types = {} |
| for c in candidates: |
| ctype = c.get('type', 'unknown') |
| candidate_types[ctype] = candidate_types.get(ctype, 0) + 1 |
|
|
| for ctype, count in candidate_types.items(): |
| icon = "✓" if ctype == "relay" else "•" |
| print(f" {icon} {ctype}: {count}") |
|
|
| |
| print("\n" + "="*60) |
| print("DIAGNÓSTICO") |
| print("="*60) |
|
|
| success = False |
|
|
| if not webrtc_state: |
| print("\n✗ FALHA: Peer connection não foi criada") |
| print(" → Verificar JavaScript do frontend") |
|
|
| elif webrtc_state['connectionState'] == 'connected': |
| print("\n✓ SUCESSO: WebRTC conectado!") |
| success = True |
|
|
| elif webrtc_state['iceConnectionState'] == 'failed': |
| print("\n✗ FALHA: ICE connection failed") |
|
|
| if len(candidates) == 0: |
| print(" → Problema: Nenhum candidato ICE gerado") |
| print(" → Solução: Verificar configuração STUN/TURN") |
|
|
| elif 'relay' not in candidate_types: |
| print(" → Problema: Nenhum candidato TURN (relay)") |
| print(" → Solução: Servidores TURN não estão funcionando") |
| print(" → Tentar outros servidores TURN") |
|
|
| else: |
| print(" → Problema: Candidatos gerados mas não conectam") |
| print(" → Solução: Problema de firewall/NAT no servidor") |
| print(" → Verificar port mapping UDP no vast.ai") |
|
|
| elif webrtc_state['connectionState'] == 'connecting': |
| print("\n⚠ TIMEOUT: Conexão travada em 'connecting'") |
| print(" → Problema: ICE negotiation timeout") |
| print(" → Causa provável: Port mapping UDP não configurado") |
| print(" → Solução: Expor portas UDP no vast.ai ou usar ngrok") |
|
|
| |
| if page_errors: |
| print("\n" + "="*60) |
| print("ERROS JAVASCRIPT") |
| print("="*60) |
| for err in page_errors: |
| print(err) |
|
|
| |
| if network_logs: |
| print("\n" + "="*60) |
| print("LOGS DE REDE") |
| print("="*60) |
| for log in network_logs: |
| print(log) |
|
|
| |
| if console_logs: |
| print("\n" + "="*60) |
| print("LOGS DO CONSOLE (últimos 20)") |
| print("="*60) |
| for log in console_logs[-20:]: |
| print(log) |
|
|
| await browser.close() |
| return success |
|
|
| async def main(): |
| success = await test_webrtc() |
| sys.exit(0 if success else 1) |
|
|
| if __name__ == "__main__": |
| asyncio.run(main()) |
|
|