This commit is contained in:
140
tests/test_github_client.py
Normal file
140
tests/test_github_client.py
Normal file
@@ -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()
|
||||
Reference in New Issue
Block a user