8742cb25be
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
147 lines
4.2 KiB
Python
147 lines
4.2 KiB
Python
"""Tests para cdp_eval.
|
|
|
|
Como cdp_eval requiere un Chrome vivo con remote debugging, se mockean las dos
|
|
fronteras de I/O:
|
|
- urllib.request.urlopen -> devuelve un /json con 2 targets (uno whatsapp).
|
|
- websocket.create_connection -> un fake que responde al id==1 con un value.
|
|
"""
|
|
|
|
import io
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
|
|
|
import urllib.request
|
|
|
|
import websocket
|
|
|
|
from browser.cdp_eval import cdp_eval
|
|
|
|
|
|
# --- Fakes -----------------------------------------------------------------
|
|
|
|
def _targets_json():
|
|
"""Dos targets de tipo page: uno de Google, otro de WhatsApp Web."""
|
|
return [
|
|
{
|
|
"type": "page",
|
|
"url": "https://www.google.com/",
|
|
"webSocketDebuggerUrl": "ws://127.0.0.1:9222/devtools/page/GOOGLE",
|
|
},
|
|
{
|
|
"type": "page",
|
|
"url": "https://web.whatsapp.com/",
|
|
"webSocketDebuggerUrl": "ws://127.0.0.1:9222/devtools/page/WA",
|
|
},
|
|
]
|
|
|
|
|
|
class _FakeHTTPResponse:
|
|
"""Context manager que imita la respuesta de urlopen con .read()."""
|
|
|
|
def __init__(self, payload):
|
|
self._buf = io.BytesIO(json.dumps(payload).encode())
|
|
|
|
def read(self):
|
|
return self._buf.read()
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, *exc):
|
|
return False
|
|
|
|
|
|
class _FakeWS:
|
|
"""WebSocket fake: guarda el ws_url usado y responde al evaluate con value.
|
|
|
|
Antes de la respuesta con id==1, emite un evento intermedio (sin id) para
|
|
verificar que cdp_eval drena eventos hasta encontrar su respuesta.
|
|
"""
|
|
|
|
last_url = None
|
|
|
|
def __init__(self, url, value):
|
|
_FakeWS.last_url = url
|
|
self._value = value
|
|
self._queue = []
|
|
|
|
def send(self, raw):
|
|
msg = json.loads(raw)
|
|
if msg.get("id") == 1:
|
|
# Primero un evento de CDP sin id (debe drenarse), luego la respuesta.
|
|
self._queue.append(json.dumps({
|
|
"method": "Runtime.consoleAPICalled",
|
|
"params": {"type": "log"},
|
|
}))
|
|
self._queue.append(json.dumps({
|
|
"id": 1,
|
|
"result": {"result": {"type": "string", "value": self._value}},
|
|
}))
|
|
|
|
def recv(self):
|
|
if self._queue:
|
|
return self._queue.pop(0)
|
|
return ""
|
|
|
|
def close(self):
|
|
pass
|
|
|
|
|
|
# --- Tests -----------------------------------------------------------------
|
|
|
|
def test_golden_selecciona_target_por_substr_y_devuelve_value(monkeypatch):
|
|
monkeypatch.setattr(
|
|
urllib.request, "urlopen",
|
|
lambda url, timeout=5: _FakeHTTPResponse(_targets_json()),
|
|
)
|
|
monkeypatch.setattr(
|
|
websocket, "create_connection",
|
|
lambda url, timeout=10.0: _FakeWS(url, "WhatsApp"),
|
|
)
|
|
|
|
res = cdp_eval("document.title", port=9222, target_url_substr="whatsapp")
|
|
|
|
assert res["ok"] is True
|
|
assert res["value"] == "WhatsApp"
|
|
assert res["error"] == ""
|
|
assert res["target_url"] == "https://web.whatsapp.com/"
|
|
# Confirma que eligio el target whatsapp, no el de google.
|
|
assert _FakeWS.last_url.endswith("/WA")
|
|
|
|
|
|
def test_edge_substr_sin_match_devuelve_ok_false(monkeypatch):
|
|
monkeypatch.setattr(
|
|
urllib.request, "urlopen",
|
|
lambda url, timeout=5: _FakeHTTPResponse(_targets_json()),
|
|
)
|
|
# create_connection no deberia llamarse; si lo hace, revienta el test.
|
|
monkeypatch.setattr(
|
|
websocket, "create_connection",
|
|
lambda *a, **k: (_ for _ in ()).throw(AssertionError("no debe conectar")),
|
|
)
|
|
|
|
res = cdp_eval("document.title", port=9222, target_url_substr="nope-no-existe")
|
|
|
|
assert res["ok"] is False
|
|
assert res["value"] is None
|
|
assert "no target matching" in res["error"]
|
|
assert "nope-no-existe" in res["error"]
|
|
assert res["target_url"] == ""
|
|
|
|
|
|
def test_error_urlopen_lanza_devuelve_ok_false(monkeypatch):
|
|
def _boom(url, timeout=5):
|
|
raise OSError("connection refused")
|
|
|
|
monkeypatch.setattr(urllib.request, "urlopen", _boom)
|
|
|
|
res = cdp_eval("document.title", port=9222, target_url_substr="whatsapp")
|
|
|
|
assert res["ok"] is False
|
|
assert res["value"] is None
|
|
assert "connection refused" in res["error"]
|
|
assert res["target_url"] == ""
|