Coverage for tests / test_forms_single_model.py: 100%
45 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-12 18:15 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-12 18:15 +0000
1from typing import Annotated, Optional 1abcd
3from fastapi import FastAPI, Form 1abcd
4from fastapi.testclient import TestClient 1abcd
5from pydantic import BaseModel, Field 1abcd
7app = FastAPI() 1abcd
10class FormModel(BaseModel): 1abcd
11 username: str 1abcd
12 lastname: str 1abcd
13 age: Optional[int] = None 1abcd
14 tags: list[str] = ["foo", "bar"] 1abcd
15 alias_with: str = Field(alias="with", default="nothing") 1abcd
18class FormModelExtraAllow(BaseModel): 1abcd
19 param: str 1abcd
21 model_config = {"extra": "allow"} 1abcd
24@app.post("/form/") 1abcd
25def post_form(user: Annotated[FormModel, Form()]): 1abcd
26 return user 1efghij
29@app.post("/form-extra-allow/") 1abcd
30def post_form_extra_allow(params: Annotated[FormModelExtraAllow, Form()]): 1abcd
31 return params 1klmnop
34client = TestClient(app) 1abcd
37def test_send_all_data(): 1abcd
38 response = client.post( 1fhj
39 "/form/",
40 data={
41 "username": "Rick",
42 "lastname": "Sanchez",
43 "age": "70",
44 "tags": ["plumbus", "citadel"],
45 "with": "something",
46 },
47 )
48 assert response.status_code == 200, response.text 1fhj
49 assert response.json() == { 1fhj
50 "username": "Rick",
51 "lastname": "Sanchez",
52 "age": 70,
53 "tags": ["plumbus", "citadel"],
54 "with": "something",
55 }
58def test_defaults(): 1abcd
59 response = client.post("/form/", data={"username": "Rick", "lastname": "Sanchez"}) 1egi
60 assert response.status_code == 200, response.text 1egi
61 assert response.json() == { 1egi
62 "username": "Rick",
63 "lastname": "Sanchez",
64 "age": None,
65 "tags": ["foo", "bar"],
66 "with": "nothing",
67 }
70def test_invalid_data(): 1abcd
71 response = client.post( 1qrs
72 "/form/",
73 data={
74 "username": "Rick",
75 "lastname": "Sanchez",
76 "age": "seventy",
77 "tags": ["plumbus", "citadel"],
78 },
79 )
80 assert response.status_code == 422, response.text 1qrs
81 assert response.json() == { 1qrs
82 "detail": [
83 {
84 "type": "int_parsing",
85 "loc": ["body", "age"],
86 "msg": "Input should be a valid integer, unable to parse string as an integer",
87 "input": "seventy",
88 }
89 ]
90 }
93def test_no_data(): 1abcd
94 response = client.post("/form/") 1tuv
95 assert response.status_code == 422, response.text 1tuv
96 assert response.json() == { 1tuv
97 "detail": [
98 {
99 "type": "missing",
100 "loc": ["body", "username"],
101 "msg": "Field required",
102 "input": {"tags": ["foo", "bar"], "with": "nothing"},
103 },
104 {
105 "type": "missing",
106 "loc": ["body", "lastname"],
107 "msg": "Field required",
108 "input": {"tags": ["foo", "bar"], "with": "nothing"},
109 },
110 ]
111 }
114def test_extra_param_single(): 1abcd
115 response = client.post( 1lnp
116 "/form-extra-allow/",
117 data={
118 "param": "123",
119 "extra_param": "456",
120 },
121 )
122 assert response.status_code == 200, response.text 1lnp
123 assert response.json() == { 1lnp
124 "param": "123",
125 "extra_param": "456",
126 }
129def test_extra_param_list(): 1abcd
130 response = client.post( 1kmo
131 "/form-extra-allow/",
132 data={
133 "param": "123",
134 "extra_params": ["456", "789"],
135 },
136 )
137 assert response.status_code == 200, response.text 1kmo
138 assert response.json() == { 1kmo
139 "param": "123",
140 "extra_params": ["456", "789"],
141 }