use rocie_client::{ apis::{ api_get_auth_recipe_api::{recipe_by_id, recipe_by_name}, api_set_auth_product_api::register_product, api_set_auth_recipe_api::add_recipe, api_set_auth_unit_property_api::register_unit_property, }, models::{ Content, ContentOneOf, CooklangRecipe, Ingredient, IngredientOneOf1NotRegisteredProduct, Item, ItemOneOf, ItemOneOf1, ItemOneOf1Ingredient, ItemOneOf3, ItemOneOfText, Metadata, NameAndUrl, ProductStub, RecipeStub, Section, Step, UnitPropertyStub, }, }; use crate::testenv::{TestEnv, init::function_name, log::request}; #[expect(clippy::unnecessary_wraps)] fn name_and_url(name: &str, url: &str) -> Option { Some(NameAndUrl { name: if name.is_empty() { None } else { Some(name.to_owned()) }, url: if url.is_empty() { None } else { Some(url.to_owned()) }, }) } #[tokio::test] async fn test_recipe_metadata() { let env = TestEnv::new(function_name!()).await; let recipe_id = request!( env, add_recipe(RecipeStub { content: " --- author: James Connor description: Meaty curry with sharp anacado source and a burning d-pad. source: https://google.com/search?q=test title: Curry --- " .to_owned(), name: "Curry".to_owned(), parent: None, }) ); let output = request!(env, recipe_by_id(recipe_id)); assert_eq!(output.name, "Curry".to_owned()); assert_eq!( output.content, CooklangRecipe { cookware: vec![], ingredients: vec![], metadata: Metadata { author: name_and_url("James Connor", ""), description: Some( "Meaty curry with sharp anacado source and a burning d-pad.".to_owned() ), source: name_and_url("", "https://google.com/search?q=test"), tags: None, title: Some("Curry".to_owned()) }, sections: vec![], timers: vec![] } ); } #[tokio::test] async fn test_recipe_whitespace() { let env = TestEnv::new(function_name!()).await; let name = " Curry ".to_owned(); request!( env, add_recipe(RecipeStub { content: " nothing really ".to_owned(), name: name.clone(), parent: None, }) ); let output = request!(env, recipe_by_name(&name)); assert_eq!(output.name, name); } #[tokio::test] #[expect(clippy::too_many_lines)] async fn test_recipe_contents() { let env = TestEnv::new(function_name!()).await; let up = request!( env, register_unit_property(UnitPropertyStub { description: None, name: "mass".to_owned() }) ); let rice_id = request!( env, register_product(ProductStub { description: None, name: "rice".to_owned(), parent: None, unit_property: up, }) ); let recipe_id = request!( env, add_recipe(RecipeStub { content: " --- author: James Connor title: Curry --- Add @rice{} and @water{200%ml} to a pot. Now add @curry-spice{200%g} let rest for ~{20%min}. " .to_owned(), name: "Curry".to_owned(), parent: None, }) ); let output = request!(env, recipe_by_id(recipe_id)); assert_eq!(output.name, "Curry".to_owned()); assert_eq!( output.content.ingredients, vec![ Ingredient::IngredientOneOf(rocie_client::models::IngredientOneOf { registered_product: rocie_client::models::IngredientOneOfRegisteredProduct { alias: None, id: rice_id, quantity: None, } }), Ingredient::IngredientOneOf1(rocie_client::models::IngredientOneOf1 { not_registered_product: IngredientOneOf1NotRegisteredProduct { name: "water".to_owned(), quantity: None, } }), Ingredient::IngredientOneOf1(rocie_client::models::IngredientOneOf1 { not_registered_product: IngredientOneOf1NotRegisteredProduct { name: "curry-spice".to_owned(), quantity: None, } }), ] ); assert_eq!( output.content.sections, vec![Section { content: vec![ Content::ContentOneOf(ContentOneOf { step: Step { items: vec![ Item::ItemOneOf(ItemOneOf { text: ItemOneOfText { value: "Add ".to_owned() } }), Item::ItemOneOf1(ItemOneOf1 { ingredient: ItemOneOf1Ingredient { index: 0 } }), Item::ItemOneOf(ItemOneOf { text: ItemOneOfText { value: " and ".to_owned() } }), Item::ItemOneOf1(ItemOneOf1 { ingredient: ItemOneOf1Ingredient { index: 1 } }), Item::ItemOneOf(ItemOneOf { text: ItemOneOfText { value: " to a pot.".to_owned() } }) ], number: 1 } }), Content::ContentOneOf(ContentOneOf { step: Step { items: vec![ Item::ItemOneOf(ItemOneOf { text: ItemOneOfText { value: "Now add ".to_owned() } }), Item::ItemOneOf1(ItemOneOf1 { ingredient: ItemOneOf1Ingredient { index: 2 } }), Item::ItemOneOf(ItemOneOf { text: ItemOneOfText { value: " let rest for ".to_owned() } }), Item::ItemOneOf3(ItemOneOf3 { timer: ItemOneOf1Ingredient { index: 0 } }), Item::ItemOneOf(ItemOneOf { text: ItemOneOfText { value: ".".to_owned() } }) ], number: 2 } }) ], name: None }] ); } #[tokio::test] async fn test_recipe_full_parse() { let env = TestEnv::new(function_name!()).await; // Recipe source: https://cook.md/https://bbcgoodfood.com/recipes/easy-pancakes let recipe_id = request!( env, add_recipe(RecipeStub { content: " --- title: Easy pancakes description: Learn how to make the perfect pancakes every time with our foolproof easy crêpe recipe – elaborate flip optional image: https://images.immediate.co.uk/production/volatile/sites/30/2020/08/recipe-image-legacy-id-1273477_8-ad36e3b.jpg?resize=440,400 nutrition: calories: 61 calories fat: 2 grams fat saturated fat: 1 grams saturated fat carbohydrates: 7 grams carbohydrates sugar: 1 grams sugar protein: 3 grams protein sodium: 0.1 milligram of sodium tags: Cassie Best, Cook school, Crepe, Crêpes, easy pancakes, Flip, Flipping, Good for you, healthy pancakes, How to make pancakes, Make ahead, Pancake day, Pancake filling, Shrove Tuesday, Skills, thin pancakes source: https://bbcgoodfood.com/recipes/easy-pancakes author: Cassie Best prep time: 10 minutes course: Breakfast, Brunch, Main course time required: 30 minutes cook time: 20 minutes servings: Makes 12 cuisine: British diet: Vegetarian --- Put @plain flour{100%g}, @eggs{2}(large), @milk{300%ml}, @sunflower oil{1%tbsp} and a pinch of @salt{} into a #bowl{} or large jug, then whisk to a smooth batter. This should be similar in consistency to single cream. Set aside for ~{30%minutes} to rest if you have time, or start cooking straight away. Set a #medium frying pan{} or #crêpe pan{} over a medium heat and carefully wipe it with some oiled kitchen paper. When hot, cook your pancakes for ~{1%minute} on each side until golden, using around half a ladleful of batter per pancake. Keep them warm in a low oven as you make the rest. Serve with @?lemon wedges{} (optional) and @?caster sugar{} (optional), or your favourite filling. Once cold, you can layer the pancakes between baking parchment, then wrap in cling film and freeze for up to two months. " .to_owned(), name: "Easy pancakes".to_owned(), parent: None, }) ); let output = request!(env, recipe_by_id(recipe_id)); assert_eq!(output.name, "Easy pancakes".to_owned()); }