"""Tests for marketing_intelligence.cli.""" from __future__ import annotations import sys from unittest.mock import MagicMock, patch import pytest _MOD = "marketing_intelligence.cli" # ──────────────────────────── serve ─────────────────────────────────────────── class TestServe: def test_calls_mcp_run(self) -> None: mock_mcp = MagicMock() mock_settings = MagicMock() mock_settings.mcp_host = "0.0.0.0" mock_settings.mcp_port = 8001 with patch.dict( "sys.modules", { "marketing_intelligence.mcp.server": MagicMock(mcp=mock_mcp), "marketing_intelligence.core.config": MagicMock(settings=mock_settings), }, ): from marketing_intelligence.cli import serve serve() mock_mcp.run.assert_called_once_with( transport="streamable-http", host="0.0.0.0", port=8001, host_origin_protection=False, ) def test_suppresses_keyboard_interrupt(self) -> None: mock_mcp = MagicMock() mock_mcp.run.side_effect = KeyboardInterrupt mock_settings = MagicMock(mcp_host="0.0.0.0", mcp_port=8001) with patch.dict( "sys.modules", { "marketing_intelligence.mcp.server": MagicMock(mcp=mock_mcp), "marketing_intelligence.core.config": MagicMock(settings=mock_settings), }, ): from marketing_intelligence.cli import serve serve() # should not raise # ──────────────────────────── api ───────────────────────────────────────────── class TestApi: def test_calls_uvicorn_run(self) -> None: mock_uvicorn = MagicMock() with patch.dict("sys.modules", {"uvicorn": mock_uvicorn}): from marketing_intelligence.cli import api api() mock_uvicorn.run.assert_called_once_with( "marketing_intelligence.api.main:app", host="0.0.0.0", port=8080 ) # ──────────────────────────── agent ─────────────────────────────────────────── class TestAgent: def _run(self, args: list[str], campaign: MagicMock | None = None) -> MagicMock: mock_campaign = campaign or MagicMock() if campaign is None: mock_campaign.tags = ["tag1"] mock_campaign.sample_size = 0 with ( patch( "marketing_intelligence.storage.campaigns.get_campaign", return_value=mock_campaign, ), patch( "marketing_intelligence.agent_workflows.discovery.run_discovery_sync", return_value="done", ), patch("marketing_intelligence.core.logging.setup_logging"), ): from marketing_intelligence.cli import agent agent(args) return mock_campaign def test_basic_run(self) -> None: self._run(["--campaign-id", "artist_track"]) def test_with_tag_overrides_tags(self) -> None: mock_campaign = MagicMock() mock_campaign.tags = ["original"] mock_campaign.sample_size = 0 self._run( ["--campaign-id", "artist_track", "--tag", "mytag"], campaign=mock_campaign ) assert mock_campaign.tags == ["mytag"] def test_with_sample_size_overrides(self) -> None: mock_campaign = MagicMock() mock_campaign.tags = ["tag"] mock_campaign.sample_size = 0 self._run( ["--campaign-id", "artist_track", "--sample-size", "50"], campaign=mock_campaign, ) assert mock_campaign.sample_size == 50 def test_unknown_campaign_exits(self) -> None: with ( patch( "marketing_intelligence.storage.campaigns.get_campaign", return_value=None, ), patch("marketing_intelligence.core.logging.setup_logging"), pytest.raises(SystemExit), ): from marketing_intelligence.cli import agent agent(["--campaign-id", "nonexistent"]) # ──────────────────────────── monitor ───────────────────────────────────────── class TestMonitor: def test_direct_mode(self) -> None: with ( patch("marketing_intelligence.core.logging.setup_logging"), patch( "marketing_intelligence.agent_workflows.monitor_direct.run_monitor_direct", return_value=None, ), patch("asyncio.run") as mock_run, ): from marketing_intelligence.cli import monitor monitor("direct") mock_run.assert_called_once() def test_agent_mode(self) -> None: with ( patch("marketing_intelligence.core.logging.setup_logging"), patch( "marketing_intelligence.agent_workflows.monitor_agent.run_monitor_agent", return_value=None, ), patch("asyncio.run") as mock_run, ): from marketing_intelligence.cli import monitor monitor("agent") mock_run.assert_called_once() # ──────────────────────────── main dispatch ─────────────────────────────────── class TestMain: def _main_with_argv(self, argv: list[str]) -> None: with patch.object(sys, "argv", argv): from marketing_intelligence.cli import main main() def test_defaults_to_api(self) -> None: with patch(f"{_MOD}.api") as mock_api: self._main_with_argv(["cli"]) mock_api.assert_called_once() def test_api_command(self) -> None: with patch(f"{_MOD}.api") as mock_api: self._main_with_argv(["cli", "api"]) mock_api.assert_called_once() def test_serve_command(self) -> None: with patch(f"{_MOD}.serve") as mock_serve: self._main_with_argv(["cli", "serve"]) mock_serve.assert_called_once() def test_agent_command(self) -> None: with patch(f"{_MOD}.agent") as mock_agent: self._main_with_argv(["cli", "agent", "--campaign-id", "x"]) mock_agent.assert_called_once_with(["--campaign-id", "x"]) def test_monitor_agent_command(self) -> None: with patch(f"{_MOD}.monitor") as mock_monitor: self._main_with_argv(["cli", "monitor_agent"]) mock_monitor.assert_called_once_with("agent") def test_monitor_direct_command(self) -> None: with patch(f"{_MOD}.monitor") as mock_monitor: self._main_with_argv(["cli", "monitor_direct"]) mock_monitor.assert_called_once_with("direct") def test_unknown_command_exits(self) -> None: with pytest.raises(SystemExit): self._main_with_argv(["cli", "unknown_cmd"])