Skip to content

Commit 8ac4189

Browse files
committed
Reduced redundant testcases and Moved utils
1 parent b1a5808 commit 8ac4189

5 files changed

Lines changed: 551 additions & 458 deletions

File tree

tests/units/test_endpoint.py

Lines changed: 40 additions & 252 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,8 @@
88
from tfe.exception import (
99
TFEConnectionException,
1010
TFEEndpointException,
11-
TFEForbiddenException,
12-
TFENotFoundException,
13-
TFEServerException,
1411
TFETimeoutException,
1512
TFEUnauthorizedException,
16-
TFEValidationException,
1713
)
1814

1915

@@ -90,223 +86,81 @@ def test_make_request_unsupported_method(self, endpoint):
9086
):
9187
endpoint._make_request("INVALID", "/test/path")
9288

93-
def test_get_method(self, endpoint, mock_response):
94-
"""Test the _get convenience method."""
95-
endpoint._http_client.get.return_value = mock_response
96-
97-
response = endpoint._get("/test/path")
98-
99-
endpoint._http_client.get.assert_called_once_with("/test/path")
100-
assert response == mock_response
101-
102-
def test_post_method(self, endpoint, mock_response):
103-
"""Test the _post convenience method."""
104-
endpoint._http_client.post.return_value = mock_response
105-
test_data = {"key": "value"}
106-
107-
response = endpoint._post("/test/path", test_data)
108-
109-
endpoint._http_client.post.assert_called_once_with("/test/path", json=test_data)
110-
assert response == mock_response
111-
112-
def test_put_method(self, endpoint, mock_response):
113-
"""Test the _put convenience method."""
114-
endpoint._http_client.put.return_value = mock_response
115-
test_data = {"key": "value"}
116-
117-
response = endpoint._put("/test/path", test_data)
118-
119-
endpoint._http_client.put.assert_called_once_with("/test/path", json=test_data)
120-
assert response == mock_response
121-
122-
def test_patch_method(self, endpoint, mock_response):
123-
"""Test the _patch convenience method."""
124-
endpoint._http_client.patch.return_value = mock_response
125-
test_data = {"key": "value"}
126-
127-
response = endpoint._patch("/test/path", test_data)
128-
129-
endpoint._http_client.patch.assert_called_once_with(
130-
"/test/path", json=test_data
131-
)
132-
assert response == mock_response
133-
134-
def test_delete_method(self, endpoint, mock_response):
135-
"""Test the _delete convenience method."""
136-
endpoint._http_client.delete.return_value = mock_response
137-
138-
response = endpoint._delete("/test/path")
139-
140-
endpoint._http_client.delete.assert_called_once_with("/test/path")
141-
assert response == mock_response
142-
14389

14490
class TestEndpointErrorHandling:
14591
"""Test cases for endpoint error handling."""
14692

14793
@pytest.mark.parametrize(
148-
"handler,error_class,error_msg,error_type",
94+
"method,http_method,exception_class,request_exception,expected_message,expected_cause_type",
14995
[
15096
(
151-
"_handle_connection_error",
97+
"GET",
98+
"get",
15299
TFEConnectionException,
100+
exceptions.ConnectionError("Connection failed"),
153101
"Failed to connect to TFE API",
154102
exceptions.ConnectionError,
155103
),
156104
(
157-
"_handle_timeout_error",
105+
"POST",
106+
"post",
158107
TFETimeoutException,
108+
exceptions.Timeout("Request timed out"),
159109
"Request timed out",
160110
exceptions.Timeout,
161111
),
162112
(
163-
"_handle_request_error",
113+
"PUT",
114+
"put",
164115
TFEEndpointException,
116+
exceptions.RequestException("Request failed"),
165117
"Request failed: Request failed",
166118
exceptions.RequestException,
167119
),
168120
(
169-
"_handle_unexpected_error",
121+
"DELETE",
122+
"delete",
170123
TFEEndpointException,
124+
ValueError("Unexpected error"),
171125
"Unexpected error occurred during DELETE request",
172126
ValueError,
173127
),
174128
],
175129
)
176-
def test_error_handlers(
177-
self, endpoint, handler, error_class, error_msg, error_type
130+
def test_error_handling(
131+
self,
132+
endpoint,
133+
method,
134+
http_method,
135+
exception_class,
136+
request_exception,
137+
expected_message,
138+
expected_cause_type,
178139
):
179-
"""Test all error handler methods."""
180-
method, path = "DELETE", "/test/path"
181-
error = error_type("Request failed")
182-
183-
with pytest.raises(error_class) as exc_info:
184-
getattr(endpoint, handler)(method, path, error)
185-
186-
exception = exc_info.value
187-
assert exception.message == error_msg
188-
assert exception.method == method
189-
assert exception.path == path
190-
assert exception.cause == error
191-
192-
@pytest.mark.parametrize(
193-
"response_data,expected",
194-
[
195-
({"error": "test"}, {"error": "test"}),
196-
({"text": "Error text"}, {"text": "Error text"}),
197-
(None, None),
198-
],
199-
)
200-
def test_extract_error_data(self, endpoint, mocker, response_data, expected):
201-
"""Test error data extraction from various response types."""
202-
if response_data is None:
203-
result = endpoint._extract_error_data(None)
204-
else:
205-
mock_response = mocker.Mock()
206-
if "error" in response_data:
207-
mock_response.json.return_value = response_data
208-
result = endpoint._extract_error_data(mock_response)
209-
else: # text case
210-
mock_response.json.side_effect = ValueError("Invalid JSON")
211-
mock_response.text = response_data["text"]
212-
result = endpoint._extract_error_data(mock_response)
213-
214-
assert result == expected
215-
216-
217-
class TestEndpointHTTPErrorHandling:
218-
"""Test cases for HTTP error handling."""
219-
220-
@pytest.mark.parametrize(
221-
"status_code,exception_class,expected_message",
222-
[
223-
(
224-
401,
225-
TFEUnauthorizedException,
226-
"Authentication failed - invalid or missing token",
227-
),
228-
(403, TFEForbiddenException, "Access forbidden - insufficient permissions"),
229-
(404, TFENotFoundException, "Resource not found"),
230-
(422, TFEValidationException, "Name is required; Email is invalid"),
231-
(500, TFEServerException, "TFE server error"),
232-
(418, TFEEndpointException, "HTTP error occurred"), # Unknown status
233-
],
234-
)
235-
def test_handle_http_error_status_codes(
236-
self, endpoint, mocker, status_code, exception_class, expected_message
237-
):
238-
"""Test HTTP error handling for different status codes."""
239-
method, path = "GET", "/test/path"
240-
241-
mock_response = mocker.Mock()
242-
mock_response.status_code = status_code
243-
if status_code == 422:
244-
mock_response.json.return_value = {
245-
"errors": [
246-
{"detail": "Name is required"},
247-
{"detail": "Email is invalid"},
248-
]
249-
}
250-
else:
251-
mock_response.json.return_value = {"error": "Test error"}
252-
253-
mock_http_error = exceptions.HTTPError(f"{status_code} Error")
254-
mock_http_error.response = mock_response
140+
"""Test various error handling scenarios."""
141+
path = "/test/path"
142+
getattr(endpoint._http_client, http_method).side_effect = request_exception
255143

256144
with pytest.raises(exception_class) as exc_info:
257-
endpoint._handle_http_error(method, path, mock_http_error)
145+
endpoint._make_request(method, path)
258146

259147
exception = exc_info.value
260148
assert exception.message == expected_message
261-
assert exception.status_code == status_code
262149
assert exception.method == method
263150
assert exception.path == path
151+
assert isinstance(exception.cause, expected_cause_type)
264152

265-
def test_handle_http_error_no_response(self, endpoint):
266-
"""Test HTTP error handling with no response."""
267-
mock_http_error = exceptions.HTTPError("HTTP Error")
268-
mock_http_error.response = None
269-
270-
with pytest.raises(TFEEndpointException) as exc_info:
271-
endpoint._handle_http_error("GET", "/test", mock_http_error)
272-
273-
assert exc_info.value.message == "HTTP error occurred"
274-
assert exc_info.value.status_code is None
275-
276-
277-
class TestEndpointIntegration:
278-
"""Integration tests for endpoint error handling."""
153+
def test_http_error_handling(self, endpoint, mocker):
154+
"""Test HTTP error handling (delegated to error_utils)."""
155+
method, path = "GET", "/test/path"
279156

280-
@pytest.mark.parametrize(
281-
"method,error_type,exception_class,expected_message",
282-
[
283-
(
284-
"GET",
285-
exceptions.ConnectionError,
286-
TFEConnectionException,
287-
"Failed to connect to TFE API",
288-
),
289-
("POST", exceptions.Timeout, TFETimeoutException, "Request timed out"),
290-
],
291-
)
292-
def test_make_request_errors(
293-
self, endpoint, method, error_type, exception_class, expected_message
294-
):
295-
"""Test _make_request with various error types."""
296-
path = "/test/path"
297-
getattr(endpoint._http_client, method.lower()).side_effect = error_type(
298-
"Test error"
157+
# Mock the handle_http_error function to raise an exception
158+
mock_handle_http_error = mocker.patch("tfe.endpoint.handle_http_error")
159+
mock_handle_http_error.side_effect = TFEUnauthorizedException(
160+
message="Authentication failed", status_code=401, method=method, path=path
299161
)
300162

301-
with pytest.raises(exception_class) as exc_info:
302-
endpoint._make_request(method, path)
303-
304-
assert exc_info.value.message == expected_message
305-
assert exc_info.value.method == method
306-
assert exc_info.value.path == path
307-
308-
def test_make_request_http_error(self, endpoint, mocker):
309-
"""Test _make_request with HTTP error."""
163+
# Create mock response that raises HTTPError
310164
mock_response = mocker.Mock()
311165
mock_response.status_code = 401
312166
mock_response.json.return_value = {"error": "Unauthorized"}
@@ -317,75 +171,9 @@ def test_make_request_http_error(self, endpoint, mocker):
317171

318172
endpoint._http_client.get.return_value = mock_response
319173

320-
with pytest.raises(TFEUnauthorizedException) as exc_info:
321-
endpoint._make_request("GET", "/test")
322-
323-
assert exc_info.value.status_code == 401
324-
325-
def test_make_request_success(self, endpoint, mock_response):
326-
"""Test successful _make_request."""
327-
endpoint._http_client.get.return_value = mock_response
328-
response = endpoint._make_request("GET", "/test")
329-
assert response == mock_response
330-
331-
332-
class TestEndpointErrorParsing:
333-
"""Test cases for error response parsing."""
334-
335-
@pytest.mark.parametrize(
336-
"response_data,expected_message,expected_errors,expected_code",
337-
[
338-
# JSON:API format with multiple errors
339-
(
340-
{
341-
"errors": [
342-
{"detail": "Name has already been taken"},
343-
{"detail": "Email is invalid"},
344-
]
345-
},
346-
"Name has already been taken; Email is invalid",
347-
["Name has already been taken", "Email is invalid"],
348-
None,
349-
),
350-
# JSON:API format with error code
351-
(
352-
{
353-
"errors": [
354-
{"detail": "Name is required", "code": "VALIDATION_ERROR"}
355-
]
356-
},
357-
"Name is required",
358-
["Name is required"],
359-
"VALIDATION_ERROR",
360-
),
361-
# Simple message format
362-
({"message": "Resource not found"}, "Resource not found", [], None),
363-
# Error field format
364-
(
365-
{"error": "Invalid request parameters"},
366-
"Invalid request parameters",
367-
[],
368-
None,
369-
),
370-
# Empty errors list
371-
({"errors": []}, "Unknown API error", [], None),
372-
# Unknown format
373-
({"unknown_field": "some value"}, "Unknown API error", [], None),
374-
# Malformed input
375-
("invalid json", "Unknown API error", [], None),
376-
],
377-
)
378-
def test_parse_tfe_error_response_formats(
379-
self, endpoint, response_data, expected_message, expected_errors, expected_code
380-
):
381-
"""Test parsing various error response formats."""
382-
result = endpoint.parse_tfe_error_response(response_data)
383-
384-
assert result["message"] == expected_message
385-
assert result["errors"] == expected_errors
386-
assert result["error_code"] == expected_code
174+
# This should call handle_http_error and raise TFEUnauthorizedException
175+
with pytest.raises(TFEUnauthorizedException):
176+
endpoint._make_request(method, path)
387177

388-
def test_parse_tfe_error_response_none(self, endpoint):
389-
"""Test parsing None response."""
390-
result = endpoint.parse_tfe_error_response(None)
391-
assert result["message"] == "Failed to parse error response: None"
178+
# Verify that handle_http_error was called
179+
mock_handle_http_error.assert_called_once()

0 commit comments

Comments
 (0)