gitbox 2.1.3

Git toolbox to simplify adoption of conventional commits and semantic version, among other things.
Documentation
use crate::usecase::{
    error::create_license_error::CreateLicenseError,
    repository::{
        license_choice_ingress_repository::LicenseChoiceIngressRepository,
        license_list_ingress_repository::LicenseListIngressRepository,
        license_text_egress_repository::LicenseTextEgressRepository,
        license_text_ingress_repository::LicenseTextIngressRepository,
    },
};

use super::usecase::UseCase;

pub struct CreateLicenseUseCase<'a> {
    license_list_ingress_repository: &'a dyn LicenseListIngressRepository,
    license_choice_ingress_repository: &'a dyn LicenseChoiceIngressRepository,
    license_text_ingress_repository: &'a dyn LicenseTextIngressRepository,
    license_text_egress_repository: &'a dyn LicenseTextEgressRepository,
}

impl<'a, 'b: 'a, 'c: 'a, 'd: 'a, 'e: 'a> CreateLicenseUseCase<'a> {
    pub fn new(
        license_list_ingress_repository: &'b dyn LicenseListIngressRepository,
        license_choice_ingress_repository: &'c dyn LicenseChoiceIngressRepository,
        license_text_ingress_repository: &'d dyn LicenseTextIngressRepository,
        license_text_egress_repository: &'e dyn LicenseTextEgressRepository,
    ) -> Self {
        CreateLicenseUseCase {
            license_list_ingress_repository,
            license_choice_ingress_repository,
            license_text_ingress_repository,
            license_text_egress_repository,
        }
    }
}

impl UseCase<(), CreateLicenseError> for CreateLicenseUseCase<'_> {
    fn execute(&self) -> Result<(), CreateLicenseError> {
        let license_list = self.license_list_ingress_repository.license_list()?;
        let chosen_license = self
            .license_choice_ingress_repository
            .ask_license(&license_list)?;
        let license_text = self.license_text_ingress_repository.text(chosen_license)?;
        Ok(self.license_text_egress_repository.consume(&license_text)?)
    }
}

#[cfg(test)]
mod tests {
    use std::cell::RefCell;

    use crate::usecase::{
        license_metadata::LicenseMetadata,
        repository::{
            license_choice_ingress_repository::LicenseChoiceIngressRepository,
            license_list_ingress_repository::LicenseListIngressRepository,
            license_text_egress_repository::LicenseTextEgressRepository,
            license_text_ingress_repository::LicenseTextIngressRepository,
        },
        type_aliases::AnyError,
        usecases::{create_license::CreateLicenseUseCase, usecase::UseCase},
    };

    struct MockLicenseListIngressRepository {}
    impl LicenseListIngressRepository for MockLicenseListIngressRepository {
        fn license_list(&self) -> Result<Box<[LicenseMetadata]>, AnyError> {
            Ok(Box::new([
                LicenseMetadata::new("MIT", "mit-license"),
                LicenseMetadata::new("MPL 2.0", "mpl-2.0"),
            ]))
        }
    }

    struct MockLicenseChoiceIngressRepository {}
    impl LicenseChoiceIngressRepository for MockLicenseChoiceIngressRepository {
        fn ask_license<'a>(
            &self,
            list: &'a [LicenseMetadata],
        ) -> Result<&'a LicenseMetadata, AnyError> {
            Ok(&list[0])
        }
    }

    struct MockLicenseTextIngressRepository {}
    impl LicenseTextIngressRepository for MockLicenseTextIngressRepository {
        fn text(&self, license: &LicenseMetadata) -> Result<Box<str>, AnyError> {
            Ok(format!(
                "Name: {}\nReference: {}\n",
                license.name(),
                license.reference()
            )
            .into_boxed_str())
        }
    }

    struct MockLicenseTextEgressRepository {
        consumed_text: RefCell<Box<str>>,
    }

    impl LicenseTextEgressRepository for MockLicenseTextEgressRepository {
        fn consume(&self, text: &str) -> Result<(), AnyError> {
            self.consumed_text.replace(text.into());
            Ok(())
        }
    }

    #[test]
    fn create_license_usecase() {
        let license_list_ingress_repository = MockLicenseListIngressRepository {};
        let license_choice_ingress_repository = MockLicenseChoiceIngressRepository {};
        let license_text_ingress_repository = MockLicenseTextIngressRepository {};
        let license_text_egress_repository = MockLicenseTextEgressRepository {
            consumed_text: RefCell::new("".into()),
        };
        let usecase = CreateLicenseUseCase::new(
            &license_list_ingress_repository,
            &license_choice_ingress_repository,
            &license_text_ingress_repository,
            &license_text_egress_repository,
        );
        usecase.execute().expect("Repositories do not return Errs");
        assert_eq!(
            license_text_egress_repository.consumed_text.take(),
            "Name: MIT\nReference: mit-license\n".into()
        );
    }
}