"""Unit tests for File Discovery component.
Tests discovery of markdown checklist files in the configured directory.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from pathlib import Path
class TestFileDiscovery:
"""Tests for File Discovery functionality."""
def test_discover_markdown_files(self, temp_dir: Path) -> None:
"""Test discovering .md files in directory."""
from sso_mcp_server.checklists.discovery import discover_checklists
# Create test files
(temp_dir / "checklist1.md").write_text("# Checklist 1")
(temp_dir / "checklist2.md").write_text("# Checklist 2")
files = discover_checklists(temp_dir)
assert len(files) == 2
filenames = {f.name for f in files}
assert "checklist1.md" in filenames
assert "checklist2.md" in filenames
def test_discover_ignores_non_markdown_files(self, temp_dir: Path) -> None:
"""Test that discovery ignores non-.md files."""
from sso_mcp_server.checklists.discovery import discover_checklists
# Create mixed files
(temp_dir / "checklist.md").write_text("# Valid")
(temp_dir / "readme.txt").write_text("Invalid")
(temp_dir / "config.json").write_text("{}")
(temp_dir / "script.py").write_text("# Python")
files = discover_checklists(temp_dir)
assert len(files) == 1
assert files[0].name == "checklist.md"
def test_discover_returns_empty_for_missing_directory(self, temp_dir: Path) -> None:
"""Test that discovery returns empty list for missing directory."""
from sso_mcp_server.checklists.discovery import discover_checklists
missing_dir = temp_dir / "nonexistent"
files = discover_checklists(missing_dir)
assert files == []
def test_discover_returns_empty_for_empty_directory(self, temp_dir: Path) -> None:
"""Test that discovery returns empty list for empty directory."""
from sso_mcp_server.checklists.discovery import discover_checklists
empty_dir = temp_dir / "empty"
empty_dir.mkdir()
files = discover_checklists(empty_dir)
assert files == []
def test_discover_does_not_recurse_subdirectories(self, temp_dir: Path) -> None:
"""Test that discovery does not recurse into subdirectories by default."""
from sso_mcp_server.checklists.discovery import discover_checklists
# Create files in root and subdirectory
(temp_dir / "root.md").write_text("# Root")
subdir = temp_dir / "subdir"
subdir.mkdir()
(subdir / "nested.md").write_text("# Nested")
files = discover_checklists(temp_dir)
# Should only find root-level files
assert len(files) == 1
assert files[0].name == "root.md"
def test_discover_returns_paths(self, temp_dir: Path) -> None:
"""Test that discovery returns Path objects."""
from pathlib import Path as PathType
from sso_mcp_server.checklists.discovery import discover_checklists
(temp_dir / "test.md").write_text("# Test")
files = discover_checklists(temp_dir)
assert len(files) == 1
assert isinstance(files[0], PathType)
assert files[0].is_absolute()
def test_discover_is_dynamic(self, temp_dir: Path) -> None:
"""Test that discovery picks up newly added files."""
from sso_mcp_server.checklists.discovery import discover_checklists
# Initial discovery
(temp_dir / "first.md").write_text("# First")
files1 = discover_checklists(temp_dir)
assert len(files1) == 1
# Add new file
(temp_dir / "second.md").write_text("# Second")
files2 = discover_checklists(temp_dir)
# Should see new file
assert len(files2) == 2
def test_discover_handles_hidden_files(self, temp_dir: Path) -> None:
"""Test that discovery ignores hidden files (starting with .)."""
from sso_mcp_server.checklists.discovery import discover_checklists
(temp_dir / "visible.md").write_text("# Visible")
(temp_dir / ".hidden.md").write_text("# Hidden")
files = discover_checklists(temp_dir)
assert len(files) == 1
assert files[0].name == "visible.md"
class TestFileDiscoveryEdgeCases:
"""Edge case tests for File Discovery."""
def test_discover_handles_files_with_spaces(self, temp_dir: Path) -> None:
"""Test discovering files with spaces in names."""
from sso_mcp_server.checklists.discovery import discover_checklists
(temp_dir / "file with spaces.md").write_text("# Spaces")
files = discover_checklists(temp_dir)
assert len(files) == 1
assert files[0].name == "file with spaces.md"
def test_discover_handles_unicode_filenames(self, temp_dir: Path) -> None:
"""Test discovering files with unicode in names."""
from sso_mcp_server.checklists.discovery import discover_checklists
(temp_dir / "日本語.md").write_text("# Japanese")
(temp_dir / "émoji-🎉.md").write_text("# Emoji")
files = discover_checklists(temp_dir)
assert len(files) == 2
def test_discover_handles_symlinks(self, temp_dir: Path) -> None:
"""Test that discovery can read files through symlinks."""
from sso_mcp_server.checklists.discovery import discover_checklists
# Create original file
original = temp_dir / "original.md"
original.write_text("# Original")
# Create symlink using Path.symlink_to
link = temp_dir / "link.md"
try:
link.symlink_to(original)
except OSError:
# Symlinks may not be supported on all systems
return
files = discover_checklists(temp_dir)
# Symlink resolves to same file as original, so deduplication removes it
# At minimum, we should find the original file
assert len(files) >= 1
assert any(f.name == "original.md" for f in files)
def test_discover_case_sensitivity(self, temp_dir: Path) -> None:
"""Test that discovery handles different case extensions."""
from sso_mcp_server.checklists.discovery import discover_checklists
(temp_dir / "lowercase.md").write_text("# Lower")
(temp_dir / "uppercase.MD").write_text("# Upper")
(temp_dir / "mixed.Md").write_text("# Mixed")
files = discover_checklists(temp_dir)
# All markdown files should be discovered
assert len(files) == 3