From d9a83825f6659d43248c50a35682f7e79a9d132a Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Mon, 2 Feb 2026 18:27:20 +0000 Subject: [PATCH] Initial upload with CI/CD workflow --- tests/test_github_client.py | 140 ++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 tests/test_github_client.py diff --git a/tests/test_github_client.py b/tests/test_github_client.py new file mode 100644 index 0000000..59cc745 --- /dev/null +++ b/tests/test_github_client.py @@ -0,0 +1,140 @@ +"""Tests for the GitHub client.""" + +from unittest.mock import MagicMock, patch +from datetime import datetime + +import pytest +from src.github_client import GitHubClient, RateLimitExceededError + + +class TestGitHubClient: + """Tests for GitHubClient class.""" + + @pytest.fixture + def mock_ghapi(self): + """Create a mock GhApi class.""" + with patch("src.github_client.GhApi") as mock: + yield mock + + @pytest.fixture + def client(self, mock_ghapi): + """Create a GitHub client with mocked API.""" + return GitHubClient(token=None, verbose=False) + + def test_init_without_token(self, client): + """Test initialization without token.""" + assert client.token is None + assert client.verbose is False + assert client.timeout == 30 + + def test_init_with_token(self, mock_ghapi): + """Test initialization with token.""" + client = GitHubClient(token="test_token", verbose=True) + assert client.token == "test_token" + assert client.verbose is True + + def test_search_repositories(self, client, mock_ghapi): + """Test repository search.""" + mock_api_instance = MagicMock() + mock_response = MagicMock() + mock_response.get.return_value = {"items": [{"full_name": "test/repo"}]} + mock_response.headers = {"X-RateLimit-Remaining": "60"} + mock_api_instance.search.repos.return_value = mock_response + mock_ghapi.return_value = mock_api_instance + + result = client.search_repositories( + language="python", + stars_min=100, + per_page=5, + ) + + assert len(result) == 1 + mock_api_instance.search.repos.assert_called_once() + + def test_search_repositories_with_query(self, client, mock_ghapi): + """Test repository search with custom query.""" + mock_api_instance = MagicMock() + mock_response = MagicMock() + mock_response.get.return_value = {"items": []} + mock_response.headers = {"X-RateLimit-Remaining": "60"} + mock_api_instance.search.repos.return_value = mock_response + mock_ghapi.return_value = mock_api_instance + + client.search_repositories( + query="machine learning", + language="python", + stars_min=50, + stars_max=500, + per_page=10, + ) + + mock_api_instance.search.repos.assert_called_once() + call_args = mock_api_instance.search.repos.call_args + assert "machine learning" in call_args[1]["q"] + assert "language:python" in call_args[1]["q"] + + def test_get_file_tree(self, client, mock_ghapi): + """Test getting file tree.""" + mock_api_instance = MagicMock() + mock_response = MagicMock() + mock_response.truncated = False + mock_response.tree = [ + {"path": "src/main.py", "type": "blob"}, + {"path": "README.md", "type": "blob"}, + ] + mock_response.headers = {"X-RateLimit-Remaining": "60"} + mock_api_instance.git_trees.get.return_value = mock_response + mock_ghapi.return_value = mock_api_instance + + result = client.get_file_tree("owner", "repo") + + assert len(result) == 2 + assert result[0]["path"] == "src/main.py" + + def test_get_file_content(self, client, mock_ghapi): + """Test getting file content.""" + import base64 + + mock_api_instance = MagicMock() + mock_response = { + "encoding": "base64", + "content": base64.b64encode(b"print('hello')").decode(), + } + mock_api_instance.repos.get_content.return_value = mock_response + mock_ghapi.return_value = mock_api_instance + + result = client.get_file_content("owner", "repo", "main.py") + + assert result == "print('hello')" + + def test_get_file_content_not_base64(self, client, mock_ghapi): + """Test getting file content when not base64 encoded.""" + mock_api_instance = MagicMock() + mock_response = {"encoding": "utf-8"} + mock_api_instance.repos.get_content.return_value = mock_response + mock_ghapi.return_value = mock_api_instance + + result = client.get_file_content("owner", "repo", "main.py") + + assert result is None + + +class TestRateLimitExceededError: + """Tests for RateLimitExceededError class.""" + + def test_error_creation(self): + """Test creating rate limit error.""" + reset_time = datetime.now() + error = RateLimitExceededError( + reset_time=reset_time, + message="Custom message", + ) + + assert error.reset_time == reset_time + assert error.message == "Custom message" + + def test_error_default_message(self): + """Test error with default message.""" + error = RateLimitExceededError(reset_time=None) + + assert "rate limit" in error.message.lower()