test_error_responses.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import json
  2. import logging
  3. from http import HTTPStatus
  4. from pydantic import BaseModel
  5. from pydantic import ValidationError
  6. from clean_python import BadRequest
  7. from clean_python import Conflict
  8. from clean_python import DoesNotExist
  9. from clean_python import PermissionDenied
  10. from clean_python import Unauthorized
  11. from clean_python.fastapi.error_responses import conflict_handler
  12. from clean_python.fastapi.error_responses import not_found_handler
  13. from clean_python.fastapi.error_responses import permission_denied_handler
  14. from clean_python.fastapi.error_responses import unauthorized_handler
  15. from clean_python.fastapi.error_responses import validation_error_handler
  16. async def test_does_not_exist():
  17. actual = await not_found_handler(None, DoesNotExist("record", id=15))
  18. assert actual.status_code == HTTPStatus.NOT_FOUND
  19. assert json.loads(actual.body) == {"message": "Could not find record with id=15"}
  20. async def test_does_not_exist_no_id():
  21. actual = await not_found_handler(None, DoesNotExist("tafeltje"))
  22. assert actual.status_code == HTTPStatus.NOT_FOUND
  23. assert json.loads(actual.body) == {"message": "Could not find tafeltje"}
  24. async def test_conflict():
  25. actual = await conflict_handler(None, Conflict("foo"))
  26. assert actual.status_code == HTTPStatus.CONFLICT
  27. assert json.loads(actual.body) == {"message": "Conflict", "detail": "foo"}
  28. async def test_conflict_no_msg():
  29. actual = await conflict_handler(None, Conflict())
  30. assert actual.status_code == HTTPStatus.CONFLICT
  31. assert json.loads(actual.body) == {"message": "Conflict", "detail": None}
  32. async def test_unauthorized(caplog):
  33. actual = await unauthorized_handler(None, Unauthorized())
  34. assert actual.status_code == HTTPStatus.UNAUTHORIZED
  35. assert json.loads(actual.body) == {"message": "Unauthorized", "detail": None}
  36. assert actual.headers["WWW-Authenticate"] == "Bearer"
  37. assert caplog.record_tuples == []
  38. async def test_unauthorized_wit_msg(caplog):
  39. caplog.set_level(logging.INFO)
  40. # message should be ignored
  41. actual = await unauthorized_handler(None, Unauthorized("foo"))
  42. assert actual.status_code == HTTPStatus.UNAUTHORIZED
  43. assert json.loads(actual.body) == {"message": "Unauthorized", "detail": None}
  44. assert actual.headers["WWW-Authenticate"] == "Bearer"
  45. assert caplog.record_tuples == [
  46. ("clean_python.fastapi.error_responses", logging.INFO, "unauthorized: foo")
  47. ]
  48. async def test_permission_denied():
  49. actual = await permission_denied_handler(None, PermissionDenied())
  50. assert actual.status_code == HTTPStatus.FORBIDDEN
  51. assert json.loads(actual.body) == {"message": "Permission denied", "detail": None}
  52. async def test_permission_denied_with_msg():
  53. actual = await permission_denied_handler(None, PermissionDenied("foo"))
  54. assert actual.status_code == HTTPStatus.FORBIDDEN
  55. assert json.loads(actual.body) == {"message": "Permission denied", "detail": "foo"}
  56. class Book(BaseModel):
  57. title: str
  58. async def test_validation_error():
  59. try:
  60. Book(name="foo")
  61. except ValidationError as e:
  62. actual = await validation_error_handler(None, e)
  63. assert actual.status_code == HTTPStatus.BAD_REQUEST
  64. assert json.loads(actual.body) == {
  65. "message": "Validation error",
  66. "detail": [{"loc": ["title"], "msg": "Field required", "type": "missing"}],
  67. }
  68. async def test_bad_request_from_validation_error():
  69. try:
  70. Book(name="foo")
  71. except ValidationError as e:
  72. actual = await validation_error_handler(None, BadRequest(e))
  73. assert actual.status_code == HTTPStatus.BAD_REQUEST
  74. assert json.loads(actual.body) == {
  75. "message": "Validation error",
  76. "detail": [{"loc": ["title"], "msg": "Field required", "type": "missing"}],
  77. }
  78. async def test_bad_request_from_msg():
  79. actual = await validation_error_handler(None, BadRequest("foo"))
  80. assert actual.status_code == HTTPStatus.BAD_REQUEST
  81. assert json.loads(actual.body) == {
  82. "message": "Validation error",
  83. "detail": [{"loc": [], "msg": "foo", "type": "value_error"}],
  84. }