"""E2E tests for list_processes MCP tool.
Scenarios from E2E Test Plan Section 5.4 and 5.5:
- Scenario 5.4.4: List Processes Returns All Available (P0)
- Scenario 5.5.4: Dynamic Process Discovery (P1)
- Scenario 5.6.8: Empty Process Directory (P2)
"""
from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING
import pytest
from sso_mcp_server.processes.service import ProcessService
if TYPE_CHECKING:
pass
@pytest.mark.e2e
@pytest.mark.smoke
@pytest.mark.process
class TestListProcessesE2E:
"""E2E tests for list_processes tool."""
def test_list_processes_returns_all_available(
self,
e2e_process_dir: Path,
) -> None:
"""Scenario 5.4.4: List processes returns all available.
Given server is authenticated and ready
And process directory contains: code-review.md, deployment.md, incident-response.md
When client sends MCP request to list_processes
Then server returns array of all processes with name and description
"""
# Arrange
service = ProcessService(e2e_process_dir)
# Act
result = service.list_processes()
# Assert
assert result is not None
assert len(result) == 3, f"Expected 3 processes, got {len(result)}"
names = [p["name"] for p in result]
assert "Code Review Process" in names
assert "Deployment Process" in names
assert "Incident Response" in names
# Each process should have name and description
for process in result:
assert "name" in process
assert "description" in process
def test_list_processes_includes_descriptions(
self,
e2e_process_dir: Path,
) -> None:
"""Test that list_processes includes descriptions from frontmatter.
Given processes have YAML frontmatter with descriptions
When client requests list_processes
Then each item includes the description
"""
# Arrange
service = ProcessService(e2e_process_dir)
# Act
result = service.list_processes()
# Assert
descriptions = {p["name"]: p["description"] for p in result}
assert descriptions["Code Review Process"] == "Standard procedure for reviewing code changes"
assert descriptions["Deployment Process"] == "Production deployment procedure"
def test_list_processes_does_not_include_content(
self,
e2e_process_dir: Path,
) -> None:
"""Test that list_processes returns metadata only, not full content.
Given multiple processes exist
When client requests list_processes
Then response includes only name and description, not full content
"""
# Arrange
service = ProcessService(e2e_process_dir)
# Act
result = service.list_processes()
# Assert
for process in result:
# Should have name and description
assert "name" in process
assert "description" in process
# Should NOT have full content in list response
@pytest.mark.e2e
@pytest.mark.regression
@pytest.mark.process
class TestDynamicProcessDiscoveryE2E:
"""E2E tests for dynamic process discovery."""
def test_dynamic_process_discovery(
self,
e2e_process_dir: Path,
) -> None:
"""Scenario 5.5.4: Dynamic process discovery.
Given server is running and authenticated
And initial list_processes returns 3 processes
When new file "custom-process.md" is added to PROCESS_DIR
And client sends list_processes request
Then response includes 4 processes (including "custom-process")
"""
# Arrange
service = ProcessService(e2e_process_dir)
# Verify initial state
initial_result = service.list_processes()
initial_count = len(initial_result)
assert initial_count == 3
# Add new process file
custom_content = """---
name: Custom Process
description: Dynamically added process
---
# Custom Process
- [ ] Custom step 1
"""
(e2e_process_dir / "custom-process.md").write_text(custom_content)
# Act - re-discover processes
result = service.list_processes()
# Assert
assert len(result) == 4, "Should discover newly added process"
names = [p["name"] for p in result]
assert "Custom Process" in names
def test_process_removal_detected(
self,
e2e_process_dir: Path,
) -> None:
"""Test that removed processes are no longer listed.
Given server is running with 3 processes
When a process file is deleted
Then list_processes returns 2 processes
"""
# Arrange
service = ProcessService(e2e_process_dir)
# Verify initial state
initial_result = service.list_processes()
assert len(initial_result) == 3
# Remove a process
(e2e_process_dir / "incident-response.md").unlink()
# Act
result = service.list_processes()
# Assert
assert len(result) == 2
names = [p["name"] for p in result]
assert "Incident Response" not in names
@pytest.mark.e2e
@pytest.mark.regression
@pytest.mark.process
class TestEmptyProcessDirectoryE2E:
"""E2E tests for empty process directory handling."""
def test_list_processes_empty_directory(
self,
e2e_temp_dir: Path,
) -> None:
"""Scenario 5.6.8: Empty process directory.
Given process directory exists but is empty
When client sends list_processes request
Then server returns empty array with count=0
"""
# Arrange - create empty process directory
empty_dir = e2e_temp_dir / "empty_processes"
empty_dir.mkdir(parents=True)
service = ProcessService(empty_dir)
# Act
result = service.list_processes()
# Assert
assert result == [], "Empty directory should return empty list"