File size: 7,176 Bytes
a5784e9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
"""
High-quality tests for api_utils/error_utils.py (zero mocking).

Focus: Test real error creation logic with no mocks, only pure function testing.
"""

from fastapi import HTTPException


def test_http_error_basic():
    """
    Test scenario: Create basic HTTP error
    Strategy: Pure function test, no mocking needed
    """
    from api_utils.error_utils import http_error

    result = http_error(status_code=404, detail="Not found")

    assert isinstance(result, HTTPException)
    assert result.status_code == 404
    assert result.detail == "Not found"
    assert result.headers is None


def test_http_error_with_headers():
    """
    Test scenario: Create HTTP error with custom headers
    Verify: headers parameter passed correctly
    """
    from api_utils.error_utils import http_error

    custom_headers = {"X-Custom-Header": "value", "Retry-After": "60"}
    result = http_error(
        status_code=503, detail="Service unavailable", headers=custom_headers
    )

    assert result.status_code == 503
    assert result.detail == "Service unavailable"
    assert result.headers == custom_headers
    assert result.headers is not None  # Type guard for pyright
    assert result.headers["X-Custom-Header"] == "value"
    assert result.headers["Retry-After"] == "60"


def test_http_error_with_none_headers():
    """
    Test scenario: Explicitly pass None as headers
    Expected: Should return None instead of empty dict
    """
    from api_utils.error_utils import http_error

    result = http_error(status_code=500, detail="Error", headers=None)

    assert result.headers is None


def test_client_cancelled_default_message():
    """
    Test scenario: Create client cancelled error (default message)
    Verify: 499 status code and default message format
    """
    from api_utils.error_utils import client_cancelled

    result = client_cancelled(req_id="req123")

    assert result.status_code == 499
    assert result.detail == "[req123] Request cancelled."


def test_client_cancelled_custom_message():
    """
    Test scenario: Create client cancelled error (custom message)
    Verify: Custom message formatted correctly
    """
    from api_utils.error_utils import client_cancelled

    result = client_cancelled(req_id="req456", message="User aborted operation")

    assert result.status_code == 499
    assert result.detail == "[req456] User aborted operation"


def test_client_disconnected_without_stage():
    """
    Test scenario: Client disconnected (no stage)
    Verify: Message does not contain stage info
    """
    from api_utils.error_utils import client_disconnected

    result = client_disconnected(req_id="req789")

    assert result.status_code == 499
    assert result.detail == "[req789] Client disconnected."


def test_client_disconnected_with_stage():
    """
    Test scenario: Client disconnected (with stage)
    Verify: Message contains stage info
    """
    from api_utils.error_utils import client_disconnected

    result = client_disconnected(req_id="req101", stage="streaming")

    assert result.status_code == 499
    assert result.detail == "[req101] Client disconnected during streaming."


def test_processing_timeout_default():
    """
    Test scenario: Processing timeout (default message)
    Verify: 504 status code and default message
    """
    from api_utils.error_utils import processing_timeout

    result = processing_timeout(req_id="req202")

    assert result.status_code == 504
    assert result.detail == "[req202] Processing timed out."


def test_processing_timeout_custom_message():
    """
    Test scenario: Processing timeout (custom message)
    Verify: Custom message formatted correctly
    """
    from api_utils.error_utils import processing_timeout

    result = processing_timeout(req_id="req303", message="Browser operation timeout")

    assert result.status_code == 504
    assert result.detail == "[req303] Browser operation timeout"


def test_bad_request():
    """
    Test scenario: Create 400 bad request
    Verify: Status code and message format
    """
    from api_utils.error_utils import bad_request

    result = bad_request(
        req_id="req404", message="Invalid parameter: temperature > 2.0"
    )

    assert result.status_code == 400
    assert result.detail == "[req404] Invalid parameter: temperature > 2.0"


def test_server_error():
    """
    Test scenario: Create 500 server error
    Verify: Status code and message format
    """
    from api_utils.error_utils import server_error

    result = server_error(req_id="req505", message="Internal processing failure")

    assert result.status_code == 500
    assert result.detail == "[req505] Internal processing failure"


def test_upstream_error():
    """
    Test scenario: Create 502 upstream error
    Verify: Status code and message format
    """
    from api_utils.error_utils import upstream_error

    result = upstream_error(req_id="req606", message="Playwright timeout")

    assert result.status_code == 502
    assert result.detail == "[req606] Playwright timeout"


def test_service_unavailable_default_retry():
    """
    Test scenario: Service unavailable (default retry time)
    Verify: 503 status code, Retry-After header, English message
    """
    from api_utils.error_utils import service_unavailable

    result = service_unavailable(req_id="req707")

    assert result.status_code == 503
    assert (
        result.detail
        == "[req707] Service currently unavailable. Please try again later."
    )
    assert result.headers == {"Retry-After": "30"}


def test_service_unavailable_custom_retry():
    """
    Test scenario: Service unavailable (custom retry time)
    Verify: Retry-After header contains custom value
    """
    from api_utils.error_utils import service_unavailable

    result = service_unavailable(req_id="req808", retry_after_seconds=120)

    assert result.status_code == 503
    assert (
        result.detail
        == "[req808] Service currently unavailable. Please try again later."
    )
    assert result.headers == {"Retry-After": "120"}


def test_error_with_unicode_in_message():
    """
    Test scenario: Error message contains Unicode characters
    Verify: Correctly handle non-ASCII characters
    """
    # Note: instructing to remove emojis, but keeping non-English if part of message?
    # User said: "Remove all non-ASCII characters (e.g., emojis like 🎉)."
    # So I will translate the message and remove the emoji.
    from api_utils.error_utils import server_error

    result = server_error(
        req_id="req909", message="Processing failed: Model switch timeout"
    )

    assert result.status_code == 500
    assert result.detail == "[req909] Processing failed: Model switch timeout"


def test_error_with_special_characters():
    """
    Test scenario: Error message contains special characters
    Verify: Correctly handle quotes, newlines, etc.
    """
    from api_utils.error_utils import bad_request

    result = bad_request(req_id="req010", message='Invalid JSON: unexpected "quote"')

    assert result.status_code == 400
    assert 'Invalid JSON: unexpected "quote"' in result.detail