Coverage for tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001_py310.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 1idefgh

2from fastapi.testclient import TestClient 1idefgh

3from sqlalchemy import inspect 1idefgh

4from sqlalchemy.engine.reflection import Inspector 1idefgh

5from sqlmodel import create_engine 1idefgh

6from sqlmodel.pool import StaticPool 1idefgh

7 

8from ....conftest import needs_py310 1idefgh

9 

10 

11@needs_py310 1idefgh

12def test_tutorial(clear_sqlmodel): 1defgh

13 from docs_src.tutorial.fastapi.multiple_models import tutorial001_py310 as mod 1abc

14 

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

16 mod.engine = create_engine( 1abc

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

18 ) 

19 

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

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

22 hero2_data = { 1abc

23 "name": "Spider-Boy", 

24 "secret_name": "Pedro Parqueador", 

25 "id": 9000, 

26 } 

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

28 data = response.json() 1abc

29 

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

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

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

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

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

35 

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

37 data = response.json() 1abc

38 

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

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

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

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

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 1abc

47 

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

49 data = response.json() 1abc

50 

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

52 assert len(data) == 2 1abc

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

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

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

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

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

58 

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

60 assert response.status_code == 200, response.text 1abc

61 

62 assert response.json() == { 1abc

63 "openapi": "3.1.0", 

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

65 "paths": { 

66 "/heroes/": { 

67 "get": { 

68 "summary": "Read Heroes", 

69 "operationId": "read_heroes_heroes__get", 

70 "responses": { 

71 "200": { 

72 "description": "Successful Response", 

73 "content": { 

74 "application/json": { 

75 "schema": { 

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

77 "type": "array", 

78 "items": { 

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

80 }, 

81 } 

82 } 

83 }, 

84 } 

85 }, 

86 }, 

87 "post": { 

88 "summary": "Create Hero", 

89 "operationId": "create_hero_heroes__post", 

90 "requestBody": { 

91 "content": { 

92 "application/json": { 

93 "schema": { 

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

95 } 

96 } 

97 }, 

98 "required": True, 

99 }, 

100 "responses": { 

101 "200": { 

102 "description": "Successful Response", 

103 "content": { 

104 "application/json": { 

105 "schema": { 

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

107 } 

108 } 

109 }, 

110 }, 

111 "422": { 

112 "description": "Validation Error", 

113 "content": { 

114 "application/json": { 

115 "schema": { 

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

117 } 

118 } 

119 }, 

120 }, 

121 }, 

122 }, 

123 } 

124 }, 

125 "components": { 

126 "schemas": { 

127 "HTTPValidationError": { 

128 "title": "HTTPValidationError", 

129 "type": "object", 

130 "properties": { 

131 "detail": { 

132 "title": "Detail", 

133 "type": "array", 

134 "items": { 

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

136 }, 

137 } 

138 }, 

139 }, 

140 "HeroCreate": { 

141 "title": "HeroCreate", 

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

143 "type": "object", 

144 "properties": { 

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

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

147 "age": IsDict( 

148 { 

149 "title": "Age", 

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

151 } 

152 ) 

153 | IsDict( 

154 # TODO: remove when deprecating Pydantic v1 

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

156 ), 

157 }, 

158 }, 

159 "HeroPublic": { 

160 "title": "HeroPublic", 

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

162 "type": "object", 

163 "properties": { 

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

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 }, 

178 }, 

179 "ValidationError": { 

180 "title": "ValidationError", 

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

182 "type": "object", 

183 "properties": { 

184 "loc": { 

185 "title": "Location", 

186 "type": "array", 

187 "items": { 

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

189 }, 

190 }, 

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

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

193 }, 

194 }, 

195 } 

196 }, 

197 } 

198 

199 # Test inherited indexes 

200 insp: Inspector = inspect(mod.engine) 1abc

201 indexes = insp.get_indexes(str(mod.Hero.__tablename__)) 1abc

202 expected_indexes = [ 1abc

203 { 

204 "name": "ix_hero_name", 

205 "dialect_options": {}, 

206 "column_names": ["name"], 

207 "unique": 0, 

208 }, 

209 { 

210 "name": "ix_hero_age", 

211 "dialect_options": {}, 

212 "column_names": ["age"], 

213 "unique": 0, 

214 }, 

215 ] 

216 for index in expected_indexes: 1abc

217 assert index in indexes, "This expected index should be in the indexes in DB" 1abc

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

219 indexes.pop(indexes.index(index)) 1abc

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