diff --git a/test/test_cli.py b/test/test_cli.py new file mode 100644 index 0000000..f6a98da --- /dev/null +++ b/test/test_cli.py @@ -0,0 +1,80 @@ +import pytest +from typer.testing import CliRunner +from unittest.mock import patch, MagicMock +from pathlib import Path +from photools3.cli import app + +runner = CliRunner() + +@pytest.fixture +def mock_photo_logic(tmp_path): + """Fixture to mock the core logic of keywords command.""" + with patch("photools3.cli.LlmSessionCaptionsAndKeywords") as mocked_session, \ + patch("photools3.cli.Photo") as mocked_photo: + + # Configure session mock + session_instance = mocked_session.return_value + session_instance.call.return_value = { + "caption": "A beautiful test image", + "args": ["test", "mock", "image"] # Wait, the code uses 'tags' + } + # Let me re-check the code in cli.py + # result.get("tags", []) + session_instance.call.return_value = { + "caption": "A beautiful test image", + "tags": ["test", "mock", "image"] + } + + # Configure photo mock + photo_instance = mocked_photo.return_value + photo_instance.path = tmp_path / "test_image.jpg" + + yield { + "session": session_instance, + "photo_class": mocked_photo, + "photo_instance": photo_instance + } + +@pytest.fixture +def dummy_file(tmp_path): + """Fixture to create a dummy file for CLI testing.""" + dummy_path = tmp_path / "test_image.jpg" + dummy_path.write_text("dummy content") + return dummy_path + +def test_keywords_command_success(mock_photo_logic, dummy_file): + """Test the 'keywords' command with a valid file path.""" + # Ensure the mock photo instance points to our dummy file + mock_photo_logic["photo_class"].return_value.path = dummy_file + + result = runner.invoke(app, ["keywords", str(dummy_file)]) + + assert result.exit_code == 0 + assert "Processing: " in result.stdout + assert "Caption: A beautiful test image" in result.stdout + assert "Tags: test, mock, image" in result.stdout + +def test_keywords_command_file_not_found(): + """Test the 'keywords' command with a non-existent file path.""" + non_existent_file = Path("non_existent_file.jpg") + result = runner.invoke(app, ["keywords", str(non_existent_file)]) + + assert result.exit_code == 1 + assert f"Error: File '{non_existent_file}' does not exist." in result.stderr + +def test_keywords_command_error_during_processing(mock_photo_logic, dummy_file): + """Test the 'keywords' command when an exception occurs during processing.""" + # Configure the session mock to raise an exception + mock_photo_logic["session"].call.side_effect = Exception("LLM error") + + result = runner.invoke(app, ["keywords", str(dummy_file)]) + + assert result.exit_code == 1 + assert "Error processing image: LLM error" in result.stderr + +def test_version_command(): + """Test the --version option.""" + result = runner.invoke(app, ["--version"]) + + assert result.exit_code == 0 + assert "photools3 version 0.1.0" in result.stdout