import pytest import seven_send.client as cl from seven_send import SevenClient, SevenError class FakeResp: def __init__(self, status_code=200, payload=None, text=""): self.status_code = status_code self._payload = payload self.text = text def json(self): if self._payload is None: raise ValueError("kein JSON") return self._payload def _patch_post(monkeypatch, capture, resp): def fake_post(url, data=None, headers=None, timeout=None): capture.append({"url": url, "data": data, "headers": headers}) return resp monkeypatch.setattr(cl.httpx, "post", fake_post) def test_send_sms_ok(monkeypatch): cap = [] _patch_post(monkeypatch, cap, FakeResp( payload={"success": "100", "messages": [{"success": True}], "total_price": 0.075})) r = SevenClient("key", sms_from="Notruf").send_sms("+4915112345678", "Hallo") assert r.ok and bool(r) is True assert r.channel == "sms" and r.price == 0.075 assert cap[0]["url"].endswith("/sms") assert cap[0]["headers"]["X-Api-Key"] == "key" assert cap[0]["data"] == {"to": "+4915112345678", "text": "Hallo", "from": "Notruf"} def test_send_voice_wraps_ssml(monkeypatch): cap = [] _patch_post(monkeypatch, cap, FakeResp(payload={"success": "100"})) r = SevenClient("key", voice_name="de-de-female").send_voice("+49", "Test & ") assert r.ok txt = cap[0]["data"]["text"] assert txt.startswith('') assert "&" in txt and "<x>" in txt assert cap[0]["url"].endswith("/voice") def test_voice_no_ssml(monkeypatch): cap = [] _patch_post(monkeypatch, cap, FakeResp(payload={"success": "100"})) SevenClient("key").send_voice("+49", "roh", ssml=False) assert cap[0]["data"]["text"] == "roh" def test_failure_code(monkeypatch): cap = [] _patch_post(monkeypatch, cap, FakeResp(payload={"success": "401"})) r = SevenClient("key").send_sms("+49", "x") assert not r.ok and r.code == "401" def test_sms_bare_int_code_ok(monkeypatch): # SMS-Endpunkt liefert oft nur den nackten Code -> resp.json() == int 100 cap = [] _patch_post(monkeypatch, cap, FakeResp(payload=100, text="100")) r = SevenClient("key").send_sms("+49", "x") assert r.ok and r.code == "100" def test_sms_bare_int_code_error(monkeypatch): cap = [] _patch_post(monkeypatch, cap, FakeResp(payload=900, text="900")) r = SevenClient("key").send_sms("+49", "x") assert not r.ok and r.code == "900" and "900" in r.error def test_http_error(monkeypatch): cap = [] _patch_post(monkeypatch, cap, FakeResp(status_code=500, text="boom")) r = SevenClient("key").send_sms("+49", "x") assert not r.ok and "HTTP 500" in r.error def test_network_exception(monkeypatch): def boom(*a, **k): raise RuntimeError("offline") monkeypatch.setattr(cl.httpx, "post", boom) r = SevenClient("key").send_sms("+49", "x") assert not r.ok and "offline" in r.error def test_dry_run_does_not_post(monkeypatch): def boom(*a, **k): raise AssertionError("kein POST im dry-run") monkeypatch.setattr(cl.httpx, "post", boom) r = SevenClient("", dry_run=True).send_sms("+49", "x") assert r.ok and r.code == "dry-run" def test_missing_key_raises(): with pytest.raises(SevenError): SevenClient("")