Coverage for tests/test_tutorial/test_bigger_applications/test_main.py: 100%

108 statements  

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

1import pytest 1abcde

2from dirty_equals import IsDict 1abcde

3from fastapi.testclient import TestClient 1abcde

4 

5 

6@pytest.fixture(name="client") 1abcde

7def get_client(): 1abcde

8 from docs_src.bigger_applications.app.main import app 1abcde

9 

10 client = TestClient(app) 1abcde

11 return client 1abcde

12 

13 

14def test_users_token_jessica(client: TestClient): 1abcde

15 response = client.get("/users?token=jessica") 1abcde

16 assert response.status_code == 200 1abcde

17 assert response.json() == [{"username": "Rick"}, {"username": "Morty"}] 1abcde

18 

19 

20def test_users_with_no_token(client: TestClient): 1abcde

21 response = client.get("/users") 1abcde

22 assert response.status_code == 422 1abcde

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

24 { 

25 "detail": [ 

26 { 

27 "type": "missing", 

28 "loc": ["query", "token"], 

29 "msg": "Field required", 

30 "input": None, 

31 } 

32 ] 

33 } 

34 ) | IsDict( 

35 # TODO: remove when deprecating Pydantic v1 

36 { 

37 "detail": [ 

38 { 

39 "loc": ["query", "token"], 

40 "msg": "field required", 

41 "type": "value_error.missing", 

42 }, 

43 ] 

44 } 

45 ) 

46 

47 

48def test_users_foo_token_jessica(client: TestClient): 1abcde

49 response = client.get("/users/foo?token=jessica") 1abcde

50 assert response.status_code == 200 1abcde

51 assert response.json() == {"username": "foo"} 1abcde

52 

53 

54def test_users_foo_with_no_token(client: TestClient): 1abcde

55 response = client.get("/users/foo") 1abcde

56 assert response.status_code == 422 1abcde

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

58 { 

59 "detail": [ 

60 { 

61 "type": "missing", 

62 "loc": ["query", "token"], 

63 "msg": "Field required", 

64 "input": None, 

65 } 

66 ] 

67 } 

68 ) | IsDict( 

69 # TODO: remove when deprecating Pydantic v1 

70 { 

71 "detail": [ 

72 { 

73 "loc": ["query", "token"], 

74 "msg": "field required", 

75 "type": "value_error.missing", 

76 }, 

77 ] 

78 } 

79 ) 

80 

81 

82def test_users_me_token_jessica(client: TestClient): 1abcde

83 response = client.get("/users/me?token=jessica") 1abcde

84 assert response.status_code == 200 1abcde

85 assert response.json() == {"username": "fakecurrentuser"} 1abcde

86 

87 

88def test_users_me_with_no_token(client: TestClient): 1abcde

89 response = client.get("/users/me") 1abcde

90 assert response.status_code == 422 1abcde

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

92 { 

93 "detail": [ 

94 { 

95 "type": "missing", 

96 "loc": ["query", "token"], 

97 "msg": "Field required", 

98 "input": None, 

99 } 

100 ] 

101 } 

102 ) | IsDict( 

103 # TODO: remove when deprecating Pydantic v1 

104 { 

105 "detail": [ 

106 { 

107 "loc": ["query", "token"], 

108 "msg": "field required", 

109 "type": "value_error.missing", 

110 }, 

111 ] 

112 } 

113 ) 

114 

115 

116def test_users_token_monica_with_no_jessica(client: TestClient): 1abcde

117 response = client.get("/users?token=monica") 1abcde

118 assert response.status_code == 400 1abcde

119 assert response.json() == {"detail": "No Jessica token provided"} 1abcde

120 

121 

122def test_items_token_jessica(client: TestClient): 1abcde

123 response = client.get( 1abcde

124 "/items?token=jessica", headers={"X-Token": "fake-super-secret-token"} 

125 ) 

126 assert response.status_code == 200 1abcde

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

128 "plumbus": {"name": "Plumbus"}, 

129 "gun": {"name": "Portal Gun"}, 

130 } 

131 

132 

133def test_items_with_no_token_jessica(client: TestClient): 1abcde

134 response = client.get("/items", headers={"X-Token": "fake-super-secret-token"}) 1abcde

135 assert response.status_code == 422 1abcde

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

137 { 

138 "detail": [ 

139 { 

140 "type": "missing", 

141 "loc": ["query", "token"], 

142 "msg": "Field required", 

143 "input": None, 

144 } 

145 ] 

146 } 

147 ) | IsDict( 

148 # TODO: remove when deprecating Pydantic v1 

149 { 

150 "detail": [ 

151 { 

152 "loc": ["query", "token"], 

153 "msg": "field required", 

154 "type": "value_error.missing", 

155 }, 

156 ] 

157 } 

158 ) 

159 

160 

161def test_items_plumbus_token_jessica(client: TestClient): 1abcde

162 response = client.get( 1abcde

163 "/items/plumbus?token=jessica", headers={"X-Token": "fake-super-secret-token"} 

164 ) 

165 assert response.status_code == 200 1abcde

166 assert response.json() == {"name": "Plumbus", "item_id": "plumbus"} 1abcde

167 

168 

169def test_items_bar_token_jessica(client: TestClient): 1abcde

170 response = client.get( 1abcde

171 "/items/bar?token=jessica", headers={"X-Token": "fake-super-secret-token"} 

172 ) 

173 assert response.status_code == 404 1abcde

174 assert response.json() == {"detail": "Item not found"} 1abcde

175 

176 

177def test_items_plumbus_with_no_token(client: TestClient): 1abcde

178 response = client.get( 1abcde

179 "/items/plumbus", headers={"X-Token": "fake-super-secret-token"} 

180 ) 

181 assert response.status_code == 422 1abcde

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

183 { 

184 "detail": [ 

185 { 

186 "type": "missing", 

187 "loc": ["query", "token"], 

188 "msg": "Field required", 

189 "input": None, 

190 } 

191 ] 

192 } 

193 ) | IsDict( 

194 # TODO: remove when deprecating Pydantic v1 

195 { 

196 "detail": [ 

197 { 

198 "loc": ["query", "token"], 

199 "msg": "field required", 

200 "type": "value_error.missing", 

201 }, 

202 ] 

203 } 

204 ) 

205 

206 

207def test_items_with_invalid_token(client: TestClient): 1abcde

208 response = client.get("/items?token=jessica", headers={"X-Token": "invalid"}) 1abcde

209 assert response.status_code == 400 1abcde

210 assert response.json() == {"detail": "X-Token header invalid"} 1abcde

211 

212 

213def test_items_bar_with_invalid_token(client: TestClient): 1abcde

214 response = client.get("/items/bar?token=jessica", headers={"X-Token": "invalid"}) 1abcde

215 assert response.status_code == 400 1abcde

216 assert response.json() == {"detail": "X-Token header invalid"} 1abcde

217 

218 

219def test_items_with_missing_x_token_header(client: TestClient): 1abcde

220 response = client.get("/items?token=jessica") 1abcde

221 assert response.status_code == 422 1abcde

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

223 { 

224 "detail": [ 

225 { 

226 "type": "missing", 

227 "loc": ["header", "x-token"], 

228 "msg": "Field required", 

229 "input": None, 

230 } 

231 ] 

232 } 

233 ) | IsDict( 

234 # TODO: remove when deprecating Pydantic v1 

235 { 

236 "detail": [ 

237 { 

238 "loc": ["header", "x-token"], 

239 "msg": "field required", 

240 "type": "value_error.missing", 

241 } 

242 ] 

243 } 

244 ) 

245 

246 

247def test_items_plumbus_with_missing_x_token_header(client: TestClient): 1abcde

248 response = client.get("/items/plumbus?token=jessica") 1abcde

249 assert response.status_code == 422 1abcde

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

251 { 

252 "detail": [ 

253 { 

254 "type": "missing", 

255 "loc": ["header", "x-token"], 

256 "msg": "Field required", 

257 "input": None, 

258 } 

259 ] 

260 } 

261 ) | IsDict( 

262 # TODO: remove when deprecating Pydantic v1 

263 { 

264 "detail": [ 

265 { 

266 "loc": ["header", "x-token"], 

267 "msg": "field required", 

268 "type": "value_error.missing", 

269 } 

270 ] 

271 } 

272 ) 

273 

274 

275def test_root_token_jessica(client: TestClient): 1abcde

276 response = client.get("/?token=jessica") 1abcde

277 assert response.status_code == 200 1abcde

278 assert response.json() == {"message": "Hello Bigger Applications!"} 1abcde

279 

280 

281def test_root_with_no_token(client: TestClient): 1abcde

282 response = client.get("/") 1abcde

283 assert response.status_code == 422 1abcde

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

285 { 

286 "detail": [ 

287 { 

288 "type": "missing", 

289 "loc": ["query", "token"], 

290 "msg": "Field required", 

291 "input": None, 

292 } 

293 ] 

294 } 

295 ) | IsDict( 

296 # TODO: remove when deprecating Pydantic v1 

297 { 

298 "detail": [ 

299 { 

300 "loc": ["query", "token"], 

301 "msg": "field required", 

302 "type": "value_error.missing", 

303 }, 

304 ] 

305 } 

306 ) 

307 

308 

309def test_put_no_header(client: TestClient): 1abcde

310 response = client.put("/items/foo") 1abcde

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

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

313 { 

314 "detail": [ 

315 { 

316 "type": "missing", 

317 "loc": ["query", "token"], 

318 "msg": "Field required", 

319 "input": None, 

320 }, 

321 { 

322 "type": "missing", 

323 "loc": ["header", "x-token"], 

324 "msg": "Field required", 

325 "input": None, 

326 }, 

327 ] 

328 } 

329 ) | IsDict( 

330 # TODO: remove when deprecating Pydantic v1 

331 { 

332 "detail": [ 

333 { 

334 "loc": ["query", "token"], 

335 "msg": "field required", 

336 "type": "value_error.missing", 

337 }, 

338 { 

339 "loc": ["header", "x-token"], 

340 "msg": "field required", 

341 "type": "value_error.missing", 

342 }, 

343 ] 

344 } 

345 ) 

346 

347 

348def test_put_invalid_header(client: TestClient): 1abcde

349 response = client.put("/items/foo", headers={"X-Token": "invalid"}) 1abcde

350 assert response.status_code == 400, response.text 1abcde

351 assert response.json() == {"detail": "X-Token header invalid"} 1abcde

352 

353 

354def test_put(client: TestClient): 1abcde

355 response = client.put( 1abcde

356 "/items/plumbus?token=jessica", headers={"X-Token": "fake-super-secret-token"} 

357 ) 

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

359 assert response.json() == {"item_id": "plumbus", "name": "The great Plumbus"} 1abcde

360 

361 

362def test_put_forbidden(client: TestClient): 1abcde

363 response = client.put( 1abcde

364 "/items/bar?token=jessica", headers={"X-Token": "fake-super-secret-token"} 

365 ) 

366 assert response.status_code == 403, response.text 1abcde

367 assert response.json() == {"detail": "You can only update the item: plumbus"} 1abcde

368 

369 

370def test_admin(client: TestClient): 1abcde

371 response = client.post( 1abcde

372 "/admin/?token=jessica", headers={"X-Token": "fake-super-secret-token"} 

373 ) 

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

375 assert response.json() == {"message": "Admin getting schwifty"} 1abcde

376 

377 

378def test_admin_invalid_header(client: TestClient): 1abcde

379 response = client.post("/admin/", headers={"X-Token": "invalid"}) 1abcde

380 assert response.status_code == 400, response.text 1abcde

381 assert response.json() == {"detail": "X-Token header invalid"} 1abcde

382 

383 

384def test_openapi_schema(client: TestClient): 1abcde

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

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

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

388 "openapi": "3.1.0", 

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

390 "paths": { 

391 "/users/": { 

392 "get": { 

393 "tags": ["users"], 

394 "summary": "Read Users", 

395 "operationId": "read_users_users__get", 

396 "parameters": [ 

397 { 

398 "required": True, 

399 "schema": {"title": "Token", "type": "string"}, 

400 "name": "token", 

401 "in": "query", 

402 } 

403 ], 

404 "responses": { 

405 "200": { 

406 "description": "Successful Response", 

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

408 }, 

409 "422": { 

410 "description": "Validation Error", 

411 "content": { 

412 "application/json": { 

413 "schema": { 

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

415 } 

416 } 

417 }, 

418 }, 

419 }, 

420 } 

421 }, 

422 "/users/me": { 

423 "get": { 

424 "tags": ["users"], 

425 "summary": "Read User Me", 

426 "operationId": "read_user_me_users_me_get", 

427 "parameters": [ 

428 { 

429 "required": True, 

430 "schema": {"title": "Token", "type": "string"}, 

431 "name": "token", 

432 "in": "query", 

433 } 

434 ], 

435 "responses": { 

436 "200": { 

437 "description": "Successful Response", 

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

439 }, 

440 "422": { 

441 "description": "Validation Error", 

442 "content": { 

443 "application/json": { 

444 "schema": { 

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

446 } 

447 } 

448 }, 

449 }, 

450 }, 

451 } 

452 }, 

453 "/users/{username}": { 

454 "get": { 

455 "tags": ["users"], 

456 "summary": "Read User", 

457 "operationId": "read_user_users__username__get", 

458 "parameters": [ 

459 { 

460 "required": True, 

461 "schema": {"title": "Username", "type": "string"}, 

462 "name": "username", 

463 "in": "path", 

464 }, 

465 { 

466 "required": True, 

467 "schema": {"title": "Token", "type": "string"}, 

468 "name": "token", 

469 "in": "query", 

470 }, 

471 ], 

472 "responses": { 

473 "200": { 

474 "description": "Successful Response", 

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

476 }, 

477 "422": { 

478 "description": "Validation Error", 

479 "content": { 

480 "application/json": { 

481 "schema": { 

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

483 } 

484 } 

485 }, 

486 }, 

487 }, 

488 } 

489 }, 

490 "/items/": { 

491 "get": { 

492 "tags": ["items"], 

493 "summary": "Read Items", 

494 "operationId": "read_items_items__get", 

495 "parameters": [ 

496 { 

497 "required": True, 

498 "schema": {"title": "Token", "type": "string"}, 

499 "name": "token", 

500 "in": "query", 

501 }, 

502 { 

503 "required": True, 

504 "schema": {"title": "X-Token", "type": "string"}, 

505 "name": "x-token", 

506 "in": "header", 

507 }, 

508 ], 

509 "responses": { 

510 "200": { 

511 "description": "Successful Response", 

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

513 }, 

514 "404": {"description": "Not found"}, 

515 "422": { 

516 "description": "Validation Error", 

517 "content": { 

518 "application/json": { 

519 "schema": { 

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

521 } 

522 } 

523 }, 

524 }, 

525 }, 

526 } 

527 }, 

528 "/items/{item_id}": { 

529 "get": { 

530 "tags": ["items"], 

531 "summary": "Read Item", 

532 "operationId": "read_item_items__item_id__get", 

533 "parameters": [ 

534 { 

535 "required": True, 

536 "schema": {"title": "Item Id", "type": "string"}, 

537 "name": "item_id", 

538 "in": "path", 

539 }, 

540 { 

541 "required": True, 

542 "schema": {"title": "Token", "type": "string"}, 

543 "name": "token", 

544 "in": "query", 

545 }, 

546 { 

547 "required": True, 

548 "schema": {"title": "X-Token", "type": "string"}, 

549 "name": "x-token", 

550 "in": "header", 

551 }, 

552 ], 

553 "responses": { 

554 "200": { 

555 "description": "Successful Response", 

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

557 }, 

558 "404": {"description": "Not found"}, 

559 "422": { 

560 "description": "Validation Error", 

561 "content": { 

562 "application/json": { 

563 "schema": { 

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

565 } 

566 } 

567 }, 

568 }, 

569 }, 

570 }, 

571 "put": { 

572 "tags": ["items", "custom"], 

573 "summary": "Update Item", 

574 "operationId": "update_item_items__item_id__put", 

575 "parameters": [ 

576 { 

577 "required": True, 

578 "schema": {"title": "Item Id", "type": "string"}, 

579 "name": "item_id", 

580 "in": "path", 

581 }, 

582 { 

583 "required": True, 

584 "schema": {"title": "Token", "type": "string"}, 

585 "name": "token", 

586 "in": "query", 

587 }, 

588 { 

589 "required": True, 

590 "schema": {"title": "X-Token", "type": "string"}, 

591 "name": "x-token", 

592 "in": "header", 

593 }, 

594 ], 

595 "responses": { 

596 "200": { 

597 "description": "Successful Response", 

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

599 }, 

600 "404": {"description": "Not found"}, 

601 "403": {"description": "Operation forbidden"}, 

602 "422": { 

603 "description": "Validation Error", 

604 "content": { 

605 "application/json": { 

606 "schema": { 

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

608 } 

609 } 

610 }, 

611 }, 

612 }, 

613 }, 

614 }, 

615 "/admin/": { 

616 "post": { 

617 "tags": ["admin"], 

618 "summary": "Update Admin", 

619 "operationId": "update_admin_admin__post", 

620 "parameters": [ 

621 { 

622 "required": True, 

623 "schema": {"title": "Token", "type": "string"}, 

624 "name": "token", 

625 "in": "query", 

626 }, 

627 { 

628 "required": True, 

629 "schema": {"title": "X-Token", "type": "string"}, 

630 "name": "x-token", 

631 "in": "header", 

632 }, 

633 ], 

634 "responses": { 

635 "200": { 

636 "description": "Successful Response", 

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

638 }, 

639 "418": {"description": "I'm a teapot"}, 

640 "422": { 

641 "description": "Validation Error", 

642 "content": { 

643 "application/json": { 

644 "schema": { 

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

646 } 

647 } 

648 }, 

649 }, 

650 }, 

651 } 

652 }, 

653 "/": { 

654 "get": { 

655 "summary": "Root", 

656 "operationId": "root__get", 

657 "parameters": [ 

658 { 

659 "required": True, 

660 "schema": {"title": "Token", "type": "string"}, 

661 "name": "token", 

662 "in": "query", 

663 } 

664 ], 

665 "responses": { 

666 "200": { 

667 "description": "Successful Response", 

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

669 }, 

670 "422": { 

671 "description": "Validation Error", 

672 "content": { 

673 "application/json": { 

674 "schema": { 

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

676 } 

677 } 

678 }, 

679 }, 

680 }, 

681 } 

682 }, 

683 }, 

684 "components": { 

685 "schemas": { 

686 "HTTPValidationError": { 

687 "title": "HTTPValidationError", 

688 "type": "object", 

689 "properties": { 

690 "detail": { 

691 "title": "Detail", 

692 "type": "array", 

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

694 } 

695 }, 

696 }, 

697 "ValidationError": { 

698 "title": "ValidationError", 

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

700 "type": "object", 

701 "properties": { 

702 "loc": { 

703 "title": "Location", 

704 "type": "array", 

705 "items": { 

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

707 }, 

708 }, 

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

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

711 }, 

712 }, 

713 } 

714 }, 

715 }