Coverage for tests/test_tutorial/test_request_form_models/test_tutorial002.py: 100%

44 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2025-05-05 00:03 +0000

1import importlib 1abcdef

2 

3import pytest 1abcdef

4from fastapi.testclient import TestClient 1abcdef

5 

6from ...utils import needs_py39, needs_pydanticv2 1abcdef

7 

8 

9@pytest.fixture( 1abcdef

10 name="client", 

11 params=[ 

12 "tutorial002", 

13 "tutorial002_an", 

14 pytest.param("tutorial002_an_py39", marks=needs_py39), 

15 ], 

16) 

17def get_client(request: pytest.FixtureRequest): 1abcdef

18 mod = importlib.import_module(f"docs_src.request_form_models.{request.param}") 1abcdef

19 

20 client = TestClient(mod.app) 1abcdef

21 return client 1abcdef

22 

23 

24@needs_pydanticv2 1abcdef

25def test_post_body_form(client: TestClient): 1abcdef

26 response = client.post("/login/", data={"username": "Foo", "password": "secret"}) 1ghijkl

27 assert response.status_code == 200 1ghijkl

28 assert response.json() == {"username": "Foo", "password": "secret"} 1ghijkl

29 

30 

31@needs_pydanticv2 1abcdef

32def test_post_body_extra_form(client: TestClient): 1abcdef

33 response = client.post( 1mnopqr

34 "/login/", data={"username": "Foo", "password": "secret", "extra": "extra"} 

35 ) 

36 assert response.status_code == 422 1mnopqr

37 assert response.json() == { 1mnopqr

38 "detail": [ 

39 { 

40 "type": "extra_forbidden", 

41 "loc": ["body", "extra"], 

42 "msg": "Extra inputs are not permitted", 

43 "input": "extra", 

44 } 

45 ] 

46 } 

47 

48 

49@needs_pydanticv2 1abcdef

50def test_post_body_form_no_password(client: TestClient): 1abcdef

51 response = client.post("/login/", data={"username": "Foo"}) 1stuvwx

52 assert response.status_code == 422 1stuvwx

53 assert response.json() == { 1stuvwx

54 "detail": [ 

55 { 

56 "type": "missing", 

57 "loc": ["body", "password"], 

58 "msg": "Field required", 

59 "input": {"username": "Foo"}, 

60 } 

61 ] 

62 } 

63 

64 

65@needs_pydanticv2 1abcdef

66def test_post_body_form_no_username(client: TestClient): 1abcdef

67 response = client.post("/login/", data={"password": "secret"}) 1yzABCD

68 assert response.status_code == 422 1yzABCD

69 assert response.json() == { 1yzABCD

70 "detail": [ 

71 { 

72 "type": "missing", 

73 "loc": ["body", "username"], 

74 "msg": "Field required", 

75 "input": {"password": "secret"}, 

76 } 

77 ] 

78 } 

79 

80 

81@needs_pydanticv2 1abcdef

82def test_post_body_form_no_data(client: TestClient): 1abcdef

83 response = client.post("/login/") 1EFGHIJ

84 assert response.status_code == 422 1EFGHIJ

85 assert response.json() == { 1EFGHIJ

86 "detail": [ 

87 { 

88 "type": "missing", 

89 "loc": ["body", "username"], 

90 "msg": "Field required", 

91 "input": {}, 

92 }, 

93 { 

94 "type": "missing", 

95 "loc": ["body", "password"], 

96 "msg": "Field required", 

97 "input": {}, 

98 }, 

99 ] 

100 } 

101 

102 

103@needs_pydanticv2 1abcdef

104def test_post_body_json(client: TestClient): 1abcdef

105 response = client.post("/login/", json={"username": "Foo", "password": "secret"}) 1KLMNOP

106 assert response.status_code == 422, response.text 1KLMNOP

107 assert response.json() == { 1KLMNOP

108 "detail": [ 

109 { 

110 "type": "missing", 

111 "loc": ["body", "username"], 

112 "msg": "Field required", 

113 "input": {}, 

114 }, 

115 { 

116 "type": "missing", 

117 "loc": ["body", "password"], 

118 "msg": "Field required", 

119 "input": {}, 

120 }, 

121 ] 

122 } 

123 

124 

125@needs_pydanticv2 1abcdef

126def test_openapi_schema(client: TestClient): 1abcdef

127 response = client.get("/openapi.json") 1QRSTUV

128 assert response.status_code == 200, response.text 1QRSTUV

129 assert response.json() == { 1QRSTUV

130 "openapi": "3.1.0", 

131 "info": {"title": "FastAPI", "version": "0.1.0"}, 

132 "paths": { 

133 "/login/": { 

134 "post": { 

135 "responses": { 

136 "200": { 

137 "description": "Successful Response", 

138 "content": {"application/json": {"schema": {}}}, 

139 }, 

140 "422": { 

141 "description": "Validation Error", 

142 "content": { 

143 "application/json": { 

144 "schema": { 

145 "$ref": "#/components/schemas/HTTPValidationError" 

146 } 

147 } 

148 }, 

149 }, 

150 }, 

151 "summary": "Login", 

152 "operationId": "login_login__post", 

153 "requestBody": { 

154 "content": { 

155 "application/x-www-form-urlencoded": { 

156 "schema": {"$ref": "#/components/schemas/FormData"} 

157 } 

158 }, 

159 "required": True, 

160 }, 

161 } 

162 } 

163 }, 

164 "components": { 

165 "schemas": { 

166 "FormData": { 

167 "properties": { 

168 "username": {"type": "string", "title": "Username"}, 

169 "password": {"type": "string", "title": "Password"}, 

170 }, 

171 "additionalProperties": False, 

172 "type": "object", 

173 "required": ["username", "password"], 

174 "title": "FormData", 

175 }, 

176 "ValidationError": { 

177 "title": "ValidationError", 

178 "required": ["loc", "msg", "type"], 

179 "type": "object", 

180 "properties": { 

181 "loc": { 

182 "title": "Location", 

183 "type": "array", 

184 "items": { 

185 "anyOf": [{"type": "string"}, {"type": "integer"}] 

186 }, 

187 }, 

188 "msg": {"title": "Message", "type": "string"}, 

189 "type": {"title": "Error Type", "type": "string"}, 

190 }, 

191 }, 

192 "HTTPValidationError": { 

193 "title": "HTTPValidationError", 

194 "type": "object", 

195 "properties": { 

196 "detail": { 

197 "title": "Detail", 

198 "type": "array", 

199 "items": {"$ref": "#/components/schemas/ValidationError"}, 

200 } 

201 }, 

202 }, 

203 } 

204 }, 

205 }