"""ORCH-067 — Group D: clickable issue number in ALL alerts (AC-13, AC-12). Every orchestrator alert that mentions a work_item_id now renders it as a Plane hyperlink via the shared ``link_for`` / ``plane_issue_link`` helpers, and degrades fail-safe to the raw (escaped) number when data is missing. This covers the dedicated notify_* helpers (notify_approve_requested, notify_error) and asserts the engine/launcher/security_gate/reconciler alert sites are wired to ``link_for`` — the single DB-resolving helper those sites call. Network is isolated: send_telegram is replaced with a recorder; the DB is a temp SQLite. Test ids TC-13, TC-14, TC-15 from 04-test-plan.yaml. """ import os import tempfile 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_notify_links.db") os.environ["ORCH_DB_PATH"] = _test_db from types import SimpleNamespace # noqa: E402 import pytest # noqa: E402 import src.db as db_module # noqa: E402 import src.projects as projects_mod # noqa: E402 from src.db import init_db, get_db # noqa: E402 from src import notifications as N # noqa: E402 _ORCH_PROJECT_ID = "8da6aa25-a60e-44d6-a1e2-d8ae59aa7d6a" @pytest.fixture(autouse=True) def setup_db(monkeypatch): monkeypatch.setattr(db_module.settings, "db_path", _test_db, raising=False) if os.path.exists(_test_db): os.unlink(_test_db) init_db() # Pin repo->project resolution so cross-file registry reloads can't strip # 'orchestrator' and break the expected issue URL. monkeypatch.setattr( projects_mod, "get_project_by_repo", lambda repo: (SimpleNamespace(plane_project_id=_ORCH_PROJECT_ID) if repo == "orchestrator" else None), ) yield if os.path.exists(_test_db): os.unlink(_test_db) def _set(monkeypatch, **kw): s = N._get_settings() for k, v in kw.items(): monkeypatch.setattr(s, k, v, raising=False) def _mk_task(wid="ORCH-067", repo="orchestrator", title="notify links", plane_issue_id="iss-1", stage="development"): conn = get_db() cur = conn.execute( "INSERT INTO tasks (plane_id, work_item_id, repo, branch, stage, title, " "plane_issue_id) VALUES (?, ?, ?, ?, ?, ?, ?)", ("p1", wid, repo, "feature/ORCH-067-x", stage, title, plane_issue_id), ) tid = cur.lastrowid conn.commit() conn.close() return tid def _record_send(monkeypatch): calls = [] def _fake(text, disable_notification=False): calls.append({"text": text, "silent": disable_notification}) return 1 monkeypatch.setattr(N, "send_telegram", _fake) monkeypatch.setattr(N, "update_task_tracker", lambda task_id: None) return calls # --------------------------------------------------------------------------- # # TC-13 / AC-13 — notify_approve_requested: number clickable, CTA + single ping # --------------------------------------------------------------------------- # def test_tc13_approve_requested_number_clickable(monkeypatch): _set(monkeypatch, plane_web_url="https://plane.example.org", plane_workspace_slug="acme", gitea_public_url="https://git.example.org", gitea_owner="orchteam") tid = _mk_task(plane_issue_id="iss-1") calls = _record_send(monkeypatch) N.notify_approve_requested(tid) assert len(calls) == 1 # exactly one notifying ping assert calls[0]["silent"] is not True text = calls[0]["text"] expected = ( f"https://plane.example.org/acme/projects/{_ORCH_PROJECT_ID}" f"/issues/iss-1/" ) assert f'ORCH-067' in text # clickable number assert "Approved" in text # call-to-action preserved # --------------------------------------------------------------------------- # # TC-14 / AC-13, AC-12 — notify_error: clickable when data present, else raw # --------------------------------------------------------------------------- # def test_tc14_notify_error_clickable(monkeypatch): _set(monkeypatch, plane_web_url="https://plane.example.org", plane_workspace_slug="acme") tid = _mk_task(plane_issue_id="iss-1") calls = _record_send(monkeypatch) N.notify_error(tid, "boom happened") assert len(calls) == 1 text = calls[0]["text"] assert ">ORCH-067" in text # number is a link assert "ERROR" in text and "boom happened" in text def test_tc14_notify_error_degrades_raw_number(monkeypatch): # No usable Plane base -> raw (unlinked) number, alert still sent, no crash. _set(monkeypatch, plane_web_url="", plane_api_url="") tid = _mk_task(plane_issue_id="iss-1") calls = _record_send(monkeypatch) N.notify_error(tid, "boom") text = calls[0]["text"] assert "ORCH-067" in text assert " & ") text = calls[0]["text"] assert "