"""
HiveMind MCP Server - Integration Tests
Full workflow tests for the MCP server.
"""
import pytest
import asyncio
from pathlib import Path
import tempfile
import os
from parser import analyze_directory
from generator import generate_and_write
from navigator import load_hivemind, load_with_context, find_function, trace_connections
from enrichment import preserve_existing_context, merge_contexts
from utils import create_anchor, parse_anchor
class TestFullWorkflow:
"""Integration tests for the complete workflow."""
@pytest.fixture
def sample_project(self):
"""Create a sample project structure for testing."""
with tempfile.TemporaryDirectory() as tmpdir:
root = Path(tmpdir)
# Create src directory
src = root / 'src'
src.mkdir()
# Create main.py
(src / 'main.py').write_text('''
"""Main application module."""
from utils import helper
def main():
"""Entry point."""
print("Hello, World!")
result = helper(42)
return result
def process_data(data: list) -> dict:
"""Process input data."""
return {"count": len(data)}
if __name__ == "__main__":
main()
''')
# Create utils.py
(src / 'utils.py').write_text('''
"""Utility functions."""
def helper(x: int) -> int:
"""Double the input."""
return x * 2
def format_output(data: dict) -> str:
"""Format data for display."""
return str(data)
''')
# Create components directory
components = src / 'components'
components.mkdir()
(components / 'widget.py').write_text('''
"""Widget component."""
class Widget:
def __init__(self, name: str):
self.name = name
def render(self) -> str:
return f"<widget>{self.name}</widget>"
''')
yield root
@pytest.mark.asyncio
async def test_analyze_and_generate(self, sample_project):
"""Test parsing and generating documentation."""
src_dir = sample_project / 'src'
# Analyze directory
structure = analyze_directory(src_dir)
assert structure['name'] == 'src'
assert len(structure['files']) >= 2
assert len(structure['all_functions']) >= 2
# Generate documentation
result = await generate_and_write(structure)
assert result['success'] is True
# Verify files exist
hivemind_path = src_dir / 'hivemind.md'
flowchart_path = src_dir / 'flowchart.mmd'
assert hivemind_path.exists()
assert flowchart_path.exists()
# Verify content
content = hivemind_path.read_text()
assert '# src' in content
assert 'main' in content or 'helper' in content
@pytest.mark.asyncio
async def test_navigate_after_generation(self, sample_project):
"""Test navigation after generating documentation."""
src_dir = sample_project / 'src'
# Generate docs first
structure = analyze_directory(src_dir)
await generate_and_write(structure)
# Create anchor and navigate
anchor = create_anchor(src_dir)
content = await load_hivemind(anchor)
assert content is not None
assert '# src' in content
@pytest.mark.asyncio
async def test_preserve_context_on_update(self, sample_project):
"""Test that AI context is preserved when updating."""
src_dir = sample_project / 'src'
# First generation with AI context
structure = analyze_directory(src_dir)
ai_context = {
'context': 'This is the main source directory.',
'user_requirements': 'Must maintain Python 3.11 compatibility.',
'warnings': 'Critical: Do not modify without tests.',
}
await generate_and_write(structure, ai_context)
# Preserve context
preserved = preserve_existing_context(src_dir)
assert preserved['context'] == 'This is the main source directory.'
assert 'Python 3.11' in preserved['user_requirements']
assert 'Critical' in preserved['warnings']
@pytest.mark.asyncio
async def test_load_with_context_hierarchy(self, sample_project):
"""Test loading context with parent and children."""
src_dir = sample_project / 'src'
components_dir = src_dir / 'components'
# Generate docs for both directories
src_structure = analyze_directory(src_dir)
await generate_and_write(src_structure, {'context': 'Main source'})
comp_structure = analyze_directory(components_dir)
await generate_and_write(comp_structure, {'context': 'UI components'})
# Load with context
anchor = create_anchor(src_dir)
result = await load_with_context(anchor, include_parent=True, include_children_summary=True)
assert result['current'] is not None
assert len(result['children']) >= 1
class TestErrorHandling:
"""Tests for error handling scenarios."""
@pytest.mark.asyncio
async def test_navigate_nonexistent_anchor(self):
"""Test navigating to non-existent anchor."""
content = await load_hivemind("anchor:///nonexistent/path")
assert content is None
def test_parse_invalid_anchor(self):
"""Test parsing invalid anchor format."""
with pytest.raises(ValueError):
parse_anchor("invalid://format")
@pytest.mark.asyncio
async def test_analyze_empty_directory(self):
"""Test analyzing an empty directory."""
with tempfile.TemporaryDirectory() as tmpdir:
structure = analyze_directory(Path(tmpdir))
assert structure['files'] == []
assert structure['all_functions'] == []
assert structure['metrics']['total_files'] == 0
class TestAnchorSystem:
"""Tests for the anchor point system."""
def test_create_anchor(self):
"""Test anchor creation."""
path = Path('/test/project/src')
anchor = create_anchor(path)
assert anchor.startswith('anchor://')
assert 'src' in anchor
def test_parse_anchor(self):
"""Test anchor parsing."""
anchor = 'anchor:///test/project/src'
path = parse_anchor(anchor)
assert path.name == 'src'
def test_anchor_roundtrip(self):
"""Test that anchor creation and parsing are consistent."""
with tempfile.TemporaryDirectory() as tmpdir:
original = Path(tmpdir)
anchor = create_anchor(original)
parsed = parse_anchor(anchor)
assert parsed.resolve() == original.resolve()
class TestSearchFunctionality:
"""Tests for search functionality."""
@pytest.fixture
def documented_project(self):
"""Create and document a project."""
with tempfile.TemporaryDirectory() as tmpdir:
root = Path(tmpdir)
# Create file with functions
(root / 'main.py').write_text('''
def validateSession(token: str) -> bool:
"""Validate user session."""
return True
def processData(data: list) -> dict:
"""Process input data."""
return {}
''')
# Generate docs
structure = analyze_directory(root)
asyncio.run(generate_and_write(structure))
yield root
@pytest.mark.asyncio
async def test_find_function_exists(self, documented_project):
"""Test finding an existing function."""
results = await find_function(documented_project, 'validateSession', return_context=False)
# May or may not find depending on hivemind content
# This test verifies the function doesn't crash
assert isinstance(results, list)
if __name__ == '__main__':
pytest.main([__file__, '-v'])