import json import logging from http import HTTPStatus from pydantic import BaseModel from pydantic import ValidationError from clean_python import BadRequest from clean_python import Conflict from clean_python import DoesNotExist from clean_python import PermissionDenied from clean_python import Unauthorized from clean_python.fastapi.error_responses import conflict_handler from clean_python.fastapi.error_responses import not_found_handler from clean_python.fastapi.error_responses import permission_denied_handler from clean_python.fastapi.error_responses import unauthorized_handler from clean_python.fastapi.error_responses import validation_error_handler async def test_does_not_exist(): actual = await not_found_handler(None, DoesNotExist("record", id=15)) assert actual.status_code == HTTPStatus.NOT_FOUND assert json.loads(actual.body) == {"message": "Could not find record with id=15"} async def test_does_not_exist_no_id(): actual = await not_found_handler(None, DoesNotExist("tafeltje")) assert actual.status_code == HTTPStatus.NOT_FOUND assert json.loads(actual.body) == {"message": "Could not find tafeltje"} async def test_conflict(): actual = await conflict_handler(None, Conflict("foo")) assert actual.status_code == HTTPStatus.CONFLICT assert json.loads(actual.body) == {"message": "Conflict", "detail": "foo"} async def test_conflict_no_msg(): actual = await conflict_handler(None, Conflict()) assert actual.status_code == HTTPStatus.CONFLICT assert json.loads(actual.body) == {"message": "Conflict", "detail": None} async def test_unauthorized(caplog): actual = await unauthorized_handler(None, Unauthorized()) assert actual.status_code == HTTPStatus.UNAUTHORIZED assert json.loads(actual.body) == {"message": "Unauthorized", "detail": None} assert actual.headers["WWW-Authenticate"] == "Bearer" assert caplog.record_tuples == [] async def test_unauthorized_wit_msg(caplog): caplog.set_level(logging.INFO) # message should be ignored actual = await unauthorized_handler(None, Unauthorized("foo")) assert actual.status_code == HTTPStatus.UNAUTHORIZED assert json.loads(actual.body) == {"message": "Unauthorized", "detail": None} assert actual.headers["WWW-Authenticate"] == "Bearer" assert caplog.record_tuples == [ ("clean_python.fastapi.error_responses", logging.INFO, "unauthorized: foo") ] async def test_permission_denied(): actual = await permission_denied_handler(None, PermissionDenied()) assert actual.status_code == HTTPStatus.FORBIDDEN assert json.loads(actual.body) == {"message": "Permission denied", "detail": None} async def test_permission_denied_with_msg(): actual = await permission_denied_handler(None, PermissionDenied("foo")) assert actual.status_code == HTTPStatus.FORBIDDEN assert json.loads(actual.body) == {"message": "Permission denied", "detail": "foo"} class Book(BaseModel): title: str async def test_validation_error(): try: Book(name="foo") except ValidationError as e: actual = await validation_error_handler(None, e) assert actual.status_code == HTTPStatus.BAD_REQUEST assert json.loads(actual.body) == { "message": "Validation error", "detail": [{"loc": ["title"], "msg": "Field required", "type": "missing"}], } async def test_bad_request_from_validation_error(): try: Book(name="foo") except ValidationError as e: actual = await validation_error_handler(None, BadRequest(e)) assert actual.status_code == HTTPStatus.BAD_REQUEST assert json.loads(actual.body) == { "message": "Validation error", "detail": [{"loc": ["title"], "msg": "Field required", "type": "missing"}], } async def test_bad_request_from_msg(): actual = await validation_error_handler(None, BadRequest("foo")) assert actual.status_code == HTTPStatus.BAD_REQUEST assert json.loads(actual.body) == { "message": "Validation error", "detail": [{"loc": [], "msg": "foo", "type": "value_error"}], }