api: add tests for recipes

This commit is contained in:
Dmitriy Pleshevskiy 2022-05-14 16:59:14 +03:00
parent 426c2ae4c2
commit 01216f2bbe
6 changed files with 192 additions and 19 deletions

View File

@ -25,11 +25,11 @@ pub fn execute(
#[cfg(test)]
mod tests {
use super::*;
use crate::domain::misc_types::Lang;
use crate::{domain::misc_types::Lang, repo::ingredient::InMemoryIngredientRepo};
#[test]
fn should_return_ingredient() {
let repo = crate::repo::ingredient::InMemoryIngredientRepo::new();
let repo = InMemoryIngredientRepo::new();
let res = execute(&repo, String::from("apple"), RequestOpts::default());
match res {
@ -44,7 +44,7 @@ mod tests {
#[test]
fn should_return_ingredient_with_choosed_lang() {
let repo = crate::repo::ingredient::InMemoryIngredientRepo::new();
let repo = InMemoryIngredientRepo::new();
let res = execute(
&repo,
String::from("apple"),
@ -65,7 +65,7 @@ mod tests {
#[test]
fn should_return_ingredient_with_fallback_lang() {
let repo = crate::repo::ingredient::InMemoryIngredientRepo::new();
let repo = InMemoryIngredientRepo::new();
let res = execute(
&repo,
String::from("orange"),
@ -86,7 +86,7 @@ mod tests {
#[test]
fn should_throw_not_found_error() {
let repo = crate::repo::ingredient::InMemoryIngredientRepo::new();
let repo = InMemoryIngredientRepo::new();
let res = execute(&repo, String::from("wildberries"), RequestOpts::default());
match res {

View File

@ -15,15 +15,19 @@ pub fn execute(repo: &impl IngredientRepo, opts: RequestOpts) -> Vec<types::Ingr
#[cfg(test)]
mod tests {
use super::*;
use crate::domain::misc_types::Lang;
use crate::{domain::misc_types::Lang, repo::ingredient::InMemoryIngredientRepo};
#[test]
fn should_return_all_ingredients() {
let repo = crate::repo::ingredient::InMemoryIngredientRepo::new();
let repo = InMemoryIngredientRepo::new();
let res = execute(&repo, RequestOpts::default());
match res.as_slice() {
[apple, orange, salt, sugar] => {
[banana, apple, orange, salt, sugar] => {
assert_eq!(banana.key, String::from("banana"));
assert_eq!(banana.lang, Lang::Rus);
assert_eq!(banana.name, String::from("Банан"));
assert_eq!(apple.key, String::from("apple"));
assert_eq!(apple.lang, Lang::Rus);
assert_eq!(apple.name, String::from("Яблоко"));
@ -46,7 +50,7 @@ mod tests {
#[test]
fn should_return_preferred_lang_with_fallback() {
let repo = crate::repo::ingredient::InMemoryIngredientRepo::new();
let repo = InMemoryIngredientRepo::new();
let res = execute(
&repo,
RequestOpts {
@ -56,7 +60,11 @@ mod tests {
);
match res.as_slice() {
[apple, orange, salt, sugar] => {
[banana, apple, orange, salt, sugar] => {
assert_eq!(banana.key, String::from("banana"));
assert_eq!(banana.lang, Lang::Eng);
assert_eq!(banana.name, String::from("Banana"));
assert_eq!(apple.key, String::from("apple"));
assert_eq!(apple.lang, Lang::Eng);
assert_eq!(apple.name, String::from("Apple"));
@ -79,7 +87,7 @@ mod tests {
#[test]
fn should_return_filtered_by_keys() {
let repo = crate::repo::ingredient::InMemoryIngredientRepo::new();
let repo = InMemoryIngredientRepo::new();
let res = execute(
&repo,
RequestOpts {

View File

@ -5,3 +5,54 @@ use super::types;
pub fn execute(repo: &impl RecipeRepo) -> Vec<types::Recipe> {
repo.get_recipes()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
domain::{misc_types::Lang, recipe::types::RecipeIngredientMeasure},
repo::recipe::InMemoryRecipeRepo,
};
#[test]
fn should_return_all_recipes() {
let repo = InMemoryRecipeRepo::new();
let res = execute(&repo);
match res.as_slice() {
[salad, pizza_base] => {
assert_eq!(salad.key, String::from("fruit_salad"));
assert_eq!(salad.lang, Lang::Rus);
assert_eq!(salad.name, String::from("Фруктовый салат"));
assert_eq!(
salad.instructions,
vec![
"Нарезать бананы кружочками",
"Нарезать яблоки и апельсины кубиками",
"Все ингредиенты перемешать",
]
);
match salad.ingredients.as_slice() {
[banana, apple, orange] => {
assert_eq!(banana.ingredient.key, "banana");
assert_eq!(banana.measure, RecipeIngredientMeasure::Gram(150));
assert_eq!(apple.ingredient.key, "apple");
assert_eq!(apple.measure, RecipeIngredientMeasure::Gram(150));
assert_eq!(orange.ingredient.key, "orange");
assert_eq!(orange.measure, RecipeIngredientMeasure::Gram(150));
}
_ => unreachable!(),
}
assert_eq!(pizza_base.key, String::from("thin_crispy_pizza_base"));
assert_eq!(pizza_base.lang, Lang::Rus);
assert_eq!(
pizza_base.name,
String::from("Тонкая хрустящая основа для пиццы")
);
}
_ => unreachable!(),
}
}
}

View File

@ -2,11 +2,11 @@ use crate::domain::{ingredient::types::Ingredient, misc_types::Lang};
#[derive(Debug, Clone, Serialize)]
pub struct Recipe {
key: String,
lang: Lang,
name: String,
instructions: Vec<String>,
ingredients: Vec<RecipeIngredient>,
pub key: String,
pub lang: Lang,
pub name: String,
pub instructions: Vec<String>,
pub ingredients: Vec<RecipeIngredient>,
}
impl From<(&db::data::Recipe, Lang, Vec<Ingredient>)> for Recipe {
@ -46,12 +46,12 @@ impl From<(&db::data::Recipe, Lang, Vec<Ingredient>)> for Recipe {
#[derive(Debug, Clone, Serialize)]
pub struct RecipeIngredient {
#[serde(flatten)]
ingredient: Ingredient,
pub ingredient: Ingredient,
#[serde(flatten)]
measure: RecipeIngredientMeasure,
pub measure: RecipeIngredientMeasure,
}
#[derive(Debug, Clone, Serialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(tag = "measure", content = "amount")]
pub enum RecipeIngredientMeasure {
#[serde(rename = "g")]

View File

@ -69,6 +69,13 @@ impl InMemoryIngredientRepo {
pub fn new() -> Self {
Self {
ingredients: vec![
db::data::Ingredient {
key: "banana",
translates: db::data::IngredientTranslate {
rus: "Банан",
eng: Some("Banana"),
},
},
db::data::Ingredient {
key: "apple",
translates: db::data::IngredientTranslate {

View File

@ -21,3 +21,110 @@ impl RecipeRepo for StaticRecipeRepo {
.collect()
}
}
#[cfg(test)]
pub struct InMemoryRecipeRepo {
recipes: Vec<db::data::Recipe>,
}
#[cfg(test)]
impl InMemoryRecipeRepo {
pub fn new() -> Self {
use db::data as Db;
use Db::RecipeIngredientMeasure as DbRIM;
Self {
recipes: vec![
Db::Recipe {
key: "fruit_salad",
steps: 0,
ingredients: vec![
Db::RecipeIngredient {
key: "banana",
measure: DbRIM::Gram(150),
},
Db::RecipeIngredient {
key: "apple",
measure: DbRIM::Gram(150),
},
Db::RecipeIngredient {
key: "orange",
measure: DbRIM::Gram(150),
},
],
translates: Db::RecipeTranslates {
rus: Db::RecipeTranslate {
name: "Фруктовый салат",
instructions: vec![
"Нарезать бананы кружочками",
"Нарезать яблоки и апельсины кубиками",
"Все ингредиенты перемешать",
],
},
eng: None,
},
},
Db::Recipe {
key: "thin_crispy_pizza_base",
steps: 7,
ingredients: vec![
Db::RecipeIngredient {
key: "salt",
measure: DbRIM::Gram(5),
},
Db::RecipeIngredient {
key: "sugar",
measure: DbRIM::Gram(4),
},
Db::RecipeIngredient {
key: "wheat_flour",
measure: DbRIM::Gram(500),
},
Db::RecipeIngredient {
key: "dry_yeast",
measure: DbRIM::Gram(7),
},
Db::RecipeIngredient {
key: "olive_oil",
measure: DbRIM::MilliLiter(25),
},
Db::RecipeIngredient {
key: "water",
measure: DbRIM::MilliLiter(250),
},
],
translates: Db::RecipeTranslates {
rus: Db::RecipeTranslate {
name: "Тонкая хрустящая основа для пиццы",
instructions: vec![
"Растворить дрожжи в воде, подогретой до температуры тела.",
"Добавить соль, сахар, оливковое масло и хорошо перемешать до однородной консистенции.",
"Добавить муку и замесить тесто. Вымешивать не менее 15 минут.",
"Разделить тесто на 3 порции, каждую завернуть в пищевую плёнку и дать настояться около 30 минут.",
"Растянуть один кусок теста до тонкого состояния и аккуратно переложить на смазанный растительным маслом противень.",
"Смазать соусом, чтобы тесто не осталось жидким и чтобы начинка не скользила по нему, и поставить в предварительно разогретую до максимальной температуры (не меньше 250 градусов) на 5-10 минут. В результате тесто хорошо пропечется и станет хрустящим.",
"Теперь на основу можно выкладывать начинку на ваш вкус и запекать до момента, когда сыр растает.",
],
},
eng: None,
},
},
],
}
}
}
#[cfg(test)]
impl RecipeRepo for InMemoryRecipeRepo {
fn get_recipes(&self) -> Vec<types::Recipe> {
let ings_repo = crate::repo::ingredient::InMemoryIngredientRepo::new();
let ings = ings_repo.get_ingredients(Default::default());
let langs = [Lang::default()].repeat(self.recipes.len());
self.recipes
.iter()
.zip(langs)
.map(|(rec, lang)| From::from((rec, lang, ings.clone())))
.collect()
}
}