@ -6,7 +6,7 @@ This test validates that Form models correctly track which fields were
explicitly provided vs . which fields use defaults .
"""
from typing import Annotated
from typing_extensions import Annotated
from fastapi import FastAPI , Form , Header , Query
from fastapi . _compat import PYDANTIC_V2
@ -14,7 +14,7 @@ from fastapi.testclient import TestClient
from pydantic import BaseModel
class FormModelFieldsSet ( BaseModel ) :
class FormModelFieldsSet ( BaseModel ) - > None :
""" Model for testing fields_set metadata preservation. """
field_1 : bool = True
@ -26,7 +26,7 @@ app = FastAPI()
@app . post ( " /form-fields-set " )
async def form_fields_set_endpoint ( model : Annotated [ FormModelFieldsSet , Form ( ) ] ) :
async def form_fields_set_endpoint ( model : Annotated [ FormModelFieldsSet , Form ( ) ] ) - > None :
# Use correct attribute name for each Pydantic version
if PYDANTIC_V2 :
fields_set = list ( model . model_fields_set )
@ -39,7 +39,7 @@ async def form_fields_set_endpoint(model: Annotated[FormModelFieldsSet, Form()])
@app . post ( " /body-fields-set " )
async def body_fields_set_endpoint ( model : FormModelFieldsSet ) :
async def body_fields_set_endpoint ( model : FormModelFieldsSet ) - > None :
# Use correct attribute name for each Pydantic version
if PYDANTIC_V2 :
fields_set = list ( model . model_fields_set )
@ -52,14 +52,14 @@ async def body_fields_set_endpoint(model: FormModelFieldsSet):
def query_model (
name : Annotated [ str , Query ( ) ] = " query_default " ,
age : Annotated [ int , Query ( ) ] = 10 ,
) :
) - > None :
return { " name " : name , " age " : age }
@app . get ( " /header/default " )
def header_model (
x_token : Annotated [ str , Header ( ) ] = " header_default " ,
) :
) - > None :
return { " x_token " : x_token }
@ -69,35 +69,35 @@ client = TestClient(app)
class TestFormFieldsSetMetadata :
""" Test that Form models correctly preserve fields_set metadata. """
def test_form_empty_data_has_empty_fields_set ( self ) :
def test_form_empty_data_has_empty_fields_set ( self ) - > None :
""" Form with no data should have empty fields_set (matching JSON behavior). """
resp = client . post ( " /form-fields-set " , data = { } )
assert resp . status_code == 200 , resp . text
fields_set = resp . json ( ) [ " fields_set " ]
assert fields_set == [ ]
def test_body_empty_data_has_empty_fields_set ( self ) :
def test_body_empty_data_has_empty_fields_set ( self ) - > None :
""" JSON body with no data should have empty fields_set. """
resp = client . post ( " /body-fields-set " , json = { } )
assert resp . status_code == 200 , resp . text
fields_set = resp . json ( ) [ " fields_set " ]
assert fields_set == [ ]
def test_form_partial_data_tracks_provided_fields ( self ) :
def test_form_partial_data_tracks_provided_fields ( self ) - > None :
""" Form with partial data should only show provided fields in fields_set. """
resp = client . post ( " /form-fields-set " , data = { " field_1 " : " False " } )
assert resp . status_code == 200 , resp . text
fields_set = resp . json ( ) [ " fields_set " ]
assert fields_set == [ " field_1 " ]
def test_body_partial_data_tracks_provided_fields ( self ) :
def test_body_partial_data_tracks_provided_fields ( self ) - > None :
""" JSON body with partial data should only show provided fields. """
resp = client . post ( " /body-fields-set " , json = { " field_1 " : False } )
assert resp . status_code == 200 , resp . text
fields_set = resp . json ( ) [ " fields_set " ]
assert fields_set == [ " field_1 " ]
def test_form_all_fields_provided ( self ) :
def test_form_all_fields_provided ( self ) - > None :
""" Form with all fields should show all fields in fields_set. """
resp = client . post (
" /form-fields-set " ,
@ -107,7 +107,7 @@ class TestFormFieldsSetMetadata:
fields_set = resp . json ( ) [ " fields_set " ]
assert set ( fields_set ) == { " field_1 " , " field_2 " , " field_3 " }
def test_body_all_fields_provided ( self ) :
def test_body_all_fields_provided ( self ) - > None :
""" JSON body with all fields should show all fields in fields_set. """
resp = client . post (
" /body-fields-set " ,
@ -117,7 +117,7 @@ class TestFormFieldsSetMetadata:
fields_set = resp . json ( ) [ " fields_set " ]
assert set ( fields_set ) == { " field_1 " , " field_2 " , " field_3 " }
def test_form_field_set_to_default_value_is_tracked ( self ) :
def test_form_field_set_to_default_value_is_tracked ( self ) - > None :
""" Form field explicitly set to default value should appear in fields_set. """
# Same as default=True, but explicitly provided
resp = client . post ( " /form-fields-set " , data = { " field_1 " : " True " } )
@ -125,14 +125,14 @@ class TestFormFieldsSetMetadata:
fields_set = resp . json ( ) [ " fields_set " ]
assert fields_set == [ " field_1 " ]
def test_body_field_set_to_default_value_is_tracked ( self ) :
def test_body_field_set_to_default_value_is_tracked ( self ) - > None :
""" JSON body field explicitly set to default value should appear in fields_set. """
resp = client . post ( " /body-fields-set " , json = { " field_1 " : True } )
assert resp . status_code == 200 , resp . text
fields_set = resp . json ( ) [ " fields_set " ]
assert fields_set == [ " field_1 " ]
def test_form_body_consistency ( self ) :
def test_form_body_consistency ( self ) - > None :
"""
Verify that body and form behave consistently .
Form fields_set should match JSON body fields_set for equivalent data .
@ -160,21 +160,21 @@ class TestNonFormCoverage:
This ensures line 762 of utils . py is covered and legacy behavior is preserved .
"""
def test_query_params_missing_uses_defaults ( self ) :
def test_query_params_missing_uses_defaults ( self ) - > None :
""" Test Query input where fields are missing -> returns default. """
response = client . get ( " /query/default " )
assert response . status_code == 200
data = response . json ( )
assert data == { " name " : " query_default " , " age " : 10 }
def test_header_params_missing_uses_defaults ( self ) :
def test_header_params_missing_uses_defaults ( self ) - > None :
""" Test Header input where fields are missing -> returns default. """
response = client . get ( " /header/default " )
assert response . status_code == 200
data = response . json ( )
assert data == { " x_token " : " header_default " }
def test_query_params_provided ( self ) :
def test_query_params_provided ( self ) - > None :
""" Test Query input where fields are provided -> returns value. """
response = client . get ( " /query/default?name=overridden&age=99 " )
assert response . status_code == 200