Coverage for tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001.py: 100%

83 statements  

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

1from dirty_equals import IsDict 1ghijkl

2from fastapi.testclient import TestClient 1ghijkl

3from sqlmodel import create_engine 1ghijkl

4from sqlmodel.pool import StaticPool 1ghijkl

5 

6 

7def test_tutorial(clear_sqlmodel): 1ghijkl

8 from docs_src.tutorial.fastapi.relationships import tutorial001 as mod 1fabcde

9 

10 mod.sqlite_url = "sqlite://" 1fabcde

11 mod.engine = create_engine( 1fabcde

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

13 ) 

14 

15 with TestClient(mod.app) as client: 1fabcde

16 team_preventers = {"name": "Preventers", "headquarters": "Sharp Tower"} 1fabcde

17 team_z_force = {"name": "Z-Force", "headquarters": "Sister Margaret's Bar"} 1fabcde

18 response = client.post("/teams/", json=team_preventers) 1fabcde

19 assert response.status_code == 200, response.text 1fabcde

20 team_preventers_data = response.json() 1fabcde

21 team_preventers_id = team_preventers_data["id"] 1fabcde

22 response = client.post("/teams/", json=team_z_force) 1fabcde

23 assert response.status_code == 200, response.text 1fabcde

24 team_z_force_data = response.json() 1fabcde

25 team_z_force_id = team_z_force_data["id"] 1fabcde

26 response = client.get("/teams/") 1fabcde

27 data = response.json() 1fabcde

28 assert len(data) == 2 1fabcde

29 response = client.get("/teams/9000") 1fabcde

30 assert response.status_code == 404, response.text 1fabcde

31 response = client.patch( 1fabcde

32 f"/teams/{team_preventers_id}", json={"headquarters": "Preventers Tower"} 

33 ) 

34 data = response.json() 1fabcde

35 assert response.status_code == 200, response.text 1fabcde

36 assert data["name"] == team_preventers["name"] 1fabcde

37 assert data["headquarters"] == "Preventers Tower" 1fabcde

38 response = client.patch("/teams/9000", json={"name": "Freedom League"}) 1fabcde

39 assert response.status_code == 404, response.text 1fabcde

40 

41 hero1_data = { 1abcde

42 "name": "Deadpond", 

43 "secret_name": "Dive Wilson", 

44 "team_id": team_z_force_id, 

45 } 

46 hero2_data = { 1abcde

47 "name": "Spider-Boy", 

48 "secret_name": "Pedro Parqueador", 

49 "id": 9000, 

50 } 

51 hero3_data = { 1abcde

52 "name": "Rusty-Man", 

53 "secret_name": "Tommy Sharp", 

54 "age": 48, 

55 "team_id": team_preventers_id, 

56 } 

57 response = client.post("/heroes/", json=hero1_data) 1fabcde

58 assert response.status_code == 200, response.text 1fabcde

59 hero1 = response.json() 1fabcde

60 hero1_id = hero1["id"] 1fabcde

61 response = client.post("/heroes/", json=hero2_data) 1fabcde

62 assert response.status_code == 200, response.text 1fabcde

63 hero2 = response.json() 1fabcde

64 hero2_id = hero2["id"] 1fabcde

65 response = client.post("/heroes/", json=hero3_data) 1fabcde

66 assert response.status_code == 200, response.text 1fabcde

67 response = client.get("/heroes/9000") 1fabcde

68 assert response.status_code == 404, response.text 1fabcde

69 response = client.get("/heroes/") 1fabcde

70 assert response.status_code == 200, response.text 1fabcde

71 data = response.json() 1fabcde

72 assert len(data) == 3 1fabcde

73 response = client.get(f"/heroes/{hero1_id}") 1fabcde

74 assert response.status_code == 200, response.text 1fabcde

75 data = response.json() 1fabcde

76 assert data["name"] == hero1_data["name"] 1fabcde

77 assert data["team"]["name"] == team_z_force["name"] 1fabcde

78 response = client.patch( 1fabcde

79 f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"} 

80 ) 

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

82 response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) 1fabcde

83 assert response.status_code == 404, response.text 1fabcde

84 response = client.delete(f"/heroes/{hero2_id}") 1fabcde

85 assert response.status_code == 200, response.text 1fabcde

86 response = client.get("/heroes/") 1fabcde

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

88 data = response.json() 1fabcde

89 assert len(data) == 2 1fabcde

90 response = client.delete("/heroes/9000") 1fabcde

91 assert response.status_code == 404, response.text 1fabcde

92 

93 response = client.get(f"/teams/{team_preventers_id}") 1fabcde

94 data = response.json() 1fabcde

95 assert response.status_code == 200, response.text 1fabcde

96 assert data["name"] == team_preventers_data["name"] 1fabcde

97 assert data["heroes"][0]["name"] == hero3_data["name"] 1fabcde

98 

99 response = client.delete(f"/teams/{team_preventers_id}") 1fabcde

100 assert response.status_code == 200, response.text 1fabcde

101 response = client.delete("/teams/9000") 1fabcde

102 assert response.status_code == 404, response.text 1fabcde

103 response = client.get("/teams/") 1fabcde

104 assert response.status_code == 200, response.text 1fabcde

105 data = response.json() 1fabcde

106 assert len(data) == 1 1fabcde

107 

108 response = client.get("/openapi.json") 1fabcde

109 assert response.status_code == 200, response.text 1fabcde

110 assert response.json() == { 1fabcde

111 "openapi": "3.1.0", 

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

113 "paths": { 

114 "/heroes/": { 

115 "get": { 

116 "summary": "Read Heroes", 

117 "operationId": "read_heroes_heroes__get", 

118 "parameters": [ 

119 { 

120 "required": False, 

121 "schema": { 

122 "title": "Offset", 

123 "type": "integer", 

124 "default": 0, 

125 }, 

126 "name": "offset", 

127 "in": "query", 

128 }, 

129 { 

130 "required": False, 

131 "schema": { 

132 "title": "Limit", 

133 "maximum": 100.0, 

134 "type": "integer", 

135 "default": 100, 

136 }, 

137 "name": "limit", 

138 "in": "query", 

139 }, 

140 ], 

141 "responses": { 

142 "200": { 

143 "description": "Successful Response", 

144 "content": { 

145 "application/json": { 

146 "schema": { 

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

148 "type": "array", 

149 "items": { 

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

151 }, 

152 } 

153 } 

154 }, 

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 "post": { 

169 "summary": "Create Hero", 

170 "operationId": "create_hero_heroes__post", 

171 "requestBody": { 

172 "content": { 

173 "application/json": { 

174 "schema": { 

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

176 } 

177 } 

178 }, 

179 "required": True, 

180 }, 

181 "responses": { 

182 "200": { 

183 "description": "Successful Response", 

184 "content": { 

185 "application/json": { 

186 "schema": { 

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

188 } 

189 } 

190 }, 

191 }, 

192 "422": { 

193 "description": "Validation Error", 

194 "content": { 

195 "application/json": { 

196 "schema": { 

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

198 } 

199 } 

200 }, 

201 }, 

202 }, 

203 }, 

204 }, 

205 "/heroes/{hero_id}": { 

206 "get": { 

207 "summary": "Read Hero", 

208 "operationId": "read_hero_heroes__hero_id__get", 

209 "parameters": [ 

210 { 

211 "required": True, 

212 "schema": {"title": "Hero Id", "type": "integer"}, 

213 "name": "hero_id", 

214 "in": "path", 

215 } 

216 ], 

217 "responses": { 

218 "200": { 

219 "description": "Successful Response", 

220 "content": { 

221 "application/json": { 

222 "schema": { 

223 "$ref": "#/components/schemas/HeroPublicWithTeam" 

224 } 

225 } 

226 }, 

227 }, 

228 "422": { 

229 "description": "Validation Error", 

230 "content": { 

231 "application/json": { 

232 "schema": { 

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

234 } 

235 } 

236 }, 

237 }, 

238 }, 

239 }, 

240 "delete": { 

241 "summary": "Delete Hero", 

242 "operationId": "delete_hero_heroes__hero_id__delete", 

243 "parameters": [ 

244 { 

245 "required": True, 

246 "schema": {"title": "Hero Id", "type": "integer"}, 

247 "name": "hero_id", 

248 "in": "path", 

249 } 

250 ], 

251 "responses": { 

252 "200": { 

253 "description": "Successful Response", 

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

255 }, 

256 "422": { 

257 "description": "Validation Error", 

258 "content": { 

259 "application/json": { 

260 "schema": { 

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

262 } 

263 } 

264 }, 

265 }, 

266 }, 

267 }, 

268 "patch": { 

269 "summary": "Update Hero", 

270 "operationId": "update_hero_heroes__hero_id__patch", 

271 "parameters": [ 

272 { 

273 "required": True, 

274 "schema": {"title": "Hero Id", "type": "integer"}, 

275 "name": "hero_id", 

276 "in": "path", 

277 } 

278 ], 

279 "requestBody": { 

280 "content": { 

281 "application/json": { 

282 "schema": { 

283 "$ref": "#/components/schemas/HeroUpdate" 

284 } 

285 } 

286 }, 

287 "required": True, 

288 }, 

289 "responses": { 

290 "200": { 

291 "description": "Successful Response", 

292 "content": { 

293 "application/json": { 

294 "schema": { 

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

296 } 

297 } 

298 }, 

299 }, 

300 "422": { 

301 "description": "Validation Error", 

302 "content": { 

303 "application/json": { 

304 "schema": { 

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

306 } 

307 } 

308 }, 

309 }, 

310 }, 

311 }, 

312 }, 

313 "/teams/": { 

314 "get": { 

315 "summary": "Read Teams", 

316 "operationId": "read_teams_teams__get", 

317 "parameters": [ 

318 { 

319 "required": False, 

320 "schema": { 

321 "title": "Offset", 

322 "type": "integer", 

323 "default": 0, 

324 }, 

325 "name": "offset", 

326 "in": "query", 

327 }, 

328 { 

329 "required": False, 

330 "schema": { 

331 "title": "Limit", 

332 "maximum": 100.0, 

333 "type": "integer", 

334 "default": 100, 

335 }, 

336 "name": "limit", 

337 "in": "query", 

338 }, 

339 ], 

340 "responses": { 

341 "200": { 

342 "description": "Successful Response", 

343 "content": { 

344 "application/json": { 

345 "schema": { 

346 "title": "Response Read Teams Teams Get", 

347 "type": "array", 

348 "items": { 

349 "$ref": "#/components/schemas/TeamPublic" 

350 }, 

351 } 

352 } 

353 }, 

354 }, 

355 "422": { 

356 "description": "Validation Error", 

357 "content": { 

358 "application/json": { 

359 "schema": { 

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

361 } 

362 } 

363 }, 

364 }, 

365 }, 

366 }, 

367 "post": { 

368 "summary": "Create Team", 

369 "operationId": "create_team_teams__post", 

370 "requestBody": { 

371 "content": { 

372 "application/json": { 

373 "schema": { 

374 "$ref": "#/components/schemas/TeamCreate" 

375 } 

376 } 

377 }, 

378 "required": True, 

379 }, 

380 "responses": { 

381 "200": { 

382 "description": "Successful Response", 

383 "content": { 

384 "application/json": { 

385 "schema": { 

386 "$ref": "#/components/schemas/TeamPublic" 

387 } 

388 } 

389 }, 

390 }, 

391 "422": { 

392 "description": "Validation Error", 

393 "content": { 

394 "application/json": { 

395 "schema": { 

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

397 } 

398 } 

399 }, 

400 }, 

401 }, 

402 }, 

403 }, 

404 "/teams/{team_id}": { 

405 "get": { 

406 "summary": "Read Team", 

407 "operationId": "read_team_teams__team_id__get", 

408 "parameters": [ 

409 { 

410 "required": True, 

411 "schema": {"title": "Team Id", "type": "integer"}, 

412 "name": "team_id", 

413 "in": "path", 

414 } 

415 ], 

416 "responses": { 

417 "200": { 

418 "description": "Successful Response", 

419 "content": { 

420 "application/json": { 

421 "schema": { 

422 "$ref": "#/components/schemas/TeamPublicWithHeroes" 

423 } 

424 } 

425 }, 

426 }, 

427 "422": { 

428 "description": "Validation Error", 

429 "content": { 

430 "application/json": { 

431 "schema": { 

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

433 } 

434 } 

435 }, 

436 }, 

437 }, 

438 }, 

439 "delete": { 

440 "summary": "Delete Team", 

441 "operationId": "delete_team_teams__team_id__delete", 

442 "parameters": [ 

443 { 

444 "required": True, 

445 "schema": {"title": "Team Id", "type": "integer"}, 

446 "name": "team_id", 

447 "in": "path", 

448 } 

449 ], 

450 "responses": { 

451 "200": { 

452 "description": "Successful Response", 

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

454 }, 

455 "422": { 

456 "description": "Validation Error", 

457 "content": { 

458 "application/json": { 

459 "schema": { 

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

461 } 

462 } 

463 }, 

464 }, 

465 }, 

466 }, 

467 "patch": { 

468 "summary": "Update Team", 

469 "operationId": "update_team_teams__team_id__patch", 

470 "parameters": [ 

471 { 

472 "required": True, 

473 "schema": {"title": "Team Id", "type": "integer"}, 

474 "name": "team_id", 

475 "in": "path", 

476 } 

477 ], 

478 "requestBody": { 

479 "content": { 

480 "application/json": { 

481 "schema": { 

482 "$ref": "#/components/schemas/TeamUpdate" 

483 } 

484 } 

485 }, 

486 "required": True, 

487 }, 

488 "responses": { 

489 "200": { 

490 "description": "Successful Response", 

491 "content": { 

492 "application/json": { 

493 "schema": { 

494 "$ref": "#/components/schemas/TeamPublic" 

495 } 

496 } 

497 }, 

498 }, 

499 "422": { 

500 "description": "Validation Error", 

501 "content": { 

502 "application/json": { 

503 "schema": { 

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

505 } 

506 } 

507 }, 

508 }, 

509 }, 

510 }, 

511 }, 

512 }, 

513 "components": { 

514 "schemas": { 

515 "HTTPValidationError": { 

516 "title": "HTTPValidationError", 

517 "type": "object", 

518 "properties": { 

519 "detail": { 

520 "title": "Detail", 

521 "type": "array", 

522 "items": { 

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

524 }, 

525 } 

526 }, 

527 }, 

528 "HeroCreate": { 

529 "title": "HeroCreate", 

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

531 "type": "object", 

532 "properties": { 

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

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

535 "age": IsDict( 

536 { 

537 "title": "Age", 

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

539 } 

540 ) 

541 | IsDict( 

542 # TODO: remove when deprecating Pydantic v1 

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

544 ), 

545 "team_id": IsDict( 

546 { 

547 "title": "Team Id", 

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

549 } 

550 ) 

551 | IsDict( 

552 # TODO: remove when deprecating Pydantic v1 

553 {"title": "Team Id", "type": "integer"} 

554 ), 

555 }, 

556 }, 

557 "HeroPublic": { 

558 "title": "HeroPublic", 

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

560 "type": "object", 

561 "properties": { 

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

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

564 "age": IsDict( 

565 { 

566 "title": "Age", 

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

568 } 

569 ) 

570 | IsDict( 

571 # TODO: remove when deprecating Pydantic v1 

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

573 ), 

574 "team_id": IsDict( 

575 { 

576 "title": "Team Id", 

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

578 } 

579 ) 

580 | IsDict( 

581 # TODO: remove when deprecating Pydantic v1 

582 {"title": "Team Id", "type": "integer"} 

583 ), 

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

585 }, 

586 }, 

587 "HeroPublicWithTeam": { 

588 "title": "HeroPublicWithTeam", 

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

590 "type": "object", 

591 "properties": { 

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

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

594 "age": IsDict( 

595 { 

596 "title": "Age", 

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

598 } 

599 ) 

600 | IsDict( 

601 # TODO: remove when deprecating Pydantic v1 

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

603 ), 

604 "team_id": IsDict( 

605 { 

606 "title": "Team Id", 

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

608 } 

609 ) 

610 | IsDict( 

611 # TODO: remove when deprecating Pydantic v1 

612 {"title": "Team Id", "type": "integer"} 

613 ), 

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

615 "team": IsDict( 

616 { 

617 "anyOf": [ 

618 {"$ref": "#/components/schemas/TeamPublic"}, 

619 {"type": "null"}, 

620 ] 

621 } 

622 ) 

623 | IsDict( 

624 # TODO: remove when deprecating Pydantic v1 

625 {"$ref": "#/components/schemas/TeamPublic"} 

626 ), 

627 }, 

628 }, 

629 "HeroUpdate": { 

630 "title": "HeroUpdate", 

631 "type": "object", 

632 "properties": { 

633 "name": IsDict( 

634 { 

635 "title": "Name", 

636 "anyOf": [{"type": "string"}, {"type": "null"}], 

637 } 

638 ) 

639 | IsDict( 

640 # TODO: remove when deprecating Pydantic v1 

641 {"title": "Name", "type": "string"} 

642 ), 

643 "secret_name": IsDict( 

644 { 

645 "title": "Secret Name", 

646 "anyOf": [{"type": "string"}, {"type": "null"}], 

647 } 

648 ) 

649 | IsDict( 

650 # TODO: remove when deprecating Pydantic v1 

651 {"title": "Secret Name", "type": "string"} 

652 ), 

653 "age": IsDict( 

654 { 

655 "title": "Age", 

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

657 } 

658 ) 

659 | IsDict( 

660 # TODO: remove when deprecating Pydantic v1 

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

662 ), 

663 "team_id": IsDict( 

664 { 

665 "title": "Team Id", 

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

667 } 

668 ) 

669 | IsDict( 

670 # TODO: remove when deprecating Pydantic v1 

671 {"title": "Team Id", "type": "integer"} 

672 ), 

673 }, 

674 }, 

675 "TeamCreate": { 

676 "title": "TeamCreate", 

677 "required": ["name", "headquarters"], 

678 "type": "object", 

679 "properties": { 

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

681 "headquarters": {"title": "Headquarters", "type": "string"}, 

682 }, 

683 }, 

684 "TeamPublic": { 

685 "title": "TeamPublic", 

686 "required": ["name", "headquarters", "id"], 

687 "type": "object", 

688 "properties": { 

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

690 "headquarters": {"title": "Headquarters", "type": "string"}, 

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

692 }, 

693 }, 

694 "TeamPublicWithHeroes": { 

695 "title": "TeamPublicWithHeroes", 

696 "required": ["name", "headquarters", "id"], 

697 "type": "object", 

698 "properties": { 

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

700 "headquarters": {"title": "Headquarters", "type": "string"}, 

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

702 "heroes": { 

703 "title": "Heroes", 

704 "type": "array", 

705 "items": {"$ref": "#/components/schemas/HeroPublic"}, 

706 "default": [], 

707 }, 

708 }, 

709 }, 

710 "TeamUpdate": { 

711 "title": "TeamUpdate", 

712 "type": "object", 

713 "properties": { 

714 "id": IsDict( 

715 { 

716 "title": "Id", 

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

718 } 

719 ) 

720 | IsDict( 

721 # TODO: remove when deprecating Pydantic v1 

722 {"title": "Id", "type": "integer"} 

723 ), 

724 "name": IsDict( 

725 { 

726 "title": "Name", 

727 "anyOf": [{"type": "string"}, {"type": "null"}], 

728 } 

729 ) 

730 | IsDict( 

731 # TODO: remove when deprecating Pydantic v1 

732 {"title": "Name", "type": "string"} 

733 ), 

734 "headquarters": IsDict( 

735 { 

736 "title": "Headquarters", 

737 "anyOf": [{"type": "string"}, {"type": "null"}], 

738 } 

739 ) 

740 | IsDict( 

741 # TODO: remove when deprecating Pydantic v1 

742 {"title": "Headquarters", "type": "string"} 

743 ), 

744 }, 

745 }, 

746 "ValidationError": { 

747 "title": "ValidationError", 

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

749 "type": "object", 

750 "properties": { 

751 "loc": { 

752 "title": "Location", 

753 "type": "array", 

754 "items": { 

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

756 }, 

757 }, 

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

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

760 }, 

761 }, 

762 } 

763 }, 

764 }