"""Tests para browser_profile_register. browser_profile_register hace POST al service osint_db (perfil + cuentas). Aqui se mockea el helper compartido `post_json` (ligado en el modulo por el `from browser._osint_db_client import post_json`) para NO tocar el service real. Se valida el armado de los payloads y el conteo/errores de cuentas. """ import os import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) import browser.browser_profile_register as bpr from browser.browser_profile_register import browser_profile_register class _PostSpy: """Registra cada (path, payload) y devuelve respuestas segun el path.""" def __init__(self, profile_resp, account_resp): self.calls = [] # lista de (path, payload) self.profile_resp = profile_resp self.account_resp = account_resp def __call__(self, base_url, path, payload): self.calls.append((path, payload)) if path == "/api/browser-profile": return self.profile_resp return self.account_resp def test_golden_registra_perfil_con_dos_cuentas(monkeypatch): spy = _PostSpy( profile_resp={"status": "ok", "profile_dir": "Profile 1", "inserted": 1, "updated": 0}, account_resp={"status": "ok", "id": "x", "inserted": 1, "updated": 0}, ) monkeypatch.setattr(bpr, "post_json", spy) res = browser_profile_register( "Profile 1", label="Persona Maria", persona="maria_ficticia", purpose="rastreo", tags=["osint", "sock-puppet"], accounts=[ {"service": "gmail", "identity": "maria@example.com", "secret_ref": "pass show osint/p1/gmail"}, {"service": "x", "identity": "@maria_fake", "role": "primary"}, ], ) assert res["status"] == "ok" assert res["profile_dir"] == "Profile 1" assert res["accounts"] == 2 assert res["account_errors"] == [] # 1 POST de perfil + 2 POST de cuentas = 3 llamadas. assert len(spy.calls) == 3 profile_path, profile_payload = spy.calls[0] assert profile_path == "/api/browser-profile" assert profile_payload["profile_dir"] == "Profile 1" assert profile_payload["label"] == "Persona Maria" assert profile_payload["tags"] == ["osint", "sock-puppet"] assert profile_payload["status"] == "active" # user_data_dir vacio no debe ir en el payload. assert "user_data_dir" not in profile_payload # Las cuentas llevan profile_dir y solo las claves no vacias. acc_path, acc_payload = spy.calls[1] assert acc_path == "/api/browser-profile/account" assert acc_payload["profile_dir"] == "Profile 1" assert acc_payload["service"] == "gmail" assert acc_payload["secret_ref"] == "pass show osint/p1/gmail" def test_edge_cuenta_invalida_se_reporta_y_no_se_envia(monkeypatch): spy = _PostSpy( profile_resp={"status": "ok", "profile_dir": "osint_01", "inserted": 0, "updated": 1}, account_resp={"status": "ok"}, ) monkeypatch.setattr(bpr, "post_json", spy) res = browser_profile_register( "osint_01", accounts=[ {"service": "gmail"}, # falta identity -> invalida {"service": "x", "identity": "@ok"}, # valida ], ) assert res["status"] == "ok" assert res["accounts"] == 1 # solo la valida se registro assert len(res["account_errors"]) == 1 assert "identity" in res["account_errors"][0]["error"] # La cuenta invalida NO genero POST: 1 perfil + 1 cuenta valida = 2 llamadas. assert len(spy.calls) == 2 def test_error_post_perfil_falla_devuelve_status_error(monkeypatch): spy = _PostSpy( profile_resp={"status": "error", "error": "service osint_db inaccesible"}, account_resp={"status": "ok"}, ) monkeypatch.setattr(bpr, "post_json", spy) res = browser_profile_register("Profile 1", accounts=[{"service": "g", "identity": "a@b"}]) assert res["status"] == "error" assert "inaccesible" in res["error"] # Si el perfil falla, NO se intentan las cuentas: solo 1 llamada (la del perfil). assert len(spy.calls) == 1