"""Unit tests for Checklist Service component.
Tests checklist retrieval and listing functionality.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from pathlib import Path
class TestChecklistService:
"""Tests for ChecklistService class."""
def test_get_checklist_by_name(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test retrieving a checklist by its name."""
import os
from sso_mcp_server.checklists.service import ChecklistService
# Create test checklist
(temp_dir / "coding.md").write_text(
"""---
name: Coding Standards
description: Standards for writing code
---
# Coding Standards Checklist
- [ ] Follow naming conventions
- [ ] Write unit tests
"""
)
os.environ["CHECKLIST_DIR"] = str(temp_dir)
service = ChecklistService(temp_dir)
result = service.get_checklist("Coding Standards")
assert result is not None
assert result["name"] == "Coding Standards"
assert "Follow naming conventions" in result["content"]
def test_get_checklist_not_found(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test that get_checklist returns None for unknown checklist."""
from sso_mcp_server.checklists.service import ChecklistService
# Create test checklist
(temp_dir / "existing.md").write_text(
"""---
name: Existing
---
Content.
"""
)
service = ChecklistService(temp_dir)
result = service.get_checklist("NonExistent")
assert result is None
def test_get_checklist_by_filename(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test retrieving a checklist by filename when name matches."""
from sso_mcp_server.checklists.service import ChecklistService
# Create file without explicit name (uses filename)
(temp_dir / "architecture.md").write_text(
"""# Architecture Checklist
- [ ] Define components
"""
)
service = ChecklistService(temp_dir)
# Should be able to find by filename (without extension)
result = service.get_checklist("architecture")
assert result is not None
assert "Define components" in result["content"]
def test_get_checklist_case_insensitive(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test that checklist lookup is case-insensitive."""
from sso_mcp_server.checklists.service import ChecklistService
(temp_dir / "coding.md").write_text(
"""---
name: Coding Standards
---
Content.
"""
)
service = ChecklistService(temp_dir)
# All of these should find the same checklist
result1 = service.get_checklist("Coding Standards")
result2 = service.get_checklist("coding standards")
result3 = service.get_checklist("CODING STANDARDS")
assert result1 is not None
assert result2 is not None
assert result3 is not None
assert result1["content"] == result2["content"] == result3["content"]
def test_get_checklist_includes_metadata(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test that get_checklist returns full metadata."""
from sso_mcp_server.checklists.service import ChecklistService
(temp_dir / "test.md").write_text(
"""---
name: Test Checklist
description: A detailed description
---
Content here.
"""
)
service = ChecklistService(temp_dir)
result = service.get_checklist("Test Checklist")
assert result["name"] == "Test Checklist"
assert result["description"] == "A detailed description"
assert "content" in result
assert "path" in result
class TestChecklistServiceListChecklists:
"""Tests for list_checklists functionality."""
def test_list_checklists_returns_all(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test listing all available checklists."""
from sso_mcp_server.checklists.service import ChecklistService
# Create multiple checklists
(temp_dir / "coding.md").write_text(
"""---
name: Coding Standards
description: Code quality checklist
---
Content.
"""
)
(temp_dir / "design.md").write_text(
"""---
name: Design Review
description: Design review checklist
---
Content.
"""
)
service = ChecklistService(temp_dir)
checklists = service.list_checklists()
assert len(checklists) == 2
names = {c["name"] for c in checklists}
assert "Coding Standards" in names
assert "Design Review" in names
def test_list_checklists_returns_metadata_only(
self, temp_dir: Path, mock_env_vars: dict
) -> None:
"""Test that list_checklists returns metadata without full content."""
from sso_mcp_server.checklists.service import ChecklistService
(temp_dir / "test.md").write_text(
"""---
name: Test
description: Test description
---
Very long content that should not be returned in list...
"""
)
service = ChecklistService(temp_dir)
checklists = service.list_checklists()
assert len(checklists) == 1
checklist = checklists[0]
assert "name" in checklist
assert "description" in checklist
# Content should NOT be included in list
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 listing checklists from empty directory."""
from sso_mcp_server.checklists.service import ChecklistService
empty_dir = temp_dir / "empty"
empty_dir.mkdir()
service = ChecklistService(empty_dir)
checklists = service.list_checklists()
assert checklists == []
def test_list_checklists_dynamic_discovery(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test that list picks up newly added files."""
from sso_mcp_server.checklists.service import ChecklistService
service = ChecklistService(temp_dir)
# Initially empty
assert len(service.list_checklists()) == 0
# Add a file
(temp_dir / "new.md").write_text(
"""---
name: New Checklist
---
Content.
"""
)
# Should see new file
checklists = service.list_checklists()
assert len(checklists) == 1
assert checklists[0]["name"] == "New Checklist"
class TestChecklistServiceEdgeCases:
"""Edge case tests for ChecklistService."""
def test_handles_malformed_frontmatter(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test handling files with malformed frontmatter."""
from sso_mcp_server.checklists.service import ChecklistService
# Create file with invalid YAML
(temp_dir / "malformed.md").write_text(
"""---
name: [invalid yaml
description: missing bracket
---
Content.
"""
)
service = ChecklistService(temp_dir)
# Should not crash, might return None or use defaults
# At minimum, should be able to list files without crashing
service.get_checklist("malformed")
service.list_checklists()
# Malformed files may be skipped or handled gracefully
def test_handles_empty_file(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test handling empty files."""
from sso_mcp_server.checklists.service import ChecklistService
(temp_dir / "empty.md").write_text("")
service = ChecklistService(temp_dir)
# Should handle gracefully without crashing
service.get_checklist("empty")
def test_handles_large_files(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test handling large checklist files."""
from sso_mcp_server.checklists.service import ChecklistService
# Create a large file
large_content = "- [ ] Item\n" * 10000
(temp_dir / "large.md").write_text(
f"""---
name: Large Checklist
---
{large_content}
"""
)
service = ChecklistService(temp_dir)
result = service.get_checklist("Large Checklist")
assert result is not None
assert result["name"] == "Large Checklist"
def test_get_available_checklist_names(self, temp_dir: Path, mock_env_vars: dict) -> None:
"""Test getting list of available checklist names for error messages."""
from sso_mcp_server.checklists.service import ChecklistService
(temp_dir / "one.md").write_text("---\nname: First\n---\nContent.")
(temp_dir / "two.md").write_text("---\nname: Second\n---\nContent.")
service = ChecklistService(temp_dir)
names = service.get_available_names()
assert "First" in names
assert "Second" in names