"""ORCH-080 — suppress Telegram link-preview in tracker/notify primitives. Both low-level primitives ``send_telegram`` (POST /sendMessage) and ``edit_telegram`` (POST /editMessageText) must add ``"disable_web_page_preview": True`` to their JSON payload, so the Plane "Modern project management" banner no longer expands under every tracker card / notification. The clickable issue link must stay clickable -> ``parse_mode: "HTML"`` is preserved in both payloads, and the never-raise / return contracts are unchanged. Network is isolated: ``src.notifications.httpx`` is patched; creds are stubbed. Test ids TC-01..TC-06 from 04-test-plan.yaml. """ import os import tempfile from unittest.mock import MagicMock, patch os.environ.setdefault("ORCH_PLANE_API_TOKEN", "test-token") os.environ.setdefault("ORCH_GITEA_TOKEN", "test-token") _test_db = os.path.join(tempfile.gettempdir(), "test_orchestrator_link_preview.db") os.environ.setdefault("ORCH_DB_PATH", _test_db) from src import notifications as N # noqa: E402 # conftest._no_telegram autouse-patches src.notifications.send_telegram to a # no-op for every test (prod-leak guard). Capture the REAL implementation at # import time (before any fixture runs) so these payload tests can exercise it. _REAL_SEND = N.send_telegram def _patch_tg_creds(monkeypatch): monkeypatch.setattr(N._get_settings(), "telegram_bot_token", "T", raising=False) monkeypatch.setattr(N._get_settings(), "telegram_chat_id", "C", raising=False) def _ok_resp(message_id=42): resp = MagicMock() resp.json.return_value = {"ok": True, "result": {"message_id": message_id}} return resp # --------------------------------------------------------------------------- # # TC-01 — send_telegram sets disable_web_page_preview: True # --------------------------------------------------------------------------- # def test_send_telegram_disables_link_preview(monkeypatch): _patch_tg_creds(monkeypatch) with patch("src.notifications.httpx") as hx: hx.post.return_value = _ok_resp() _REAL_SEND("hello") payload = hx.post.call_args.kwargs["json"] assert payload["disable_web_page_preview"] is True # --------------------------------------------------------------------------- # # TC-02 — edit_telegram sets disable_web_page_preview: True # --------------------------------------------------------------------------- # def test_edit_telegram_disables_link_preview(monkeypatch): _patch_tg_creds(monkeypatch) with patch("src.notifications.httpx") as hx: hx.post.return_value = _ok_resp() N.edit_telegram(1, "hello") payload = hx.post.call_args.kwargs["json"] assert payload["disable_web_page_preview"] is True # --------------------------------------------------------------------------- # # TC-03 — parse_mode HTML preserved in both payloads (clickable ) # --------------------------------------------------------------------------- # def test_send_telegram_keeps_parse_mode_html(monkeypatch): _patch_tg_creds(monkeypatch) with patch("src.notifications.httpx") as hx: hx.post.return_value = _ok_resp() _REAL_SEND("hello") assert hx.post.call_args.kwargs["json"]["parse_mode"] == "HTML" def test_edit_telegram_keeps_parse_mode_html(monkeypatch): _patch_tg_creds(monkeypatch) with patch("src.notifications.httpx") as hx: hx.post.return_value = _ok_resp() N.edit_telegram(1, "hello") assert hx.post.call_args.kwargs["json"]["parse_mode"] == "HTML" # --------------------------------------------------------------------------- # # TC-04 — send_telegram preserves existing fields + disable_notification arg # --------------------------------------------------------------------------- # def test_send_telegram_preserves_existing_fields(monkeypatch): _patch_tg_creds(monkeypatch) with patch("src.notifications.httpx") as hx: hx.post.return_value = _ok_resp() _REAL_SEND("body", disable_notification=True) payload = hx.post.call_args.kwargs["json"] assert payload["chat_id"] == "C" assert payload["text"] == "body" assert payload["parse_mode"] == "HTML" assert payload["disable_notification"] is True def test_send_telegram_disable_notification_default_false(monkeypatch): _patch_tg_creds(monkeypatch) with patch("src.notifications.httpx") as hx: hx.post.return_value = _ok_resp() _REAL_SEND("body") assert hx.post.call_args.kwargs["json"]["disable_notification"] is False def test_edit_telegram_preserves_existing_fields(monkeypatch): _patch_tg_creds(monkeypatch) with patch("src.notifications.httpx") as hx: hx.post.return_value = _ok_resp() N.edit_telegram(7, "body") payload = hx.post.call_args.kwargs["json"] assert payload["chat_id"] == "C" assert payload["message_id"] == 7 assert payload["text"] == "body" assert payload["parse_mode"] == "HTML" # --------------------------------------------------------------------------- # # TC-05 — return contracts unchanged # --------------------------------------------------------------------------- # def test_send_telegram_returns_message_id(monkeypatch): _patch_tg_creds(monkeypatch) with patch("src.notifications.httpx") as hx: hx.post.return_value = _ok_resp(message_id=99) assert _REAL_SEND("x") == 99 def test_send_telegram_returns_none_without_creds(monkeypatch): monkeypatch.setattr(N._get_settings(), "telegram_bot_token", "", raising=False) monkeypatch.setattr(N._get_settings(), "telegram_chat_id", "", raising=False) assert _REAL_SEND("x") is None def test_edit_telegram_returns_edit_ok(monkeypatch): _patch_tg_creds(monkeypatch) with patch("src.notifications.httpx") as hx: hx.post.return_value = _ok_resp() assert N.edit_telegram(1, "x") == N.EDIT_OK # --------------------------------------------------------------------------- # # TC-06 — never-raise: httpx.post raising -> None / EDIT_FAILED # --------------------------------------------------------------------------- # def test_send_telegram_never_raises(monkeypatch): _patch_tg_creds(monkeypatch) with patch("src.notifications.httpx") as hx: hx.post.side_effect = Exception("boom") assert _REAL_SEND("x") is None def test_edit_telegram_never_raises(monkeypatch): _patch_tg_creds(monkeypatch) with patch("src.notifications.httpx") as hx: hx.post.side_effect = Exception("boom") assert N.edit_telegram(1, "x") == N.EDIT_FAILED