Skip to main content
Glama
aserper

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

by aserper
test_zig.py6.01 kB
"""Tests for Zig provider.""" from unittest.mock import AsyncMock, MagicMock import httpx import pytest from bs4 import BeautifulSoup from src.RTFD.providers.zig import ZigProvider from src.RTFD.utils import create_http_client @pytest.fixture def provider(): """Create a Zig provider instance.""" return ZigProvider(create_http_client) @pytest.fixture def mock_html_content(): """Return mock HTML content for Zig documentation.""" return """ <html> <body> <h1>Zig Documentation</h1> <p>Welcome to Zig docs.</p> <h2>Installation</h2> <p>How to install Zig.</p> <h2>Language Reference</h2> <p>Details about the language.</p> <h3>Variables</h3> <p>const and var keywords.</p> <h3>Functions</h3> <p>fn keyword usage.</p> </body> </html> """ def test_zig_metadata(provider): """Test Zig provider metadata.""" metadata = provider.get_metadata() assert metadata.name == "zig" assert metadata.supports_library_search is False assert "zig_docs" in metadata.tool_names @pytest.mark.asyncio async def test_zig_search_library_not_supported(provider): """Test that search_library returns failure as it's not supported.""" result = await provider.search_library("anything") assert result.success is False assert "not support" in result.error @pytest.mark.asyncio async def test_zig_docs_search_success(provider, mock_html_content): """Test successful search in Zig docs.""" # Mock HTTP client response mock_response = MagicMock() mock_response.text = mock_html_content mock_response.raise_for_status.return_value = None mock_client = AsyncMock() mock_client.get.return_value = mock_response mock_client.__aenter__.return_value = mock_client mock_client.__aexit__.return_value = None # The factory needs to return an awaitable that yields the client # In base.py: return await self._http_client_factory() async def mock_factory(): return mock_client provider = ZigProvider(mock_factory) # Test the internal search method result = await provider._search_zig_docs("variables") # Debug info if fails if "error" in result: print(f"DEBUG: {result['error']}") assert result["query"] == "variables" assert "matches" in result matches = result["matches"] assert len(matches) > 0 assert matches[0]["title"] == "Variables" assert "const and var" in matches[0]["summary"] @pytest.mark.asyncio async def test_zig_docs_search_tool(provider, mock_html_content): """Test the zig_docs tool.""" mock_response = MagicMock() mock_response.text = mock_html_content mock_client = AsyncMock() mock_client.get.return_value = mock_response mock_client.__aenter__.return_value = mock_client mock_client.__aexit__.return_value = None async def mock_factory(): return mock_client provider = ZigProvider(mock_factory) tools = provider.get_tools() assert "zig_docs" in tools # Run the tool result = await tools["zig_docs"]("install") assert result.content[0].type == "text" text = result.content[0].text assert "Installation" in text assert "How to install Zig" in text @pytest.mark.asyncio async def test_zig_docs_http_error(provider): """Test handling of HTTP errors.""" mock_client = AsyncMock() mock_client.get.side_effect = httpx.HTTPStatusError( "404 Not Found", request=None, response=None ) mock_client.__aenter__.return_value = mock_client mock_client.__aexit__.return_value = None async def mock_factory(): return mock_client provider = ZigProvider(mock_factory) result = await provider._search_zig_docs("query") assert "error" in result assert "Failed to fetch" in result["error"] @pytest.mark.asyncio async def test_zig_docs_general_error(provider): """Test handling of general exceptions.""" async def mock_factory(): raise Exception("Something bad") provider = ZigProvider(mock_factory) result = await provider._search_zig_docs("query") assert "error" in result assert "Error searching" in result["error"] def test_extract_doc_sections(provider, mock_html_content): """Test extracting sections from HTML.""" soup = BeautifulSoup(mock_html_content, "html.parser") sections = provider._extract_doc_sections(soup) assert len(sections) == 5 # H1, H2, H2, H3, H3 # Check Installation section install = next(s for s in sections if s["title"] == "Installation") assert install["summary"] == "How to install Zig." # Check Variables section variables = next(s for s in sections if s["title"] == "Variables") assert "const and var" in variables["summary"] def test_search_sections(provider): """Test scoring and sorting of sections.""" sections = [ {"title": "Installation", "summary": "Setup guide"}, {"title": "Variables", "summary": "const var"}, {"title": "Functions", "summary": "fn keyword"}, {"title": "Values", "summary": "const values"}, ] # Search for "var" # Variables: match in title (2 pts) + match in summary (1 pt) = 3 # Values: match in summary? No ("values" != "var")? # Logic is `word in string` or `string.count(word)`? # Code uses `title_lower.count(word)`. "var" is in "variables". matches = provider._search_sections(sections, "var") assert len(matches) > 0 assert matches[0]["title"] == "Variables" # "Values" summary has "values". "values".count("var") -> 0? # "values" contains "v", "a", "l"... no. # But "var" is a substring of "variable". # Wait, code: `title_lower.count(word)`. # "variables".count("var") -> 1. # Check multiple words matches = provider._search_sections(sections, "setup guide") assert matches[0]["title"] == "Installation"

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