Coverage for tests/test_dependency_duplicates.py: 100%

44 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-08-08 03:53 +0000

1from typing import List 1abcde

2 

3from dirty_equals import IsDict 1abcde

4from fastapi import Depends, FastAPI 1abcde

5from fastapi.testclient import TestClient 1abcde

6from pydantic import BaseModel 1abcde

7 

8app = FastAPI() 1abcde

9 

10client = TestClient(app) 1abcde

11 

12 

13class Item(BaseModel): 1abcde

14 data: str 1abcde

15 

16 

17def duplicate_dependency(item: Item): 1abcde

18 return item 1abcde

19 

20 

21def dependency(item2: Item): 1abcde

22 return item2 1abcde

23 

24 

25def sub_duplicate_dependency( 1abcde

26 item: Item, sub_item: Item = Depends(duplicate_dependency) 

27): 

28 return [item, sub_item] 1abcde

29 

30 

31@app.post("/with-duplicates") 1abcde

32async def with_duplicates(item: Item, item2: Item = Depends(duplicate_dependency)): 1abcde

33 return [item, item2] 1abcde

34 

35 

36@app.post("/no-duplicates") 1abcde

37async def no_duplicates(item: Item, item2: Item = Depends(dependency)): 1abcde

38 return [item, item2] 1abcde

39 

40 

41@app.post("/with-duplicates-sub") 1abcde

42async def no_duplicates_sub( 1abcde

43 item: Item, sub_items: List[Item] = Depends(sub_duplicate_dependency) 

44): 

45 return [item, sub_items] 1abcde

46 

47 

48def test_no_duplicates_invalid(): 1abcde

49 response = client.post("/no-duplicates", json={"item": {"data": "myitem"}}) 1abcde

50 assert response.status_code == 422, response.text 1abcde

51 assert response.json() == IsDict( 1abcde

52 { 

53 "detail": [ 

54 { 

55 "type": "missing", 

56 "loc": ["body", "item2"], 

57 "msg": "Field required", 

58 "input": None, 

59 } 

60 ] 

61 } 

62 ) | IsDict( 

63 # TODO: remove when deprecating Pydantic v1 

64 { 

65 "detail": [ 

66 { 

67 "loc": ["body", "item2"], 

68 "msg": "field required", 

69 "type": "value_error.missing", 

70 } 

71 ] 

72 } 

73 ) 

74 

75 

76def test_no_duplicates(): 1abcde

77 response = client.post( 1abcde

78 "/no-duplicates", 

79 json={"item": {"data": "myitem"}, "item2": {"data": "myitem2"}}, 

80 ) 

81 assert response.status_code == 200, response.text 1abcde

82 assert response.json() == [{"data": "myitem"}, {"data": "myitem2"}] 1abcde

83 

84 

85def test_duplicates(): 1abcde

86 response = client.post("/with-duplicates", json={"data": "myitem"}) 1abcde

87 assert response.status_code == 200, response.text 1abcde

88 assert response.json() == [{"data": "myitem"}, {"data": "myitem"}] 1abcde

89 

90 

91def test_sub_duplicates(): 1abcde

92 response = client.post("/with-duplicates-sub", json={"data": "myitem"}) 1abcde

93 assert response.status_code == 200, response.text 1abcde

94 assert response.json() == [ 1abcde

95 {"data": "myitem"}, 

96 [{"data": "myitem"}, {"data": "myitem"}], 

97 ] 

98 

99 

100def test_openapi_schema(): 1abcde

101 response = client.get("/openapi.json") 1abcde

102 assert response.status_code == 200, response.text 1abcde

103 assert response.json() == { 1abcde

104 "openapi": "3.1.0", 

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

106 "paths": { 

107 "/with-duplicates": { 

108 "post": { 

109 "summary": "With Duplicates", 

110 "operationId": "with_duplicates_with_duplicates_post", 

111 "requestBody": { 

112 "content": { 

113 "application/json": { 

114 "schema": {"$ref": "#/components/schemas/Item"} 

115 } 

116 }, 

117 "required": True, 

118 }, 

119 "responses": { 

120 "200": { 

121 "description": "Successful Response", 

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

123 }, 

124 "422": { 

125 "description": "Validation Error", 

126 "content": { 

127 "application/json": { 

128 "schema": { 

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

130 } 

131 } 

132 }, 

133 }, 

134 }, 

135 } 

136 }, 

137 "/no-duplicates": { 

138 "post": { 

139 "summary": "No Duplicates", 

140 "operationId": "no_duplicates_no_duplicates_post", 

141 "requestBody": { 

142 "content": { 

143 "application/json": { 

144 "schema": { 

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

146 } 

147 } 

148 }, 

149 "required": True, 

150 }, 

151 "responses": { 

152 "200": { 

153 "description": "Successful Response", 

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

155 }, 

156 "422": { 

157 "description": "Validation Error", 

158 "content": { 

159 "application/json": { 

160 "schema": { 

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

162 } 

163 } 

164 }, 

165 }, 

166 }, 

167 } 

168 }, 

169 "/with-duplicates-sub": { 

170 "post": { 

171 "summary": "No Duplicates Sub", 

172 "operationId": "no_duplicates_sub_with_duplicates_sub_post", 

173 "requestBody": { 

174 "content": { 

175 "application/json": { 

176 "schema": {"$ref": "#/components/schemas/Item"} 

177 } 

178 }, 

179 "required": True, 

180 }, 

181 "responses": { 

182 "200": { 

183 "description": "Successful Response", 

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

185 }, 

186 "422": { 

187 "description": "Validation Error", 

188 "content": { 

189 "application/json": { 

190 "schema": { 

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

192 } 

193 } 

194 }, 

195 }, 

196 }, 

197 } 

198 }, 

199 }, 

200 "components": { 

201 "schemas": { 

202 "Body_no_duplicates_no_duplicates_post": { 

203 "title": "Body_no_duplicates_no_duplicates_post", 

204 "required": ["item", "item2"], 

205 "type": "object", 

206 "properties": { 

207 "item": {"$ref": "#/components/schemas/Item"}, 

208 "item2": {"$ref": "#/components/schemas/Item"}, 

209 }, 

210 }, 

211 "HTTPValidationError": { 

212 "title": "HTTPValidationError", 

213 "type": "object", 

214 "properties": { 

215 "detail": { 

216 "title": "Detail", 

217 "type": "array", 

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

219 } 

220 }, 

221 }, 

222 "Item": { 

223 "title": "Item", 

224 "required": ["data"], 

225 "type": "object", 

226 "properties": {"data": {"title": "Data", "type": "string"}}, 

227 }, 

228 "ValidationError": { 

229 "title": "ValidationError", 

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

231 "type": "object", 

232 "properties": { 

233 "loc": { 

234 "title": "Location", 

235 "type": "array", 

236 "items": { 

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

238 }, 

239 }, 

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

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

242 }, 

243 }, 

244 } 

245 }, 

246 }