ahora si funciona
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
"""Tests para whatsapp_open_chat.
|
||||
|
||||
whatsapp_open_chat compone cuatro primitivas CDP (cdp_eval, cdp_type_chars,
|
||||
cdp_press_key, cdp_click_xy) y requiere un Chrome vivo. Aqui se mockean las cuatro
|
||||
con monkeypatch sobre el modulo `browser.whatsapp_open_chat` (donde quedan ligados
|
||||
los nombres por el `from browser.X import Y`), de modo que NO hace falta Chrome.
|
||||
|
||||
Las llamadas a cdp_eval que importan son dos:
|
||||
- la del ancla (querySelectorAll '#side span[title]') -> devuelve coords JSON.
|
||||
- la de verificacion (footer contenteditable aria-label) -> devuelve el label.
|
||||
El resto de cdp_eval (focus/select del input) devuelven un value inocuo.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
||||
|
||||
import browser.whatsapp_open_chat as woc
|
||||
from browser.whatsapp_open_chat import whatsapp_open_chat
|
||||
|
||||
|
||||
# --- Fakes -----------------------------------------------------------------
|
||||
|
||||
def _fake_cdp_eval_factory(anchor_value, composer_value):
|
||||
"""Devuelve un fake de cdp_eval que distingue el ancla del composer.
|
||||
|
||||
- Expresion con 'span[title]' (busqueda del ancla) -> {"value": anchor_value}.
|
||||
- Expresion con 'contenteditable' (composer) -> {"value": composer_value}.
|
||||
- Cualquier otra (focus/select del input) -> {"value": None} inocuo.
|
||||
"""
|
||||
|
||||
def _fake(expr, *, port=9222, target_url_substr=""):
|
||||
if "span[title]" in expr:
|
||||
return {"ok": True, "value": anchor_value, "error": "", "target_url": ""}
|
||||
if "contenteditable" in expr:
|
||||
return {"ok": True, "value": composer_value, "error": "", "target_url": ""}
|
||||
return {"ok": True, "value": None, "error": "", "target_url": ""}
|
||||
|
||||
return _fake
|
||||
|
||||
|
||||
class _Spy:
|
||||
"""Registra los argumentos posicionales de cada llamada."""
|
||||
|
||||
def __init__(self, ret=None):
|
||||
self.calls = []
|
||||
self.ret = ret if ret is not None else {"ok": True}
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
self.calls.append((args, kwargs))
|
||||
return self.ret
|
||||
|
||||
|
||||
def _patch_io(monkeypatch, *, anchor_value, composer_value, click_spy=None):
|
||||
"""Mockea las cuatro primitivas + time.sleep en el modulo woc."""
|
||||
monkeypatch.setattr(woc, "cdp_eval",
|
||||
_fake_cdp_eval_factory(anchor_value, composer_value))
|
||||
monkeypatch.setattr(woc, "cdp_type_chars", lambda *a, **k: {"ok": True})
|
||||
monkeypatch.setattr(woc, "cdp_press_key", lambda *a, **k: {"ok": True})
|
||||
monkeypatch.setattr(woc, "cdp_click_xy", click_spy or (lambda *a, **k: {"ok": True}))
|
||||
monkeypatch.setattr(woc.time, "sleep", lambda *a, **k: None)
|
||||
|
||||
|
||||
# --- Tests -----------------------------------------------------------------
|
||||
|
||||
def test_golden_abre_chat_y_verifica_composer(monkeypatch):
|
||||
coords = json.dumps({"x": 180, "y": 240})
|
||||
label = "Escribir un mensaje para el grupo NOTAS WASAP"
|
||||
_patch_io(monkeypatch, anchor_value=coords, composer_value=label)
|
||||
|
||||
res = whatsapp_open_chat("NOTAS WASAP", port=9222, target_url_substr="whatsapp")
|
||||
|
||||
assert res["opened"] is True
|
||||
assert res["name"] == "NOTAS WASAP"
|
||||
assert res["composer_label"] == label
|
||||
assert res["coords"] == {"x": 180, "y": 240}
|
||||
|
||||
|
||||
def test_edge_ancla_no_encontrada_opened_false(monkeypatch):
|
||||
# El ancla no existe: cdp_eval del span[title] devuelve value None.
|
||||
_patch_io(monkeypatch, anchor_value=None, composer_value="irrelevante")
|
||||
|
||||
res = whatsapp_open_chat("Contacto Inexistente", port=9222,
|
||||
target_url_substr="whatsapp")
|
||||
|
||||
assert res["opened"] is False
|
||||
assert res["name"] == "Contacto Inexistente"
|
||||
assert "no encontrado" in res["reason"]
|
||||
# Sin coords ni composer_label cuando no se encuentra el ancla.
|
||||
assert "coords" not in res
|
||||
assert "composer_label" not in res
|
||||
|
||||
|
||||
def test_click_usa_coords_devueltas_por_el_ancla(monkeypatch):
|
||||
coords = json.dumps({"x": 333, "y": 444})
|
||||
label = "Escribir un mensaje para el grupo NOTAS WASAP"
|
||||
click_spy = _Spy(ret={"ok": True})
|
||||
_patch_io(monkeypatch, anchor_value=coords, composer_value=label,
|
||||
click_spy=click_spy)
|
||||
|
||||
res = whatsapp_open_chat("NOTAS WASAP", port=9222, target_url_substr="whatsapp")
|
||||
|
||||
# Se llamo a cdp_click_xy exactamente una vez con las coords del ancla.
|
||||
assert len(click_spy.calls) == 1
|
||||
args, kwargs = click_spy.calls[0]
|
||||
assert args[0] == 333
|
||||
assert args[1] == 444
|
||||
assert kwargs["port"] == 9222
|
||||
assert kwargs["target_url_substr"] == "whatsapp"
|
||||
assert res["opened"] is True
|
||||
Reference in New Issue
Block a user