Coverage for tests / test_file_and_form_order_issue_9116.py: 100%
39 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +0000
1"""
2Regression test, Error 422 if Form is declared before File
3See https://github.com/tiangolo/fastapi/discussions/9116
4"""
6from pathlib import Path 1abcd
7from typing import Annotated 1abcd
9import pytest 1abcd
10from fastapi import FastAPI, File, Form 1abcd
11from fastapi.testclient import TestClient 1abcd
13app = FastAPI() 1abcd
16@app.post("/file_before_form") 1abcd
17def file_before_form( 1abcd
18 file: bytes = File(),
19 city: str = Form(),
20):
21 return {"file_content": file, "city": city} 1lmno
24@app.post("/file_after_form") 1abcd
25def file_after_form( 1abcd
26 city: str = Form(),
27 file: bytes = File(),
28):
29 return {"file_content": file, "city": city} 1pGqr
32@app.post("/file_list_before_form") 1abcd
33def file_list_before_form( 1abcd
34 files: Annotated[list[bytes], File()],
35 city: Annotated[str, Form()],
36):
37 return {"file_contents": files, "city": city} 1stuv
40@app.post("/file_list_after_form") 1abcd
41def file_list_after_form( 1abcd
42 city: Annotated[str, Form()],
43 files: Annotated[list[bytes], File()],
44):
45 return {"file_contents": files, "city": city} 1wHxy
48client = TestClient(app) 1abcd
51@pytest.fixture 1abcd
52def tmp_file_1(tmp_path: Path) -> Path: 1abcd
53 f = tmp_path / "example1.txt" 1zAefBgCDhiEFjk
54 f.write_text("foo") 1zAefBgCDhiEFjk
55 return f 1zAefBgCDhiEFjk
58@pytest.fixture 1abcd
59def tmp_file_2(tmp_path: Path) -> Path: 1abcd
60 f = tmp_path / "example2.txt" 1efghijk
61 f.write_text("bar") 1efghijk
62 return f 1efghijk
65@pytest.mark.parametrize("endpoint_path", ("/file_before_form", "/file_after_form")) 1abcd
66def test_file_form_order(endpoint_path: str, tmp_file_1: Path): 1abcd
67 response = client.post( 1plmqnro
68 url=endpoint_path,
69 data={"city": "Thimphou"},
70 files={"file": (tmp_file_1.name, tmp_file_1.read_bytes())},
71 )
72 assert response.status_code == 200, response.text 1plmqnro
73 assert response.json() == {"file_content": "foo", "city": "Thimphou"} 1plmqnro
76@pytest.mark.parametrize( 1abcd
77 "endpoint_path", ("/file_list_before_form", "/file_list_after_form")
78)
79def test_file_list_form_order(endpoint_path: str, tmp_file_1: Path, tmp_file_2: Path): 1abcd
80 response = client.post( 1wstxuyv
81 url=endpoint_path,
82 data={"city": "Thimphou"},
83 files=(
84 ("files", (tmp_file_1.name, tmp_file_1.read_bytes())),
85 ("files", (tmp_file_2.name, tmp_file_2.read_bytes())),
86 ),
87 )
88 assert response.status_code == 200, response.text 1wstxuyv
89 assert response.json() == {"file_contents": ["foo", "bar"], "city": "Thimphou"} 1wstxuyv