diff --git a/tests/test_json_error_improvements.py b/tests/test_json_body_decode_error.py similarity index 68% rename from tests/test_json_error_improvements.py rename to tests/test_json_body_decode_error.py index 764ee13bf..2bd5f36b6 100644 --- a/tests/test_json_error_improvements.py +++ b/tests/test_json_body_decode_error.py @@ -1,3 +1,4 @@ +import pytest from dirty_equals import IsDict from fastapi import FastAPI from fastapi.testclient import TestClient @@ -6,6 +7,13 @@ from pydantic import BaseModel app = FastAPI() +INVALID_JSON = """ +{ + "name": "Test", + "price": 'invalid' +}""" + + class Item(BaseModel): name: str price: float @@ -41,14 +49,8 @@ def test_json_decode_error_single_line(): def test_json_decode_error_multiline(): - invalid_json = """ -{ - "name": "Test", - "price": 'invalid' -}""" - response = client.post( - "/items/", content=invalid_json, headers={"Content-Type": "application/json"} + "/items/", content=INVALID_JSON, headers={"Content-Type": "application/json"} ) assert response.status_code == 422 @@ -63,22 +65,6 @@ def test_json_decode_error_multiline(): assert "invalid" in error["ctx"]["snippet"] -def test_json_decode_error_shows_snippet(): - long_json = '{"very_long_field_name_here": "some value", "another_field": invalid}' - - response = client.post( - "/items/", content=long_json, headers={"Content-Type": "application/json"} - ) - - assert response.status_code == 422 - error = response.json()["detail"][0] - - assert error["msg"] == "JSON decode error" - assert error["input"] == {} - assert "invalid" in error["ctx"]["snippet"] - assert len(error["ctx"]["snippet"]) <= 83 - - def test_json_decode_error_empty_body(): response = client.post( "/items/", content="", headers={"Content-Type": "application/json"} @@ -130,13 +116,32 @@ def test_json_decode_error_unclosed_brace(): assert "snippet" in error["ctx"] -def test_json_decode_error_in_middle_of_long_document(): - # Create a JSON with error early in a long document (need >40 chars after error) - # The error is at position for "invalid" which needs at least 41 chars after it - long_json = '{"field": invalid, "padding_field": "this needs to be long enough that we have more than forty characters after the error position"}' - +@pytest.mark.parametrize( + "json_content,expected_starts_with_ellipsis,expected_ends_with_ellipsis", + [ + ( + '{"field": invalid, "padding_field": "this needs to be long enough that we have more than forty characters after the error position"}', + False, + True, + ), + ( + '{"very_long_field_name_here": "some value that is long enough to push us past the forty character mark", "another_field": invalid}', + True, + False, + ), + ( + '{"very_long_field_name_here": "some value", "field": invalid, "padding_field": "this needs to be long enough that we have more than forty characters after the error position"}', + True, + True, + ), + ('{"field": invalid}', False, False), + ], +) +def test_json_decode_error_snippet_ellipsis( + json_content, expected_starts_with_ellipsis, expected_ends_with_ellipsis +): response = client.post( - "/items/", content=long_json, headers={"Content-Type": "application/json"} + "/items/", content=json_content, headers={"Content-Type": "application/json"} ) assert response.status_code == 422 @@ -144,19 +149,9 @@ def test_json_decode_error_in_middle_of_long_document(): assert error["msg"] == "JSON decode error" assert error["input"] == {} - assert error["ctx"]["snippet"].endswith("...") assert "invalid" in error["ctx"]["snippet"] assert error["type"] == "json_invalid" - -def test_successful_item_creation(): - response = client.post( - "/items/", - json={"name": "Test Item", "price": 19.99, "description": "A test item"}, - ) - - assert response.status_code == 200 - data = response.json() - assert data["name"] == "Test Item" - assert data["price"] == 19.99 - assert data["description"] == "A test item" + snippet = error["ctx"]["snippet"] + assert snippet.startswith("...") == expected_starts_with_ellipsis + assert snippet.endswith("...") == expected_ends_with_ellipsis