Files
wehub-resource-sync 7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

728 lines
24 KiB
Python

"""
Comprehensive tests for the GitHub search engine.
Tests initialization, search functionality, and API configuration.
"""
import base64
import pytest
from unittest.mock import Mock, patch
class TestGitHubSearchEngineInit:
"""Tests for GitHub search engine initialization."""
def test_init_default_parameters(self):
"""Test initialization with default parameters."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
assert engine.max_results >= 10
# Default search type is repositories
assert engine.search_type == "repositories"
assert engine.api_key is None
def test_init_with_api_key(self):
"""Test initialization with GitHub API key."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(api_key="ghp_test_token_123")
assert engine.api_key == "ghp_test_token_123"
def test_init_with_search_type(self):
"""Test initialization with specific search type."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(search_type="code")
assert engine.search_type == "code"
def test_init_with_custom_max_results(self):
"""Test initialization with custom max results."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(max_results=50)
assert engine.max_results >= 50
class TestGitHubSearchExecution:
"""Tests for GitHub search execution."""
@pytest.fixture
def github_engine(self):
"""Create a GitHub engine instance."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
return GitHubSearchEngine(max_results=10)
def test_engine_initialization(self, github_engine):
"""Test that engine is properly initialized."""
assert github_engine is not None
assert github_engine.max_results >= 10
def test_engine_has_api_base(self, github_engine):
"""Test that engine has API base URL configured."""
assert hasattr(github_engine, "api_base")
assert "api.github.com" in github_engine.api_base
class TestGitHubAPIConfiguration:
"""Tests for GitHub API configuration."""
def test_api_key_in_headers(self):
"""Test that API key is included in headers when provided."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(api_key="ghp_my_token")
assert engine.api_key == "ghp_my_token"
# Check that Authorization header is set
assert "Authorization" in engine.headers
assert "ghp_my_token" in engine.headers["Authorization"]
def test_no_api_key_anonymous_access(self):
"""Test that engine works without API key (anonymous access)."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
assert engine.api_key is None
# Authorization header should not be present without API key
assert "Authorization" not in engine.headers
class TestGitHubSearchTypes:
"""Tests for different GitHub search types."""
def test_repository_search_type(self):
"""Test repository search type configuration."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(search_type="repositories")
assert engine.search_type == "repositories"
def test_code_search_type(self):
"""Test code search type configuration."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(search_type="code")
assert engine.search_type == "code"
def test_issues_search_type(self):
"""Test issues search type configuration."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(search_type="issues")
assert engine.search_type == "issues"
def test_users_search_type(self):
"""Test users search type configuration."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(search_type="users")
assert engine.search_type == "users"
class TestGitHubEngineType:
"""Tests for GitHub engine type identification."""
def test_engine_type_set(self):
"""Test that engine type is properly set."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
assert "github" in engine.engine_type.lower()
class TestGitHubHeaders:
"""Tests for GitHub request headers."""
def test_accept_header_set(self):
"""Test that Accept header is set for API compatibility."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
assert "Accept" in engine.headers
assert "application/vnd.github" in engine.headers["Accept"]
def test_user_agent_header_set(self):
"""Test that User-Agent header is set."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
assert "User-Agent" in engine.headers
class TestGitHubAdvancedInit:
"""Tests for advanced initialization options."""
def test_init_with_readme_option(self):
"""Test initialization with include_readme option."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(include_readme=False)
assert engine.include_readme is False
def test_init_with_issues_option(self):
"""Test initialization with include_issues option."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(include_issues=True)
assert engine.include_issues is True
def test_init_with_llm(self):
"""Test initialization with LLM."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
mock_llm = Mock()
engine = GitHubSearchEngine(llm=mock_llm)
assert engine.llm is mock_llm
class TestGitHubRateLimits:
"""Tests for rate limit handling."""
def test_handle_rate_limits_normal(self):
"""Test rate limit handling with normal remaining."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
mock_response = Mock()
mock_response.headers = {
"X-RateLimit-Remaining": "50",
"X-RateLimit-Reset": "0",
}
# Should not raise or sleep
engine._handle_rate_limits(mock_response)
def test_handle_rate_limits_low_remaining(self):
"""Test rate limit handling with low remaining requests."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
mock_response = Mock()
mock_response.headers = {
"X-RateLimit-Remaining": "3",
"X-RateLimit-Reset": "0",
}
# Should log warning but not sleep
engine._handle_rate_limits(mock_response)
class TestGitHubOptimizeQuery:
"""Tests for query optimization."""
def test_optimize_query_without_llm(self):
"""Test query optimization returns original without LLM."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(llm=None)
# Patch the config getter to return None
with patch(
"local_deep_research.web_search_engines.engines.search_engine_github.llm_config.get_llm",
return_value=None,
):
result = engine._optimize_github_query("python web framework")
assert result == "python web framework"
def test_optimize_query_with_llm(self):
"""Test query optimization with LLM."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
mock_llm = Mock()
mock_llm.invoke.return_value = Mock(
content="python web framework stars:>100"
)
engine = GitHubSearchEngine(llm=mock_llm)
result = engine._optimize_github_query("python web framework")
assert "python" in result.lower()
mock_llm.invoke.assert_called_once()
def test_optimize_query_handles_error(self):
"""Test query optimization handles LLM errors gracefully."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
mock_llm = Mock()
mock_llm.invoke.side_effect = Exception("LLM error")
engine = GitHubSearchEngine(llm=mock_llm)
result = engine._optimize_github_query("test query")
# Should fall back to original query
assert result == "test query"
def test_optimize_query_handles_empty_response(self):
"""Test query optimization handles empty LLM response."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
mock_llm = Mock()
mock_llm.invoke.return_value = Mock(content="")
engine = GitHubSearchEngine(llm=mock_llm)
result = engine._optimize_github_query("test query")
# Should fall back to original query
assert result == "test query"
class TestGitHubSearchGithub:
"""Tests for _search_github method."""
def test_search_github_success(self):
"""Test successful GitHub search."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(llm=None)
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {
"total_count": 2,
"items": [
{"id": 1, "full_name": "owner/repo1"},
{"id": 2, "full_name": "owner/repo2"},
],
}
mock_response.headers = {
"X-RateLimit-Remaining": "50",
"X-RateLimit-Reset": "0",
}
with patch(
"local_deep_research.web_search_engines.engines.search_engine_github.llm_config.get_llm",
return_value=None,
):
with patch(
"local_deep_research.web_search_engines.engines.search_engine_github.safe_get",
return_value=mock_response,
):
result = engine._search_github("python")
assert len(result) == 2
assert result[0]["full_name"] == "owner/repo1"
def test_search_github_handles_error(self):
"""Test search handles API errors."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(llm=None)
with patch(
"local_deep_research.web_search_engines.engines.search_engine_github.llm_config.get_llm",
return_value=None,
):
with patch(
"local_deep_research.web_search_engines.engines.search_engine_github.safe_get",
side_effect=Exception("API error"),
):
result = engine._search_github("test query")
assert result == []
def test_search_github_handles_non_200_response(self):
"""Test search handles non-200 responses."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(llm=None)
mock_response = Mock()
mock_response.status_code = 403
mock_response.text = "Rate limit exceeded"
mock_response.headers = {
"X-RateLimit-Remaining": "0",
"X-RateLimit-Reset": "0",
}
with patch(
"local_deep_research.web_search_engines.engines.search_engine_github.llm_config.get_llm",
return_value=None,
):
with patch(
"local_deep_research.web_search_engines.engines.search_engine_github.safe_get",
return_value=mock_response,
):
result = engine._search_github("test")
assert result == []
class TestGitHubGetReadmeContent:
"""Tests for _get_readme_content method."""
def test_get_readme_success(self):
"""Test successful README retrieval."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
readme_content = "# Test README\nThis is a test."
encoded_content = base64.b64encode(readme_content.encode()).decode()
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {
"content": encoded_content,
"encoding": "base64",
}
mock_response.headers = {
"X-RateLimit-Remaining": "50",
"X-RateLimit-Reset": "0",
}
with patch(
"local_deep_research.web_search_engines.engines.search_engine_github.safe_get",
return_value=mock_response,
):
result = engine._get_readme_content("owner/repo")
assert "Test README" in result
def test_get_readme_not_found(self):
"""Test README not found."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
mock_response = Mock()
mock_response.status_code = 404
mock_response.headers = {
"X-RateLimit-Remaining": "50",
"X-RateLimit-Reset": "0",
}
with patch(
"local_deep_research.web_search_engines.engines.search_engine_github.safe_get",
return_value=mock_response,
):
result = engine._get_readme_content("owner/repo")
assert result == ""
def test_get_readme_handles_error(self):
"""Test README retrieval handles errors."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
with patch(
"local_deep_research.web_search_engines.engines.search_engine_github.safe_get",
side_effect=Exception("Network error"),
):
result = engine._get_readme_content("owner/repo")
assert result == ""
class TestGitHubGetRecentIssues:
"""Tests for _get_recent_issues method."""
def test_get_issues_success(self):
"""Test successful issues retrieval."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
mock_issues = [
{"number": 1, "title": "Issue 1"},
{"number": 2, "title": "Issue 2"},
]
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = mock_issues
mock_response.headers = {
"X-RateLimit-Remaining": "50",
"X-RateLimit-Reset": "0",
}
with patch(
"local_deep_research.web_search_engines.engines.search_engine_github.safe_get",
return_value=mock_response,
):
result = engine._get_recent_issues("owner/repo", limit=5)
assert len(result) == 2
assert result[0]["title"] == "Issue 1"
def test_get_issues_not_found(self):
"""Test issues not found."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
mock_response = Mock()
mock_response.status_code = 404
mock_response.headers = {
"X-RateLimit-Remaining": "50",
"X-RateLimit-Reset": "0",
}
with patch(
"local_deep_research.web_search_engines.engines.search_engine_github.safe_get",
return_value=mock_response,
):
result = engine._get_recent_issues("owner/repo")
assert result == []
class TestGitHubFormatPreviews:
"""Tests for preview formatting methods."""
def test_format_repository_preview(self):
"""Test repository preview formatting."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
repo = {
"id": 123,
"full_name": "owner/repo",
"html_url": "https://github.com/owner/repo",
"description": "Test description",
"stargazers_count": 100,
"forks_count": 10,
"language": "Python",
"owner": {"login": "owner"},
}
preview = engine._format_repository_preview(repo)
assert preview["title"] == "owner/repo"
assert preview["stars"] == 100
assert preview["language"] == "Python"
assert preview["search_type"] == "repository"
def test_format_code_preview(self):
"""Test code preview formatting."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
code = {
"sha": "abc123",
"name": "test.py",
"path": "src/test.py",
"html_url": "https://github.com/owner/repo/blob/main/test.py",
"repository": {
"full_name": "owner/repo",
"html_url": "https://github.com/owner/repo",
},
}
preview = engine._format_code_preview(code)
assert "test.py" in preview["title"]
assert preview["path"] == "src/test.py"
assert preview["search_type"] == "code"
def test_format_issue_preview(self):
"""Test issue preview formatting."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
issue = {
"number": 42,
"title": "Bug report",
"html_url": "https://github.com/owner/repo/issues/42",
"body": "This is a bug description",
"state": "open",
"user": {"login": "reporter"},
"comments": 5,
}
preview = engine._format_issue_preview(issue)
assert preview["title"] == "Bug report"
assert preview["state"] == "open"
assert preview["search_type"] == "issue"
def test_format_user_preview(self):
"""Test user preview formatting."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine()
user = {
"id": 1,
"login": "testuser",
"html_url": "https://github.com/testuser",
"bio": "Test bio",
"followers": 100,
"public_repos": 50,
}
preview = engine._format_user_preview(user)
assert preview["title"] == "testuser"
assert preview["followers"] == 100
assert preview["search_type"] == "user"
class TestGitHubGetPreviews:
"""Tests for _get_previews method."""
def test_get_previews_repository(self):
"""Test getting repository previews."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(search_type="repositories", llm=None)
mock_results = [
{
"id": 123,
"full_name": "owner/repo",
"html_url": "https://github.com/owner/repo",
"description": "Test repo",
"stargazers_count": 100,
"forks_count": 10,
"owner": {"login": "owner"},
}
]
with patch.object(engine, "_search_github", return_value=mock_results):
previews = engine._get_previews("python")
assert len(previews) == 1
assert previews[0]["search_type"] == "repository"
def test_get_previews_code(self):
"""Test getting code previews."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(search_type="code", llm=None)
mock_results = [
{
"sha": "abc123",
"name": "test.py",
"path": "src/test.py",
"html_url": "https://github.com/owner/repo/blob/main/test.py",
"repository": {"full_name": "owner/repo"},
}
]
with patch.object(engine, "_search_github", return_value=mock_results):
previews = engine._get_previews("function")
assert len(previews) == 1
assert previews[0]["search_type"] == "code"
def test_get_previews_no_results(self):
"""Test getting previews with no results."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(llm=None)
with patch.object(engine, "_search_github", return_value=[]):
previews = engine._get_previews("nonexistent")
assert previews == []
def test_get_previews_contribution_query(self):
"""Test getting previews for contribution-focused queries."""
from local_deep_research.web_search_engines.engines.search_engine_github import (
GitHubSearchEngine,
)
engine = GitHubSearchEngine(search_type="issues", llm=None)
mock_results = [
{
"id": 123,
"full_name": "owner/repo",
"html_url": "https://github.com/owner/repo",
"description": "Good for beginners",
"stargazers_count": 500,
"forks_count": 50,
"owner": {"login": "owner"},
}
]
with patch.object(engine, "_search_github", return_value=mock_results):
previews = engine._get_previews(
"beginner python projects to contribute"
)
# Should have adjusted search type
assert len(previews) == 1