diff --git a/test/conftest.py b/test/conftest.py index 1c89a548..bacc479f 100755 --- a/test/conftest.py +++ b/test/conftest.py @@ -58,6 +58,9 @@ def recording_server_fixture(): def recording_server(responses): """Serve the given (status, body) responses, repeating the last one. + A response may also be (status, body, content_type) to override the + content type inferred from the body, e.g. to serve malformed JSON. + Yields the endpoint along with the list of requests received so far. """ @@ -80,7 +83,8 @@ def do_POST(self): # BaseHTTPRequestHandler dispatches on this name. } ) - status, payload = remaining.pop(0) if len(remaining) > 1 else remaining[0] + response = remaining.pop(0) if len(remaining) > 1 else remaining[0] + status, payload, *rest = response if isinstance(payload, str): content_type = "text/plain" @@ -89,6 +93,9 @@ def do_POST(self): # BaseHTTPRequestHandler dispatches on this name. content_type = "application/json" body = json.dumps(payload).encode() + if rest: + content_type = rest[0] + self.send_response(status) self.send_header("content-type", content_type) self.send_header("content-length", str(len(body))) diff --git a/test/http_error_test.py b/test/http_error_test.py index 27454229..d737cfcc 100644 --- a/test/http_error_test.py +++ b/test/http_error_test.py @@ -60,3 +60,50 @@ def test_seam_http_throws_http_error_on_non_standard_response(server): seam.devices.list() assert exc_info.value.response.status_code == 503 + + +# The fake cannot produce malformed error responses, so the recording server +# drives the bodies that must fall through is_api_error_response and raise a +# plain HTTPError rather than being parsed into a SeamHttpApiError. +def test_seam_http_raises_http_error_on_non_json_response(recording_server): + with recording_server([(500, "Internal Server Error")]) as (endpoint, _): + seam = Seam.from_api_key("seam_apikey_token", endpoint=endpoint) + + with pytest.raises(niquests.HTTPError) as exc_info: + seam.devices.list() + + assert exc_info.value.response.status_code == 500 + + +def test_seam_http_raises_http_error_on_malformed_json(recording_server): + responses = [(500, "{invalid json", "application/json")] + + with recording_server(responses) as (endpoint, _): + seam = Seam.from_api_key("seam_apikey_token", endpoint=endpoint) + + with pytest.raises(niquests.HTTPError) as exc_info: + seam.devices.list() + + assert exc_info.value.response.status_code == 500 + + +def test_seam_http_raises_http_error_on_json_without_error_object(recording_server): + with recording_server([(500, {"message": "Some error"})]) as (endpoint, _): + seam = Seam.from_api_key("seam_apikey_token", endpoint=endpoint) + + with pytest.raises(niquests.HTTPError) as exc_info: + seam.devices.list() + + assert exc_info.value.response.status_code == 500 + + +def test_seam_http_raises_http_error_on_error_object_without_type_and_message( + recording_server, +): + with recording_server([(500, {"error": {"code": 500}})]) as (endpoint, _): + seam = Seam.from_api_key("seam_apikey_token", endpoint=endpoint) + + with pytest.raises(niquests.HTTPError) as exc_info: + seam.devices.list() + + assert exc_info.value.response.status_code == 500