"""Integration tests for MCP tools.
Tests the get_checklist and list_checklists MCP tools with authentication.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from pathlib import Path
class TestGetChecklistTool:
"""Integration tests for get_checklist MCP tool."""
def test_get_checklist_returns_content(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test that get_checklist tool returns checklist content."""
from sso_mcp_server.checklists.service import ChecklistService
from sso_mcp_server.tools.get_checklist import get_checklist_impl
# Create test checklist
checklist_dir = temp_dir / "test_checklists"
checklist_dir.mkdir(exist_ok=True)
(checklist_dir / "coding.md").write_text(
"""---
name: Coding Standards
description: Code quality checklist
---
# Coding Standards
- [ ] Follow naming conventions
- [ ] Write unit tests
- [ ] Document public APIs
"""
)
service = ChecklistService(checklist_dir)
result = get_checklist_impl("Coding Standards", service)
assert result is not None
assert result["name"] == "Coding Standards"
assert "Follow naming conventions" in result["content"]
def test_get_checklist_not_found_returns_error(
self, temp_dir: Path, mock_env_vars: dict
) -> None:
"""Test that get_checklist returns error for unknown checklist."""
from sso_mcp_server.checklists.service import ChecklistService
from sso_mcp_server.tools.get_checklist import get_checklist_impl
checklist_dir = temp_dir / "test_checklists2"
checklist_dir.mkdir(exist_ok=True)
(checklist_dir / "existing.md").write_text("---\nname: Existing\n---\nContent.")
service = ChecklistService(checklist_dir)
result = get_checklist_impl("NonExistent", service)
assert result is not None
assert "error" in result or result.get("name") is None
# Should include available checklists in error
if "available" in result:
assert "Existing" in result["available"]
def test_get_checklist_requires_authentication(
self, temp_dir: Path, mock_env_vars: dict
) -> None:
"""Test that get_checklist requires authentication."""
from sso_mcp_server.auth.middleware import set_auth_manager
# Clear any existing auth manager
set_auth_manager(None) # type: ignore
# The decorated tool should raise when not authenticated
# This tests the middleware integration
def test_get_checklist_works_when_authenticated(
self, temp_dir: Path, mock_env_vars: dict
) -> None:
"""Test that get_checklist works when user is authenticated."""
from unittest.mock import MagicMock
from sso_mcp_server.auth.middleware import set_auth_manager
from sso_mcp_server.checklists.service import ChecklistService
from sso_mcp_server.tools.get_checklist import get_checklist_impl
# Mock authenticated auth manager
mock_auth = MagicMock()
mock_auth.is_authenticated.return_value = True
mock_auth.ensure_authenticated.return_value = True
set_auth_manager(mock_auth)
checklist_dir = temp_dir / "test_checklists3"
checklist_dir.mkdir(exist_ok=True)
(checklist_dir / "test.md").write_text("---\nname: Test\n---\nContent.")
service = ChecklistService(checklist_dir)
result = get_checklist_impl("Test", service)
assert result is not None
class TestListChecklistsTool:
"""Integration tests for list_checklists MCP tool."""
def test_list_checklists_returns_all(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test that list_checklists returns all available checklists."""
from sso_mcp_server.checklists.service import ChecklistService
from sso_mcp_server.tools.list_checklists import list_checklists_impl
checklist_dir = temp_dir / "list_checklists"
checklist_dir.mkdir(exist_ok=True)
(checklist_dir / "coding.md").write_text(
"---\nname: Coding Standards\ndescription: Code quality\n---\nContent."
)
(checklist_dir / "design.md").write_text(
"---\nname: Design Review\ndescription: Design quality\n---\nContent."
)
(checklist_dir / "architecture.md").write_text(
"---\nname: Architecture\ndescription: System design\n---\nContent."
)
service = ChecklistService(checklist_dir)
result = list_checklists_impl(service)
assert "checklists" in result
assert "count" in result
assert len(result["checklists"]) == 3
assert result["count"] == 3
names = {c["name"] for c in result["checklists"]}
assert "Coding Standards" in names
assert "Design Review" in names
assert "Architecture" in names
def test_list_checklists_includes_metadata(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test that list_checklists includes name and description."""
from sso_mcp_server.checklists.service import ChecklistService
from sso_mcp_server.tools.list_checklists import list_checklists_impl
checklist_dir = temp_dir / "list_metadata"
checklist_dir.mkdir(exist_ok=True)
(checklist_dir / "test.md").write_text(
"""---
name: Test Checklist
description: A comprehensive test checklist
---
Content not included in list.
"""
)
service = ChecklistService(checklist_dir)
result = list_checklists_impl(service)
assert len(result["checklists"]) == 1
checklist = result["checklists"][0]
assert checklist["name"] == "Test Checklist"
assert checklist["description"] == "A comprehensive test checklist"
# Content should NOT be included
assert "content" not in checklist or checklist.get("content") is None
def test_list_checklists_empty_directory(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test list_checklists with no checklists available."""
from sso_mcp_server.checklists.service import ChecklistService
from sso_mcp_server.tools.list_checklists import list_checklists_impl
checklist_dir = temp_dir / "empty_checklists"
checklist_dir.mkdir()
service = ChecklistService(checklist_dir)
result = list_checklists_impl(service)
assert "checklists" in result
assert "count" in result
assert result["checklists"] == []
assert result["count"] == 0
def test_list_checklists_dynamic_discovery(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test that list_checklists picks up newly added files."""
from sso_mcp_server.checklists.service import ChecklistService
from sso_mcp_server.tools.list_checklists import list_checklists_impl
checklist_dir = temp_dir / "dynamic"
checklist_dir.mkdir()
service = ChecklistService(checklist_dir)
# Initially empty
result1 = list_checklists_impl(service)
assert len(result1["checklists"]) == 0
assert result1["count"] == 0
# Add a file
(checklist_dir / "new.md").write_text("---\nname: New Checklist\n---\nContent.")
# Should see new file (no caching)
result2 = list_checklists_impl(service)
assert len(result2["checklists"]) == 1
assert result2["count"] == 1
assert result2["checklists"][0]["name"] == "New Checklist"
class TestMCPToolErrors:
"""Tests for MCP tool error handling."""
def test_get_checklist_not_found_provides_suggestions(
self, temp_dir: Path, mock_env_vars: dict
) -> None:
"""Test that not found error includes available checklists."""
from sso_mcp_server.checklists.service import ChecklistService
from sso_mcp_server.tools.get_checklist import get_checklist_impl
checklist_dir = temp_dir / "error_test"
checklist_dir.mkdir(exist_ok=True)
(checklist_dir / "coding.md").write_text("---\nname: Coding Standards\n---\nContent.")
(checklist_dir / "design.md").write_text("---\nname: Design Review\n---\nContent.")
service = ChecklistService(checklist_dir)
result = get_checklist_impl("Unknown Checklist", service)
# Error response should include available checklists
assert "available" in result or "error" in result
if "available" in result:
assert "Coding Standards" in result["available"]
assert "Design Review" in result["available"]
def test_get_checklist_similar_name_suggestion(
self, temp_dir: Path, mock_env_vars: dict
) -> None:
"""Test that misspelled names get helpful suggestions."""
from sso_mcp_server.checklists.service import ChecklistService
from sso_mcp_server.tools.get_checklist import get_checklist_impl
checklist_dir = temp_dir / "similar_name"
checklist_dir.mkdir(exist_ok=True)
(checklist_dir / "coding.md").write_text("---\nname: Coding Standards\n---\nContent.")
service = ChecklistService(checklist_dir)
# Slightly misspelled - should still return available checklists
result = get_checklist_impl("Coding Standars", service)
# Should return error with available checklists
assert "available" in result or "error" in result