"""Tests for search tools."""
import pytest
import importlib
import sys
from pathlib import Path
# Add tests directory to path for helper import
sys.path.insert(0, str(Path(__file__).parent.parent))
from helpers import get_tool_fn
class TestSearchStandards:
"""Tests for search_standards tool."""
@pytest.mark.asyncio
async def test_search_finds_matching_content(self, mock_config, mock_context, monkeypatch):
"""Search should find documents containing query terms."""
# Reload the module to ensure clean state
from standards_mcp_server.tools import search as search_module
importlib.reload(search_module)
monkeypatch.setattr(search_module, "get_config", lambda: mock_config)
results = await get_tool_fn(search_module.search_standards)(
query="authentication",
ctx=mock_context
)
assert results["total"] > 0
assert any("security" in r["uri"] for r in results["results"])
@pytest.mark.asyncio
async def test_search_with_category_filter(self, mock_config, mock_context, monkeypatch):
"""Search with category filter should only search that category."""
from standards_mcp_server.tools import search as search_module
importlib.reload(search_module)
monkeypatch.setattr(search_module, "get_config", lambda: mock_config)
results = await get_tool_fn(search_module.search_standards)(
query="standards",
category="agents",
ctx=mock_context
)
# All results should be from agents category
for result in results["results"]:
assert "agents" in result["uri"]
@pytest.mark.asyncio
async def test_search_respects_max_results(self, mock_config, mock_context, monkeypatch):
"""Search should respect max_results limit."""
from standards_mcp_server.tools import search as search_module
importlib.reload(search_module)
monkeypatch.setattr(search_module, "get_config", lambda: mock_config)
results = await get_tool_fn(search_module.search_standards)(
query="the", # Common word, should match multiple docs
max_results=1,
ctx=mock_context
)
assert len(results["results"]) <= 1
@pytest.mark.asyncio
async def test_search_returns_excerpts(self, mock_config, mock_context, monkeypatch):
"""Search results should include relevant excerpts."""
from standards_mcp_server.tools import search as search_module
importlib.reload(search_module)
monkeypatch.setattr(search_module, "get_config", lambda: mock_config)
results = await get_tool_fn(search_module.search_standards)(
query="architecture",
ctx=mock_context
)
if results["total"] > 0:
first_result = results["results"][0]
assert "excerpt" in first_result
assert len(first_result["excerpt"]) > 0
class TestListStandardsCategories:
"""Tests for list_standards_categories tool."""
@pytest.mark.asyncio
async def test_lists_all_categories(self, mock_config, mock_context, monkeypatch):
"""Should list all top-level categories."""
from standards_mcp_server.tools import search as search_module
importlib.reload(search_module)
monkeypatch.setattr(search_module, "get_config", lambda: mock_config)
result = await get_tool_fn(search_module.list_standards_categories)(ctx=mock_context)
assert "categories" in result
category_names = [c["name"] for c in result["categories"]]
assert "agents" in category_names
assert "mcp" in category_names
@pytest.mark.asyncio
async def test_includes_document_counts(self, mock_config, mock_context, monkeypatch):
"""Categories should include document counts."""
from standards_mcp_server.tools import search as search_module
importlib.reload(search_module)
monkeypatch.setattr(search_module, "get_config", lambda: mock_config)
result = await get_tool_fn(search_module.list_standards_categories)(ctx=mock_context)
for category in result["categories"]:
assert "document_count" in category
assert category["document_count"] >= 0
class TestGetStandardsSummary:
"""Tests for get_standards_summary tool."""
@pytest.mark.asyncio
async def test_gets_category_summary(self, mock_config, mock_context, monkeypatch):
"""Should get summary of documents in category."""
from standards_mcp_server.tools import search as search_module
importlib.reload(search_module)
monkeypatch.setattr(search_module, "get_config", lambda: mock_config)
result = await get_tool_fn(search_module.get_standards_summary)(
category="agents",
ctx=mock_context
)
assert result["category"] == "agents"
assert "documents" in result
assert len(result["documents"]) > 0
@pytest.mark.asyncio
async def test_documents_have_required_fields(self, mock_config, mock_context, monkeypatch):
"""Each document should have uri, title, filename."""
from standards_mcp_server.tools import search as search_module
importlib.reload(search_module)
monkeypatch.setattr(search_module, "get_config", lambda: mock_config)
result = await get_tool_fn(search_module.get_standards_summary)(
category="agents",
ctx=mock_context
)
for doc in result["documents"]:
assert "uri" in doc
assert "title" in doc
assert "filename" in doc
@pytest.mark.asyncio
async def test_invalid_category_returns_error(self, mock_config, mock_context, monkeypatch):
"""Invalid category should return error."""
from standards_mcp_server.tools import search as search_module
importlib.reload(search_module)
monkeypatch.setattr(search_module, "get_config", lambda: mock_config)
result = await get_tool_fn(search_module.get_standards_summary)(
category="nonexistent",
ctx=mock_context
)
assert "error" in result