puerto 0.19.1

Puerto — Rust full-stack DDD framework CLI. Scaffolds Clean Architecture projects with auto-wired DI, SQLx support, and zero manual wiring. Formerly puerto-framework.
use business::domain::user::errors::UserError;
use poem::http::StatusCode;
use poem_openapi::payload::Json;
use puerto_web::ErrorResponse;

use crate::api::error::IntoErrorResponse;

impl IntoErrorResponse for UserError {
    /// Exhaustive on purpose: a new error variant does not compile until it has a status.
    fn into_error_response(self) -> (StatusCode, Json<ErrorResponse>) {
        let status = match &self {
            UserError::ValidationError(_) => StatusCode::UNPROCESSABLE_ENTITY,
            UserError::InvalidCredentials => StatusCode::UNAUTHORIZED,
            UserError::NotFound => StatusCode::NOT_FOUND,
            UserError::Duplicate => StatusCode::CONFLICT,
            UserError::RepositoryError => StatusCode::INTERNAL_SERVER_ERROR,
            UserError::Unknown => StatusCode::INTERNAL_SERVER_ERROR,
        };
        (status, Json(ErrorResponse::from_code(self.to_string())))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn mapped(err: UserError) -> (StatusCode, String) {
        let (status, Json(body)) = err.into_error_response();
        (status, body.name)
    }

    #[test]
    fn should_map_validation_error_to_422_with_its_code() {
        assert_eq!(
            mapped(UserError::ValidationError("password_too_short".into())),
            (
                StatusCode::UNPROCESSABLE_ENTITY,
                "user.validation_error.password_too_short".into()
            )
        );
    }

    #[test]
    fn should_map_invalid_credentials_to_401_with_its_code() {
        assert_eq!(
            mapped(UserError::InvalidCredentials),
            (StatusCode::UNAUTHORIZED, "auth.invalid_credentials".into())
        );
    }

    #[test]
    fn should_map_not_found_to_404_with_its_code() {
        assert_eq!(
            mapped(UserError::NotFound),
            (StatusCode::NOT_FOUND, "user.not_found".into())
        );
    }

    #[test]
    fn should_map_duplicate_to_409_with_its_code() {
        assert_eq!(
            mapped(UserError::Duplicate),
            (StatusCode::CONFLICT, "user.duplicate".into())
        );
    }

    #[test]
    fn should_map_repository_error_to_500_with_its_code() {
        assert_eq!(
            mapped(UserError::RepositoryError),
            (StatusCode::INTERNAL_SERVER_ERROR, "user.repository_error".into())
        );
    }

    #[test]
    fn should_map_unknown_to_500_with_its_code() {
        assert_eq!(
            mapped(UserError::Unknown),
            (StatusCode::INTERNAL_SERVER_ERROR, "user.unknown".into())
        );
    }
}