import time from typing import Any import pytest from app.core.config import get_settings from app.modules.feishu.client import FeishuClient from app.modules.feishu.errors import FeishuAPIError class _Response: def __init__(self, payload: dict[str, Any], status_code: int = 200): self.payload = payload self.status_code = status_code def json(self) -> dict[str, Any]: return self.payload class _Client: response = _Response({"code": 0, "data": {"message_id": "om-ok"}}) request: dict[str, Any] | None = None def __init__(self, **_: Any): pass def __enter__(self) -> "_Client": return self def __exit__(self, *_: Any) -> None: return None def post(self, url: str, **kwargs: Any) -> _Response: _Client.request = {"url": url, **kwargs} return self.response def _configured_client(monkeypatch: pytest.MonkeyPatch) -> FeishuClient: monkeypatch.setenv("FEISHU_APP_ID", "test-app") monkeypatch.setenv("FEISHU_APP_SECRET", "test-secret") get_settings.cache_clear() client = FeishuClient() client._tenant_access_token = "tenant-token" client._token_expires_at = time.time() + 60 monkeypatch.setattr("app.modules.feishu.client.httpx.Client", _Client) return client def test_message_uuid_is_forwarded_to_feishu(monkeypatch: pytest.MonkeyPatch) -> None: client = _configured_client(monkeypatch) try: result = client.send_text( "hello", receive_id="ou-user", receive_id_type="open_id", uuid="stable-delivery-uuid", ) assert result["code"] == 0 assert _Client.request is not None assert _Client.request["json"]["uuid"] == "stable-delivery-uuid" finally: get_settings.cache_clear() def test_nonzero_feishu_business_code_is_not_success( monkeypatch: pytest.MonkeyPatch, ) -> None: client = _configured_client(monkeypatch) _Client.response = _Response({"code": 99991400, "msg": "rate limited"}) try: with pytest.raises(FeishuAPIError) as exc_info: client.send_text("hello", receive_id="ou-user", receive_id_type="open_id") assert exc_info.value.provider_code == 99991400 assert exc_info.value.retryable is True finally: _Client.response = _Response({"code": 0, "data": {"message_id": "om-ok"}}) get_settings.cache_clear()