"""Shared test fixtures for SSO MCP Server tests."""
from __future__ import annotations
import os
import tempfile
import time
from pathlib import Path
from typing import TYPE_CHECKING
from unittest.mock import patch
import pytest
if TYPE_CHECKING:
from collections.abc import Generator
@pytest.fixture
def temp_dir() -> Generator[Path, None, None]:
"""Create a temporary directory for test files.
Yields:
Path to the temporary directory.
"""
with tempfile.TemporaryDirectory() as tmpdir:
yield Path(tmpdir)
@pytest.fixture
def sample_checklist_dir(temp_dir: Path) -> Path:
"""Create a temporary directory with sample checklist files.
Args:
temp_dir: Temporary directory fixture.
Returns:
Path to directory containing sample checklists.
"""
checklists_dir = temp_dir / "checklists"
checklists_dir.mkdir()
# Create coding.md
coding_content = """---
name: coding
description: Code quality checklist
---
# Coding Standards
- [ ] Variables use descriptive names
- [ ] Functions follow verb_noun pattern
"""
(checklists_dir / "coding.md").write_text(coding_content)
# Create architecture.md
arch_content = """---
name: architecture
description: Architecture review checklist
---
# Architecture Review
- [ ] Single responsibility principle
- [ ] Dependencies point inward
"""
(checklists_dir / "architecture.md").write_text(arch_content)
# Create file without frontmatter for edge case testing
no_frontmatter = """# No Frontmatter
This file has no YAML frontmatter.
"""
(checklists_dir / "no-frontmatter.md").write_text(no_frontmatter)
return checklists_dir
@pytest.fixture
def mock_env_vars(
temp_dir: Path, sample_checklist_dir: Path
) -> Generator[dict[str, str], None, None]:
"""Mock environment variables for testing.
Args:
temp_dir: Temporary directory fixture.
sample_checklist_dir: Sample checklist directory fixture.
Yields:
Dictionary of mocked environment variables.
"""
env_vars = {
"AZURE_CLIENT_ID": "test-client-id-12345678",
"AZURE_TENANT_ID": "test-tenant-id-87654321",
"CHECKLIST_DIR": str(sample_checklist_dir),
"MCP_PORT": "8080",
"LOG_LEVEL": "DEBUG",
"TOKEN_CACHE_PATH": str(temp_dir / "token_cache.bin"),
}
with patch.dict(os.environ, env_vars, clear=False):
yield env_vars
@pytest.fixture
def mock_token_data() -> dict:
"""Create mock token data for authentication tests.
Returns:
Dictionary containing mock token information.
"""
return {
"access_token": "mock-access-token-xyz",
"refresh_token": "mock-refresh-token-abc",
"expires_at": time.time() + 3600, # 1 hour from now
"user_id": "test-user@example.com",
"tenant_id": "test-tenant-id-87654321",
"token_type": "Bearer",
"scope": "openid profile email",
}
@pytest.fixture
def expired_token_data() -> dict:
"""Create expired token data for testing token refresh.
Returns:
Dictionary containing expired token information.
"""
return {
"access_token": "expired-access-token",
"refresh_token": "valid-refresh-token",
"expires_at": time.time() - 3600, # 1 hour ago (expired)
"user_id": "test-user@example.com",
"tenant_id": "test-tenant-id-87654321",
"token_type": "Bearer",
"scope": "openid profile email",
}
@pytest.fixture
def near_expiry_token_data() -> dict:
"""Create token data that is about to expire (for refresh testing).
Returns:
Dictionary containing token that expires in less than 5 minutes.
"""
return {
"access_token": "near-expiry-access-token",
"refresh_token": "valid-refresh-token",
"expires_at": time.time() + 180, # 3 minutes from now
"user_id": "test-user@example.com",
"tenant_id": "test-tenant-id-87654321",
"token_type": "Bearer",
"scope": "openid profile email",
}
@pytest.fixture(autouse=True)
def reset_settings_after_test() -> Generator[None, None, None]:
"""Reset global settings after each test.
This ensures tests don't affect each other through global state.
"""
yield
# Import here to avoid circular imports during test collection
from sso_mcp_server.config import reset_settings
reset_settings()