Files
fn_registry/python/functions/infra/carddav_put_vcard_test.py
T
egutierrez a76760edba feat(dav,obsidian): grupo dav completo (CardDAV/CalDAV client + split vcf/ics + import pipelines) + build_obsidian_graph + dav_list_calendars
Funciones reutilizables creadas esta sesion para el sistema self-hosted de contactos/calendario (Xandikos) y la app osint_web:
- grupo dav (infra): split_vcards, split_vevents_to_vcalendars, extract_or_make_uid, carddav_put_vcard, caldav_put_event, dav_list_resources, dav_get_resource, dav_list_calendars
- pipelines: import_vcf_to_carddav, import_ics_to_caldav
- obsidian: build_obsidian_graph (grafo agregado del vault)
2026-06-12 00:43:59 +02:00

89 lines
2.5 KiB
Python

"""Tests para carddav_put_vcard.
Smoke deterministas: monkeypatchean urllib.request.urlopen para capturar el
Request object (URL, method, headers, body) sin enviarlo a un servidor real.
"""
import base64
import sys
import infra.carddav_put_vcard # noqa: F401
mod = sys.modules["infra.carddav_put_vcard"]
carddav_put_vcard = mod.carddav_put_vcard
class _FakeResp:
status = 201
def __enter__(self):
return self
def __exit__(self, *a):
return False
def _capture(monkeypatch):
captured = {}
def fake_urlopen(req, timeout=None, context=None):
captured["url"] = req.full_url
captured["method"] = req.get_method()
captured["headers"] = dict(req.header_items())
captured["body"] = req.data
return _FakeResp()
monkeypatch.setattr(mod.urllib.request, "urlopen", fake_urlopen)
return captured
def _call():
return carddav_put_vcard(
base_url="https://dav.example.com",
username="enmanuel",
password="secret-pw",
collection_path="/enmanuel/contacts/addressbook/",
uid="abc-123@google.com",
vcard_text="BEGIN:VCARD\r\nFN:Ada\r\nUID:abc-123@google.com\r\nEND:VCARD",
)
def test_construye_request_put_con_headers_correctos(monkeypatch):
cap = _capture(monkeypatch)
res = _call()
assert res == {"status": "ok", "http_status": 201, "url": cap["url"]}
assert cap["method"] == "PUT"
def test_url_se_forma_con_uid_saneado(monkeypatch):
cap = _capture(monkeypatch)
_call()
# El '@' del uid se sanea a '_'.
assert cap["url"].endswith("/enmanuel/contacts/addressbook/abc-123_google.com.vcf")
def test_content_type_es_text_vcard(monkeypatch):
cap = _capture(monkeypatch)
_call()
# urllib capitaliza las claves de header.
headers = {k.lower(): v for k, v in cap["headers"].items()}
assert headers["content-type"] == "text/vcard; charset=utf-8"
def test_basic_auth_header_correcto(monkeypatch):
cap = _capture(monkeypatch)
_call()
headers = {k.lower(): v for k, v in cap["headers"].items()}
expected = "Basic " + base64.b64encode(b"enmanuel:secret-pw").decode("ascii")
assert headers["authorization"] == expected
def test_httperror_devuelve_status_error(monkeypatch):
def fake_urlopen(req, timeout=None, context=None):
raise mod.urllib.error.HTTPError(req.full_url, 409, "Conflict", {}, None)
monkeypatch.setattr(mod.urllib.request, "urlopen", fake_urlopen)
res = _call()
assert res["status"] == "error"
assert res["http_status"] == 409