📦 EqualifyEverything / equalify-reflow

📄 clients.py · 129 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129"""
Canonical mock clients for test suite.

Provides standardized mocks for:
- Redis (AsyncMock for async operations)
- S3/boto3 (MagicMock for sync operations)
- AI services (AsyncMock for async operations)

All fixtures use function scope (default) unless specified.
"""

from unittest.mock import AsyncMock, MagicMock

import pytest


@pytest.fixture
def mock_redis_client():
    """Create mock Redis client with common async operations.

    Pre-configured with:
    - lpush, rpush, lrange, llen (queue operations)
    - set, get, delete, exists (key-value operations)
    - flushall, aclose (cleanup operations)

    Returns:
        AsyncMock: Mock Redis client for unit tests
    """
    client = AsyncMock()

    # Configure common return values
    client.lpush.return_value = 1
    client.rpush.return_value = 1
    client.llen.return_value = 0
    client.lrange.return_value = []
    client.get.return_value = None
    client.exists.return_value = 0
    client.flushall.return_value = None
    client.aclose.return_value = None

    return client


@pytest.fixture
def mock_s3_client():
    """Create mock S3 client with common sync operations.

    Pre-configured with:
    - upload_fileobj (document uploads)
    - put_object (content uploads)
    - get_object (downloads)
    - delete_object (cleanup)
    - list_objects_v2 (listing)

    Returns:
        MagicMock: Mock S3 client for unit tests
    """
    client = MagicMock()

    # Configure common return values
    client.upload_fileobj.return_value = None
    client.put_object.return_value = {"ResponseMetadata": {"HTTPStatusCode": 200}}
    client.get_object.return_value = {
        "Body": MagicMock(read=MagicMock(return_value=b"test content")),
        "ContentLength": 12,
    }
    client.delete_object.return_value = {"ResponseMetadata": {"HTTPStatusCode": 204}}
    client.list_objects_v2.return_value = {"Contents": []}

    return client


@pytest.fixture
def mock_ai_service():
    """Create mock AI service with common async operations.

    Pre-configured with:
    - enhance_accessibility (returns enhanced markdown)
    - generate_alt_text (returns descriptive alt text)
    - fix_heading_hierarchy (returns corrected structure)

    Returns:
        AsyncMock: Mock AI service for unit tests
    """
    service = AsyncMock()

    # Configure common return values
    service.enhance_accessibility.return_value = "# Enhanced Markdown\n\nAccessible content."
    service.generate_alt_text.return_value = "A descriptive alt text for the image"
    service.fix_heading_hierarchy.return_value = "# Corrected Heading Structure"

    return service


@pytest.fixture
def mock_presidio_analyzer():
    """Create mock Microsoft Presidio analyzer for PII detection.

    Pre-configured with:
    - analyze (returns empty list by default, no PII)

    Returns:
        MagicMock: Mock Presidio AnalyzerEngine
    """
    analyzer = MagicMock()
    analyzer.analyze.return_value = []  # No PII by default
    return analyzer


@pytest.fixture
def mock_presidio_anonymizer():
    """Create mock Microsoft Presidio anonymizer for PII redaction.

    Pre-configured with:
    - anonymize (returns anonymized text)

    Returns:
        MagicMock: Mock Presidio AnonymizerEngine
    """
    anonymizer = MagicMock()

    # Configure default return
    anonymizer.anonymize.return_value = MagicMock(
        text="[REDACTED]",
        items=[]
    )

    return anonymizer