Files
fn_registry/python/functions/browser/whatsapp_open_chat_test.py
T
egutierrez 10bfb846a8 ahora si funciona
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-07 16:23:52 +02:00

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