"""Unit tests for Process Parser component.
Tests YAML frontmatter parsing and content extraction from process files.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from pathlib import Path
class TestProcessParser:
"""Tests for Process Parser functionality."""
def test_parse_valid_frontmatter(self, temp_dir: Path) -> None:
"""Test parsing a markdown file with valid YAML frontmatter."""
from sso_mcp_server.processes.parser import parse_process_file
# Create test file with frontmatter
test_file = temp_dir / "test.md"
test_file.write_text(
"""---
name: Code Review Process
description: Standard procedure for code reviews
---
# Code Review Process
## Steps
1. Create a pull request
2. Request reviewers
"""
)
result = parse_process_file(test_file)
assert result is not None
assert result["name"] == "Code Review Process"
assert result["description"] == "Standard procedure for code reviews"
assert "# Code Review Process" in result["content"]
assert "1. Create a pull request" in result["content"]
def test_parse_frontmatter_extracts_name(self, temp_dir: Path) -> None:
"""Test that parser extracts name from frontmatter (FR-003)."""
from sso_mcp_server.processes.parser import parse_process_file
test_file = temp_dir / "named.md"
test_file.write_text(
"""---
name: Deployment Process
---
Content here.
"""
)
result = parse_process_file(test_file)
assert result["name"] == "Deployment Process"
def test_parse_frontmatter_extracts_description(self, temp_dir: Path) -> None:
"""Test that parser extracts description from frontmatter (FR-003)."""
from sso_mcp_server.processes.parser import parse_process_file
test_file = temp_dir / "described.md"
test_file.write_text(
"""---
name: Test
description: This is a detailed description of the process.
---
Content here.
"""
)
result = parse_process_file(test_file)
assert result["description"] == "This is a detailed description of the process."
def test_parse_file_without_frontmatter(self, temp_dir: Path) -> None:
"""Test parsing a file without YAML frontmatter (edge case: malformed)."""
from sso_mcp_server.processes.parser import parse_process_file
test_file = temp_dir / "no_frontmatter.md"
test_file.write_text(
"""# Just a Title
Some content without frontmatter.
"""
)
result = parse_process_file(test_file)
assert result is not None
# Name should default to filename without extension
assert result["name"] == "no_frontmatter"
assert result["description"] is None or result["description"] == ""
assert "# Just a Title" in result["content"]
def test_parse_file_with_empty_frontmatter(self, temp_dir: Path) -> None:
"""Test parsing a file with empty frontmatter."""
from sso_mcp_server.processes.parser import parse_process_file
test_file = temp_dir / "empty_frontmatter.md"
test_file.write_text(
"""---
---
Content after empty frontmatter.
"""
)
result = parse_process_file(test_file)
assert result is not None
assert result["name"] == "empty_frontmatter"
assert "Content after empty frontmatter" in result["content"]
def test_parse_returns_content_body(self, temp_dir: Path) -> None:
"""Test that parser returns the content body without frontmatter."""
from sso_mcp_server.processes.parser import parse_process_file
test_file = temp_dir / "content.md"
test_file.write_text(
"""---
name: Test
description: Test description
---
# Main Content
This is the main content that should be returned.
- Item 1
- Item 2
"""
)
result = parse_process_file(test_file)
# Content should NOT include the frontmatter delimiters
assert "---" not in result["content"]
assert "name: Test" not in result["content"]
assert "# Main Content" in result["content"]
assert "This is the main content" in result["content"]
def test_parse_preserves_markdown_formatting(self, temp_dir: Path) -> None:
"""Test that parser preserves markdown formatting in content."""
from sso_mcp_server.processes.parser import parse_process_file
test_file = temp_dir / "formatted.md"
test_file.write_text(
"""---
name: Formatted
---
# Header
## Subheader
**Bold** and *italic* text.
```bash
./deploy.sh
```
| Step | Description |
|------|-------------|
| 1 | Build |
"""
)
result = parse_process_file(test_file)
assert "# Header" in result["content"]
assert "## Subheader" in result["content"]
assert "**Bold**" in result["content"]
assert "```bash" in result["content"]
assert "| Step |" in result["content"]
def test_parse_nonexistent_file_returns_none(self, temp_dir: Path) -> None:
"""Test that parsing a nonexistent file returns None."""
from sso_mcp_server.processes.parser import parse_process_file
nonexistent = temp_dir / "does_not_exist.md"
result = parse_process_file(nonexistent)
assert result is None
def test_parse_includes_file_path(self, temp_dir: Path) -> None:
"""Test that result includes the file path."""
from sso_mcp_server.processes.parser import parse_process_file
test_file = temp_dir / "with_path.md"
test_file.write_text(
"""---
name: Path Test
---
Content.
"""
)
result = parse_process_file(test_file)
assert result["path"] == test_file
def test_parse_includes_normalized_name(self, temp_dir: Path) -> None:
"""Test that result includes normalized name for matching."""
from sso_mcp_server.processes.parser import parse_process_file
test_file = temp_dir / "test.md"
test_file.write_text(
"""---
name: Code Review Process
---
Content.
"""
)
result = parse_process_file(test_file)
assert "normalized_name" in result
assert result["normalized_name"] == "code-review-process"
class TestProcessParserEdgeCases:
"""Edge case tests for Process Parser."""
def test_parse_file_with_multiple_frontmatter_delimiters(self, temp_dir: Path) -> None:
"""Test parsing file with --- in content (not frontmatter)."""
from sso_mcp_server.processes.parser import parse_process_file
test_file = temp_dir / "multiple_dashes.md"
test_file.write_text(
"""---
name: Multiple Dashes
---
Content with horizontal rule:
---
More content after.
"""
)
result = parse_process_file(test_file)
assert result["name"] == "Multiple Dashes"
# Horizontal rule should be in content
assert "---" in result["content"]
assert "More content after" in result["content"]
def test_parse_file_with_special_characters_in_name(self, temp_dir: Path) -> None:
"""Test parsing file with special characters in frontmatter values."""
from sso_mcp_server.processes.parser import parse_process_file
test_file = temp_dir / "special.md"
test_file.write_text(
"""---
name: "Test: Special & Characters!"
description: Description with "quotes" and 'apostrophes'
---
Content.
"""
)
result = parse_process_file(test_file)
assert result["name"] == "Test: Special & Characters!"
assert "quotes" in result["description"]
def test_parse_file_with_unicode_content(self, temp_dir: Path) -> None:
"""Test parsing file with unicode characters."""
from sso_mcp_server.processes.parser import parse_process_file
test_file = temp_dir / "unicode.md"
test_file.write_text(
"""---
name: Unicode Test 日本語
description: Description with émojis 🎉
---
Content with unicode: café, naïve, 中文
"""
)
result = parse_process_file(test_file)
assert "日本語" in result["name"]
assert "🎉" in result["description"]
assert "中文" in result["content"]
class TestNormalizeName:
"""Tests for name normalization function."""
def test_normalize_lowercase(self) -> None:
"""Test that normalize converts to lowercase."""
from sso_mcp_server.processes.parser import normalize_name
assert normalize_name("CODE-REVIEW") == "code-review"
assert normalize_name("Code Review") == "code-review"
def test_normalize_replaces_spaces(self) -> None:
"""Test that normalize replaces spaces with hyphens."""
from sso_mcp_server.processes.parser import normalize_name
assert normalize_name("code review process") == "code-review-process"
def test_normalize_removes_special_characters(self) -> None:
"""Test that normalize removes special characters (edge case)."""
from sso_mcp_server.processes.parser import normalize_name
assert normalize_name("code-review!") == "code-review"
assert normalize_name("test@process#123") == "testprocess123"
assert normalize_name("release (v1.0)") == "release-v10"
def test_normalize_collapses_hyphens(self) -> None:
"""Test that normalize collapses multiple hyphens."""
from sso_mcp_server.processes.parser import normalize_name
assert normalize_name("code--review") == "code-review"
assert normalize_name("code - review") == "code-review"
def test_normalize_strips_hyphens(self) -> None:
"""Test that normalize strips leading/trailing hyphens."""
from sso_mcp_server.processes.parser import normalize_name
assert normalize_name("-code-review-") == "code-review"
assert normalize_name("---test---") == "test"
def test_normalize_handles_empty_string(self) -> None:
"""Test that normalize handles empty string."""
from sso_mcp_server.processes.parser import normalize_name
assert normalize_name("") == ""
assert normalize_name(" ") == ""