10bfb846a8
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
113 lines
4.4 KiB
Python
113 lines
4.4 KiB
Python
"""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
|