Coverage for tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002_py39.py: 100%

48 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-09-09 00:02 +0000

1from dirty_equals import IsDict 1jefghi

2from fastapi.testclient import TestClient 1jefghi

3from sqlalchemy import inspect 1jefghi

4from sqlalchemy.engine.reflection import Inspector 1jefghi

5from sqlmodel import create_engine 1jefghi

6from sqlmodel.pool import StaticPool 1jefghi

7 

8from ....conftest import needs_py39 1jefghi

9 

10 

11@needs_py39 1jefghi

12def test_tutorial(clear_sqlmodel): 1efghi

13 from docs_src.tutorial.fastapi.multiple_models import tutorial002_py39 as mod 1abcd

14 

15 mod.sqlite_url = "sqlite://" 1abcd

16 mod.engine = create_engine( 1abcd

17 mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool 

18 ) 

19 

20 with TestClient(mod.app) as client: 1abcd

21 hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} 1abcd

22 hero2_data = { 1abcd

23 "name": "Spider-Boy", 

24 "secret_name": "Pedro Parqueador", 

25 "id": 9000, 

26 } 

27 response = client.post("/heroes/", json=hero1_data) 1abcd

28 data = response.json() 1abcd

29 

30 assert response.status_code == 200, response.text 1abcd

31 assert data["name"] == hero1_data["name"] 1abcd

32 assert data["secret_name"] == hero1_data["secret_name"] 1abcd

33 assert data["id"] is not None 1abcd

34 assert data["age"] is None 1abcd

35 

36 response = client.post("/heroes/", json=hero2_data) 1abcd

37 data = response.json() 1abcd

38 

39 assert response.status_code == 200, response.text 1abcd

40 assert data["name"] == hero2_data["name"] 1abcd

41 assert data["secret_name"] == hero2_data["secret_name"] 1abcd

42 assert data["id"] != hero2_data["id"], ( 1abcd

43 "Now it's not possible to predefine the ID from the request, " 

44 "it's now set by the database" 

45 ) 

46 assert data["age"] is None 1abcd

47 

48 response = client.get("/heroes/") 1abcd

49 data = response.json() 1abcd

50 

51 assert response.status_code == 200, response.text 1abcd

52 assert len(data) == 2 1abcd

53 assert data[0]["name"] == hero1_data["name"] 1abcd

54 assert data[0]["secret_name"] == hero1_data["secret_name"] 1abcd

55 assert data[1]["name"] == hero2_data["name"] 1abcd

56 assert data[1]["secret_name"] == hero2_data["secret_name"] 1abcd

57 assert data[1]["id"] != hero2_data["id"] 1abcd

58 

59 response = client.get("/openapi.json") 1abcd

60 

61 assert response.status_code == 200, response.text 1abcd

62 

63 assert response.json() == { 1abcd

64 "openapi": "3.1.0", 

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

66 "paths": { 

67 "/heroes/": { 

68 "get": { 

69 "summary": "Read Heroes", 

70 "operationId": "read_heroes_heroes__get", 

71 "responses": { 

72 "200": { 

73 "description": "Successful Response", 

74 "content": { 

75 "application/json": { 

76 "schema": { 

77 "title": "Response Read Heroes Heroes Get", 

78 "type": "array", 

79 "items": { 

80 "$ref": "#/components/schemas/HeroPublic" 

81 }, 

82 } 

83 } 

84 }, 

85 } 

86 }, 

87 }, 

88 "post": { 

89 "summary": "Create Hero", 

90 "operationId": "create_hero_heroes__post", 

91 "requestBody": { 

92 "content": { 

93 "application/json": { 

94 "schema": { 

95 "$ref": "#/components/schemas/HeroCreate" 

96 } 

97 } 

98 }, 

99 "required": True, 

100 }, 

101 "responses": { 

102 "200": { 

103 "description": "Successful Response", 

104 "content": { 

105 "application/json": { 

106 "schema": { 

107 "$ref": "#/components/schemas/HeroPublic" 

108 } 

109 } 

110 }, 

111 }, 

112 "422": { 

113 "description": "Validation Error", 

114 "content": { 

115 "application/json": { 

116 "schema": { 

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

118 } 

119 } 

120 }, 

121 }, 

122 }, 

123 }, 

124 } 

125 }, 

126 "components": { 

127 "schemas": { 

128 "HTTPValidationError": { 

129 "title": "HTTPValidationError", 

130 "type": "object", 

131 "properties": { 

132 "detail": { 

133 "title": "Detail", 

134 "type": "array", 

135 "items": { 

136 "$ref": "#/components/schemas/ValidationError" 

137 }, 

138 } 

139 }, 

140 }, 

141 "HeroCreate": { 

142 "title": "HeroCreate", 

143 "required": ["name", "secret_name"], 

144 "type": "object", 

145 "properties": { 

146 "name": {"title": "Name", "type": "string"}, 

147 "secret_name": {"title": "Secret Name", "type": "string"}, 

148 "age": IsDict( 

149 { 

150 "title": "Age", 

151 "anyOf": [{"type": "integer"}, {"type": "null"}], 

152 } 

153 ) 

154 | IsDict( 

155 # TODO: remove when deprecating Pydantic v1 

156 {"title": "Age", "type": "integer"} 

157 ), 

158 }, 

159 }, 

160 "HeroPublic": { 

161 "title": "HeroPublic", 

162 "required": ["name", "secret_name", "id"], 

163 "type": "object", 

164 "properties": { 

165 "name": {"title": "Name", "type": "string"}, 

166 "secret_name": {"title": "Secret Name", "type": "string"}, 

167 "age": IsDict( 

168 { 

169 "title": "Age", 

170 "anyOf": [{"type": "integer"}, {"type": "null"}], 

171 } 

172 ) 

173 | IsDict( 

174 # TODO: remove when deprecating Pydantic v1 

175 {"title": "Age", "type": "integer"} 

176 ), 

177 "id": {"title": "Id", "type": "integer"}, 

178 }, 

179 }, 

180 "ValidationError": { 

181 "title": "ValidationError", 

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

183 "type": "object", 

184 "properties": { 

185 "loc": { 

186 "title": "Location", 

187 "type": "array", 

188 "items": { 

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

190 }, 

191 }, 

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

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

194 }, 

195 }, 

196 } 

197 }, 

198 } 

199 

200 # Test inherited indexes 

201 insp: Inspector = inspect(mod.engine) 1abcd

202 indexes = insp.get_indexes(str(mod.Hero.__tablename__)) 1abcd

203 expected_indexes = [ 1abcd

204 { 

205 "name": "ix_hero_age", 

206 "dialect_options": {}, 

207 "column_names": ["age"], 

208 "unique": 0, 

209 }, 

210 { 

211 "name": "ix_hero_name", 

212 "dialect_options": {}, 

213 "column_names": ["name"], 

214 "unique": 0, 

215 }, 

216 ] 

217 for index in expected_indexes: 1abcd

218 assert index in indexes, "This expected index should be in the indexes in DB" 1abcd

219 # Now that this index was checked, remove it from the list of indexes 

220 indexes.pop(indexes.index(index)) 1abcd

221 assert len(indexes) == 0, "The database should only have the expected indexes" 1abcd