import os import sys import tempfile _fd, _TMP = tempfile.mkstemp(suffix=".db") os.close(_fd) os.unlink(_TMP) os.environ["AGENT_OFFICE_DB_PATH"] = _TMP sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import pytest from unittest.mock import AsyncMock, patch @pytest.fixture(autouse=True) def _init_db(): import gc gc.collect() if os.path.exists(_TMP): os.remove(_TMP) from app.db import init_db init_db() yield gc.collect() @pytest.mark.asyncio async def test_poll_notifies_once_per_state(): from app.agents.youtube_publisher import YoutubePublisherAgent pipelines = [{ "id": 1, "state": "cover_pending", "cover_url": "/x.jpg", "track_title": "Test", }] with patch( "app.agents.youtube_publisher.service_proxy.list_active_pipelines", new=AsyncMock(return_value=pipelines), ), patch( "app.agents.youtube_publisher.send_raw", new=AsyncMock(return_value={"ok": True, "message_id": 99}), ) as mock_send, patch( "app.agents.youtube_publisher.service_proxy.save_pipeline_telegram_msg", new=AsyncMock(), ): a = YoutubePublisherAgent() await a.poll_state_changes() await a.poll_state_changes() # 같은 상태 — 두 번째는 알림 안 함 assert mock_send.call_count == 1 @pytest.mark.asyncio async def test_on_telegram_reply_approve_calls_feedback(): from app.agents.youtube_publisher import YoutubePublisherAgent with patch( "app.agents.youtube_publisher.service_proxy.post_pipeline_feedback", new=AsyncMock(), ) as mock_fb, patch( "app.agents.youtube_publisher.send_raw", new=AsyncMock(), ): a = YoutubePublisherAgent() await a.on_telegram_reply(pipeline_id=42, step="cover", user_text="승인") mock_fb.assert_called_once_with(42, "cover", "approve", None) @pytest.mark.asyncio async def test_on_telegram_reply_reject_with_feedback(): from app.agents.youtube_publisher import YoutubePublisherAgent with patch( "app.agents.youtube_publisher.service_proxy.post_pipeline_feedback", new=AsyncMock(), ) as mock_fb, patch( "app.agents.youtube_publisher.send_raw", new=AsyncMock(), ): a = YoutubePublisherAgent() await a.on_telegram_reply(pipeline_id=43, step="meta", user_text="반려, 제목 짧게") args = mock_fb.call_args[0] assert args[0] == 43 assert args[1] == "meta" assert args[2] == "reject" assert "제목 짧게" in (args[3] or "") @pytest.mark.asyncio async def test_on_telegram_reply_unclear_asks_again(): from app.agents.youtube_publisher import YoutubePublisherAgent sent = [] async def mock_send(text=None, **kw): sent.append(text) return {"ok": True, "message_id": 1} with patch( "app.agents.youtube_publisher.send_raw", new=mock_send, ), patch( "app.agents.youtube_publisher.classify_intent.classify", return_value=("unclear", None), ): a = YoutubePublisherAgent() await a.on_telegram_reply(pipeline_id=44, step="cover", user_text="huh?") assert any("다시 입력" in (s or "") for s in sent)