"""Tests for CLI entry point.""" from unittest.mock import MagicMock, patch import pytest import requests from gitea_dashboard.cli import main class TestMainNominal: """Test main() happy path.""" @patch("gitea_dashboard.cli.render_dashboard") @patch("gitea_dashboard.cli.collect_all") @patch("gitea_dashboard.cli.GiteaClient") def test_main_runs_full_pipeline(self, mock_client_cls, mock_collect, mock_render): """main() creates client, collects, and renders.""" env = {"GITEA_TOKEN": "test-token-123", "GITEA_URL": "http://localhost:3000"} mock_client = MagicMock() mock_client_cls.return_value = mock_client mock_collect.return_value = [] with patch.dict("os.environ", env, clear=False): main() mock_client_cls.assert_called_once_with("http://localhost:3000", "test-token-123") mock_collect.assert_called_once_with(mock_client) mock_render.assert_called_once_with(mock_collect.return_value) @patch("gitea_dashboard.cli.render_dashboard") @patch("gitea_dashboard.cli.collect_all") @patch("gitea_dashboard.cli.GiteaClient") def test_main_uses_default_url(self, mock_client_cls, mock_collect, mock_render): """main() uses default URL when GITEA_URL is not set.""" env = {"GITEA_TOKEN": "my-token"} mock_client_cls.return_value = MagicMock() mock_collect.return_value = [] with patch.dict("os.environ", env, clear=True): main() mock_client_cls.assert_called_once_with("http://192.168.0.106:3000", "my-token") class TestMainMissingToken: """Test main() when GITEA_TOKEN is not set.""" def test_exits_when_token_missing(self): """main() exits with SystemExit when GITEA_TOKEN is absent.""" with patch.dict("os.environ", {}, clear=True): with pytest.raises(SystemExit): main() def test_error_message_when_token_missing(self, capsys): """main() prints a clear error message about missing token.""" with patch.dict("os.environ", {}, clear=True): with pytest.raises(SystemExit): main() class TestMainConnectionErrors: """Test main() error handling for network issues.""" @patch("gitea_dashboard.cli.collect_all") @patch("gitea_dashboard.cli.GiteaClient") def test_connection_error_handled(self, mock_client_cls, mock_collect): """ConnectionError is caught and does not crash.""" env = {"GITEA_TOKEN": "test-token"} mock_client_cls.return_value = MagicMock() mock_collect.side_effect = requests.ConnectionError("Connection refused") with patch.dict("os.environ", env, clear=True): # Should not raise — error is handled gracefully main() @patch("gitea_dashboard.cli.collect_all") @patch("gitea_dashboard.cli.GiteaClient") def test_timeout_error_handled(self, mock_client_cls, mock_collect): """Timeout is caught and does not crash.""" env = {"GITEA_TOKEN": "test-token"} mock_client_cls.return_value = MagicMock() mock_collect.side_effect = requests.Timeout("Request timed out") with patch.dict("os.environ", env, clear=True): main() @patch("gitea_dashboard.cli.collect_all") @patch("gitea_dashboard.cli.GiteaClient") def test_request_exception_handled(self, mock_client_cls, mock_collect): """Generic RequestException is caught and does not crash.""" env = {"GITEA_TOKEN": "test-token"} mock_client_cls.return_value = MagicMock() mock_collect.side_effect = requests.RequestException("Something went wrong") with patch.dict("os.environ", env, clear=True): main() @patch("gitea_dashboard.cli.collect_all") @patch("gitea_dashboard.cli.GiteaClient") def test_token_not_in_error_output(self, mock_client_cls, mock_collect, capsys): """Token must never appear in error messages.""" env = {"GITEA_TOKEN": "super-secret-token-xyz"} mock_client_cls.return_value = MagicMock() mock_collect.side_effect = requests.ConnectionError("Connection refused") with patch.dict("os.environ", env, clear=True): main() captured = capsys.readouterr() assert "super-secret-token-xyz" not in captured.out assert "super-secret-token-xyz" not in captured.err