import pytest from click.testing import CliRunner from unittest.mock import Mock, patch, AsyncMock import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).parent.parent / "src")) from promptforge.cli.main import main @pytest.fixture def cli_runner(): return CliRunner() def test_main_help(cli_runner): result = cli_runner.invoke(main, ["--help"]) assert result.exit_code == 0 assert "PromptForge" in result.output def test_main_version(cli_runner): result = cli_runner.invoke(main, ["--version"]) assert result.exit_code == 0 assert "0.1.0" in result.output def test_prompt_group(cli_runner): result = cli_runner.invoke(main, ["prompt", "--help"]) assert result.exit_code == 0 assert "create" in result.output assert "list" in result.output assert "show" in result.output def test_version_group(cli_runner): result = cli_runner.invoke(main, ["version", "--help"]) assert result.exit_code == 0 assert "history" in result.output assert "create" in result.output def test_registry_group(cli_runner): result = cli_runner.invoke(main, ["registry", "--help"]) assert result.exit_code == 0 assert "list" in result.output assert "search" in result.output def test_run_command(cli_runner, tmp_path): with patch("promptforge.cli.commands.run.Prompt.list") as mock_list: mock_prompt = Mock() mock_prompt.name = "TestPrompt" mock_prompt.content = "Hello {{name}}" mock_prompt.variables = [] mock_prompt.provider = None mock_prompt.validation_rules = [] mock_list.return_value = [mock_prompt] with patch("promptforge.cli.commands.run.ProviderFactory.create") as mock_factory: mock_provider = Mock() mock_provider.stream_complete = AsyncMock(return_value=iter(["Hello ", "World"])) mock_factory.return_value = mock_provider with patch("promptforge.cli.commands.run.get_config") as mock_config: mock_cfg = Mock() mock_cfg.providers = {} mock_cfg.defaults.provider = "openai" mock_config.return_value = mock_cfg result = cli_runner.invoke(main, ["run", "TestPrompt", "-v", "name=World", "--no-stream"]) assert result.exit_code == 0 assert mock_factory.called