refac: add fetch one ingredient use case
This commit is contained in:
parent
1a7c1f099c
commit
f2d24e89db
|
@ -1,3 +1,4 @@
|
|||
mod domain;
|
||||
mod use_case;
|
||||
|
||||
pub use domain::Ingredient;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use crate::app_core::shared::{domain::Lang, lib::EntityId};
|
||||
use crate::app_core::shared::lib::EntityId;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Ingredient {
|
||||
pub key: EntityId,
|
||||
pub lang: Lang,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
mod fetch_one;
|
|
@ -0,0 +1,110 @@
|
|||
use crate::app_core::{
|
||||
components::ingredient::Ingredient,
|
||||
port::repo::{FindOneError, IngredientRepoPort},
|
||||
shared::lib::UseCase,
|
||||
};
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Request {
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
type Response = Ingredient;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("Ingredient not found")]
|
||||
NotFound,
|
||||
|
||||
#[error("Unknown error")]
|
||||
Unknown,
|
||||
}
|
||||
|
||||
pub trait FetchOneIngredientUseCase: UseCase<Request, Response, Error> {}
|
||||
|
||||
#[derive(Provider)]
|
||||
#[shaku(interface = FetchOneIngredientUseCase)]
|
||||
pub struct FetchOneIngredient {
|
||||
#[shaku(provide)]
|
||||
ingredient_repo: Box<dyn IngredientRepoPort>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl UseCase<Request, Response, Error> for FetchOneIngredient {
|
||||
async fn execute(&self, req: Request) -> Result<Response, Error> {
|
||||
self.ingredient_repo
|
||||
.find_one(&req.key)
|
||||
.await
|
||||
.map_err(|e| match e {
|
||||
FindOneError::Unknown => Error::Unknown,
|
||||
FindOneError::NotFound => Error::NotFound,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl FetchOneIngredientUseCase for FetchOneIngredient {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
domain::{Context, Lang},
|
||||
repo::ingredient::InMemoryIngredientRepo,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn should_return_ingredient() {
|
||||
let repo = InMemoryIngredientRepo::new();
|
||||
let res = execute(&repo, &Context::default(), String::from("apple"));
|
||||
|
||||
match res {
|
||||
Ok(apple) => {
|
||||
assert_eq!(apple.key, String::from("apple"));
|
||||
assert_eq!(apple.lang, Lang::Rus);
|
||||
assert_eq!(apple.name, String::from("Яблоко"));
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_return_ingredient_with_choosed_lang() {
|
||||
let repo = InMemoryIngredientRepo::new();
|
||||
let res = execute(&repo, &Context::eng(), String::from("apple"));
|
||||
|
||||
match res {
|
||||
Ok(apple) => {
|
||||
assert_eq!(apple.key, String::from("apple"));
|
||||
assert_eq!(apple.lang, Lang::Eng);
|
||||
assert_eq!(apple.name, String::from("Apple"));
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_return_ingredient_with_fallback_lang() {
|
||||
let repo = InMemoryIngredientRepo::new();
|
||||
let res = execute(&repo, &Context::eng(), String::from("orange"));
|
||||
|
||||
match res {
|
||||
Ok(orange) => {
|
||||
assert_eq!(orange.key, String::from("orange"));
|
||||
assert_eq!(orange.lang, Lang::Rus);
|
||||
assert_eq!(orange.name, String::from("Апельсин"));
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_throw_not_found_error() {
|
||||
let repo = InMemoryIngredientRepo::new();
|
||||
let res = execute(&repo, &Context::default(), String::from("wildberries"));
|
||||
|
||||
match res {
|
||||
Err(ResponseError::NotFound) => {}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
use crate::app_core::shared::{domain::Lang, lib::EntityId};
|
||||
use crate::app_core::shared::lib::EntityId;
|
||||
|
||||
use super::RecipeIngredient;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Recipe {
|
||||
pub key: EntityId,
|
||||
pub lang: Lang,
|
||||
pub name: String,
|
||||
pub instructions: Vec<String>,
|
||||
pub ingredients: Vec<RecipeIngredient>,
|
||||
|
|
|
@ -1 +1 @@
|
|||
mod repo;
|
||||
pub mod repo;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
mod ingredient;
|
||||
mod recipe;
|
||||
|
||||
pub use ingredient::IngredientRepoPort;
|
||||
pub use recipe::RecipeRepoPort;
|
||||
|
||||
use crate::app_core::shared::lib::{Entity, EntityId};
|
||||
|
||||
use shaku::Interface;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
pub mod domain;
|
||||
#[macro_use]
|
||||
pub mod lib;
|
||||
|
||||
pub mod app;
|
||||
pub mod domain;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
mod context;
|
||||
mod lang;
|
||||
|
||||
pub use context::Context;
|
||||
pub use lang::Lang;
|
|
@ -0,0 +1,9 @@
|
|||
use shaku::Interface;
|
||||
|
||||
use super::lang::Lang;
|
||||
|
||||
pub trait Context: Interface {
|
||||
fn lang(&self) -> &Lang {
|
||||
&self.lang
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
|
||||
pub enum Lang {
|
||||
#[default]
|
||||
Rus,
|
||||
Eng,
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
mod lang;
|
||||
|
||||
pub use lang::Lang;
|
|
@ -1,11 +0,0 @@
|
|||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Lang {
|
||||
Rus,
|
||||
Eng,
|
||||
}
|
||||
|
||||
impl Default for Lang {
|
||||
fn default() -> Self {
|
||||
Lang::Rus
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#[macro_use]
|
||||
extern crate async_trait;
|
||||
#[macro_use]
|
||||
extern crate shaku;
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
|
|
Loading…
Reference in New Issue