"""Pytest configuration and fixtures for integration tests."""
import tempfile
import shutil
from pathlib import Path
from unittest.mock import Mock
import pytest
from local_filesystem.server import create_server
from local_filesystem.schemas.config import LocalFSConfig
@pytest.fixture
def temp_root():
"""Create a temporary root directory for testing."""
temp_dir = tempfile.mkdtemp(prefix="localfs_integration_test_")
root_path = Path(temp_dir)
yield root_path
# Cleanup after test
shutil.rmtree(temp_dir, ignore_errors=True)
@pytest.fixture
def populated_temp_root(temp_root):
"""Create a temporary root directory with sample files and directories."""
# Create directory structure
(temp_root / "dir1").mkdir()
(temp_root / "dir2").mkdir()
(temp_root / "dir1" / "subdir1").mkdir()
(temp_root / "dir1" / "subdir2").mkdir()
(temp_root / "empty_dir").mkdir()
# Create text files
(temp_root / "file1.txt").write_text("Hello World\nThis is a test file.\nPython is awesome!")
(temp_root / "file2.txt").write_text("Another test file\nWith multiple lines\nFor testing")
(temp_root / "dir1" / "nested.txt").write_text("Nested file content\nInside dir1")
(temp_root / "dir1" / "subdir1" / "deep.txt").write_text("Deep nested file\nIn subdir1")
# Create files with different extensions
(temp_root / "script.py").write_text("#!/usr/bin/env python\nprint('Hello')")
(temp_root / "data.json").write_text('{"key": "value", "number": 42}')
(temp_root / "config.yml").write_text("setting: true\nvalue: 123")
(temp_root / "readme.md").write_text("# README\n\nThis is a readme file.")
# Create binary file
(temp_root / "binary.bin").write_bytes(b"\x00\x01\x02\x03\x04\x05\xff\xfe\xfd")
# Create files for search testing
(temp_root / "dir1" / "search_test.txt").write_text(
"This file contains the word SEARCH multiple times.\nSEARCH is here too."
)
(temp_root / "dir2" / "another.txt").write_text("Different content without the keyword")
yield temp_root
@pytest.fixture
def mock_context():
"""Create a mock Context object with default configuration."""
context = Mock()
context.session_config = LocalFSConfig(max_file_size_mb=10, max_search_depth=10)
return context
@pytest.fixture
def server():
"""Create a FastMCP server instance."""
return create_server()
@pytest.fixture
def capture_handlers(monkeypatch):
"""Fixture factory to capture route handlers with patched DEFAULT_ROOT."""
def _capture(temp_root, register_fn, module_name):
"""
Capture route handlers from a registration function.
Args:
temp_root: Temporary root path to patch
register_fn: Route registration function (e.g., register_directory_routes)
module_name: Module name to patch (e.g., 'local_filesystem.api.directory_routes')
Returns:
Dict of handler functions by tool name
"""
from mcp.server.fastmcp import FastMCP
# Patch the DEFAULT_ROOT
monkeypatch.setattr(f"{module_name}.DEFAULT_ROOT", temp_root)
server = FastMCP("test")
handlers = {}
original_tool = server.tool
def capture_tool(**kwargs):
def decorator(fn):
handlers[kwargs["name"]] = fn
return original_tool(**kwargs)(fn)
return decorator
server.tool = capture_tool
register_fn(server)
server.tool = original_tool
return handlers
return _capture