Skip to main content
Glama
aserper

RTFD (Read The F*****g Docs)

by aserper
test_github.py10.5 kB
"""Tests for GitHub provider.""" import pytest from src.RTFD.providers.github import GitHubProvider from src.RTFD.utils import create_http_client @pytest.fixture def provider(): """Create a GitHub provider instance.""" return GitHubProvider(create_http_client) def test_github_metadata(): """Test GitHub provider metadata.""" provider = GitHubProvider(lambda: None) metadata = provider.get_metadata() assert metadata.name == "github" assert metadata.expose_as_tool is True assert "github_repo_search" in metadata.tool_names assert "github_code_search" in metadata.tool_names assert metadata.supports_library_search is True def test_github_get_tools(): """Test that GitHub provider provides correct tools.""" provider = GitHubProvider(lambda: None) tools = provider.get_tools() assert "github_repo_search" in tools assert "github_code_search" in tools assert callable(tools["github_repo_search"]) assert callable(tools["github_code_search"]) @pytest.mark.asyncio async def test_github_search_repos_success(provider): """Test repository search on GitHub (may fail due to rate limits).""" try: result = await provider._search_repos("python requests", limit=2) assert isinstance(result, list) assert len(result) <= 2 for repo in result: assert "name" in repo assert "description" in repo assert "stars" in repo assert "url" in repo assert "default_branch" in repo except Exception as e: # May fail due to rate limits without GITHUB_TOKEN assert "403" in str(e) or "rate limit" in str(e).lower() @pytest.mark.asyncio async def test_github_search_library_success(provider): """Test library search integration (may fail due to rate limits).""" result = await provider.search_library("requests", limit=2) # May fail due to rate limits without GITHUB_TOKEN if not result.success: assert result.error is not None assert "rate limit" in result.error.lower() or "403" in result.error else: assert result.data is not None assert result.provider_name == "github" assert isinstance(result.data, list) @pytest.mark.asyncio async def test_github_search_code_success(provider): """Test code search on GitHub (may fail without auth).""" # GitHub code search requires authentication # This test verifies the method exists and handles errors gracefully try: result = await provider._search_code("def hello", limit=2) assert isinstance(result, list) for hit in result: assert "name" in hit assert "path" in hit assert "repository" in hit assert "url" in hit except Exception as e: # Expected: 401 Unauthorized without GITHUB_TOKEN # Also handle 403 Rate Limit which can happen in shared environments error_str = str(e) assert any(x in error_str for x in ["401", "Unauthorized", "403", "rate limit"]) @pytest.mark.asyncio async def test_github_search_code_with_repo(provider): """Test code search scoped to a repository.""" # GitHub code search requires authentication try: result = await provider._search_code("function", repo="psf/requests", limit=2) assert isinstance(result, list) except Exception: # Expected: authentication required pass @pytest.mark.asyncio async def test_github_repo_search_tool(provider): """Test the github_repo_search tool directly (may fail due to rate limits).""" tools = provider.get_tools() tool = tools["github_repo_search"] try: result = await tool("python requests", limit=2) assert result.content[0].type == "text" text_content = result.content[0].text assert isinstance(text_content, str) assert "[" in text_content # JSON array format except Exception as e: # May fail due to rate limits without GITHUB_TOKEN assert "403" in str(e) or "rate limit" in str(e).lower() @pytest.mark.asyncio async def test_github_code_search_tool(provider): """Test the github_code_search tool directly.""" tools = provider.get_tools() tool = tools["github_code_search"] try: result = await tool("def main", limit=2) assert result.content[0].type == "text" text_content = result.content[0].text assert isinstance(text_content, str) except Exception as e: # GitHub code search requires authentication error_str = str(e) assert any(x in error_str for x in ["401", "Unauthorized", "403", "rate limit"]) @pytest.mark.asyncio async def test_list_repo_contents_root(provider): """Test listing repository root contents.""" try: result = await provider._list_repo_contents("psf", "requests", "") assert "repository" in result assert result["repository"] == "psf/requests" assert "contents" in result assert isinstance(result["contents"], list) # Root should have some files/dirs if len(result["contents"]) > 0: item = result["contents"][0] assert "name" in item assert "path" in item assert "type" in item except Exception as e: # May fail due to rate limits assert "403" in str(e) or "rate limit" in str(e).lower() @pytest.mark.asyncio async def test_list_repo_contents_subdirectory(provider): """Test listing a subdirectory in a repository.""" try: result = await provider._list_repo_contents("psf", "requests", "requests") assert "repository" in result assert "contents" in result assert isinstance(result["contents"], list) except Exception as e: # May fail due to rate limits or if path doesn't exist assert "40" in str(e) or "rate limit" in str(e).lower() @pytest.mark.asyncio async def test_get_file_content_success(provider): """Test getting file content from a repository.""" try: result = await provider._get_file_content("psf", "requests", "README.md") assert "repository" in result assert result["repository"] == "psf/requests" assert "path" in result assert result["path"] == "README.md" assert "content" in result # If no error, content should be non-empty if "error" not in result: assert len(result["content"]) > 0 assert "size_bytes" in result except Exception as e: # May fail due to rate limits assert "403" in str(e) or "rate limit" in str(e).lower() @pytest.mark.asyncio async def test_get_file_content_not_a_file(provider): """Test error handling when path is a directory.""" try: result = await provider._get_file_content("psf", "requests", "requests") # Should return error indicating it's not a file assert "error" in result assert "dir" in result["error"].lower() or "not a file" in result["error"].lower() except Exception: # May fail due to rate limits pass @pytest.mark.asyncio async def test_get_repo_tree_non_recursive(provider): """Test getting repository tree non-recursively.""" try: result = await provider._get_repo_tree("psf", "requests", recursive=False) assert "repository" in result assert result["repository"] == "psf/requests" assert "tree" in result assert isinstance(result["tree"], list) assert "branch" in result # Non-recursive should have fewer items than recursive assert len(result["tree"]) < 1000 except Exception as e: # May fail due to rate limits assert "403" in str(e) or "rate limit" in str(e).lower() @pytest.mark.asyncio async def test_get_repo_tree_recursive(provider): """Test getting full repository tree recursively.""" try: result = await provider._get_repo_tree("psf", "requests", recursive=True, max_items=100) assert "repository" in result assert "tree" in result assert isinstance(result["tree"], list) # Recursive should include nested files if len(result["tree"]) > 0: item = result["tree"][0] assert "path" in item assert "type" in item except Exception as e: # May fail due to rate limits assert "403" in str(e) or "rate limit" in str(e).lower() @pytest.mark.asyncio async def test_list_repo_contents_tool(provider): """Test the list_repo_contents tool.""" tools = provider.get_tools() # Tool should only be available when fetch is enabled if "list_repo_contents" not in tools: pytest.skip("list_repo_contents tool not enabled (fetch disabled)") tool = tools["list_repo_contents"] try: result = await tool("psf/requests", "") assert result.content[0].type == "text" text_content = result.content[0].text assert isinstance(text_content, str) assert "psf/requests" in text_content except Exception as e: # May fail due to rate limits assert "403" in str(e) or "rate limit" in str(e).lower() @pytest.mark.asyncio async def test_get_file_content_tool(provider): """Test the get_file_content tool.""" tools = provider.get_tools() if "get_file_content" not in tools: pytest.skip("get_file_content tool not enabled (fetch disabled)") tool = tools["get_file_content"] try: result = await tool("psf/requests", "README.md") assert result.content[0].type == "text" text_content = result.content[0].text assert isinstance(text_content, str) except Exception as e: # May fail due to rate limits assert "403" in str(e) or "rate limit" in str(e).lower() @pytest.mark.asyncio async def test_get_repo_tree_tool(provider): """Test the get_repo_tree tool.""" tools = provider.get_tools() if "get_repo_tree" not in tools: pytest.skip("get_repo_tree tool not enabled (fetch disabled)") tool = tools["get_repo_tree"] try: result = await tool("psf/requests", recursive=False, max_items=50) assert result.content[0].type == "text" text_content = result.content[0].text assert isinstance(text_content, str) assert "psf/requests" in text_content except Exception as e: # May fail due to rate limits assert "403" in str(e) or "rate limit" in str(e).lower()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/aserper/RTFD'

If you have feedback or need assistance with the MCP directory API, please join our Discord server