From 450de740b695c1d9706ad315f84acea00a9d7bc3 Mon Sep 17 00:00:00 2001 From: smilerz Date: Fri, 5 Nov 2021 12:01:36 -0500 Subject: [PATCH] RecipeFactory and all related models --- cookbook/tests/api/test_api_food.py | 6 +- .../tests/api/test_api_shopping_list_entry.py | 5 +- cookbook/tests/factories/__init__.py | 168 +++++++++++++++--- 3 files changed, 152 insertions(+), 27 deletions(-) diff --git a/cookbook/tests/api/test_api_food.py b/cookbook/tests/api/test_api_food.py index 4e1772d73..9f5d7c149 100644 --- a/cookbook/tests/api/test_api_food.py +++ b/cookbook/tests/api/test_api_food.py @@ -470,8 +470,8 @@ def test_tree_filter(obj_tree_1, obj_2, obj_3, u1_s1): # This is more about the model than the API - should this be moved to a different test? @pytest.mark.parametrize("obj_tree_1, field, inherit, new_val", [ - ({'add_categories': True, 'inherit': True}, 'supermarket_category', True, 'cat_1'), - ({'add_categories': True, 'inherit': False}, 'supermarket_category', False, 'cat_1'), + ({'has_category': True, 'inherit': True}, 'supermarket_category', True, 'cat_1'), + ({'has_category': True, 'inherit': False}, 'supermarket_category', False, 'cat_1'), ({'ignore_shopping': True, 'inherit': True}, 'ignore_shopping', True, 'false'), ({'ignore_shopping': True, 'inherit': False}, 'ignore_shopping', False, 'false'), ], indirect=['obj_tree_1']) # indirect=True populates magic variable request.param of obj_tree_1 with the parameter @@ -499,7 +499,7 @@ def test_inherit(request, obj_tree_1, field, inherit, new_val, u1_s1): # This is more about the model than the API - should this be moved to a different test? @pytest.mark.parametrize("obj_tree_1, field, inherit, new_val", [ - ({'add_categories': True, 'inherit': True, }, 'supermarket_category', True, 'cat_1'), + ({'has_category': True, 'inherit': True, }, 'supermarket_category', True, 'cat_1'), ({'ignore_shopping': True, 'inherit': True, }, 'ignore_shopping', True, 'false'), ], indirect=['obj_tree_1']) # indirect=True populates magic variable request.param of obj_tree_1 with the parameter def test_ignoreinherit_field(request, obj_tree_1, field, inherit, new_val, u1_s1): diff --git a/cookbook/tests/api/test_api_shopping_list_entry.py b/cookbook/tests/api/test_api_shopping_list_entry.py index 846f67d86..3a8853d11 100644 --- a/cookbook/tests/api/test_api_shopping_list_entry.py +++ b/cookbook/tests/api/test_api_shopping_list_entry.py @@ -6,7 +6,7 @@ from django.forms import model_to_dict from django.urls import reverse from django_scopes import scopes_disabled -from cookbook.models import ShoppingList, ShoppingListEntry, Food +from cookbook.models import Food, ShoppingList, ShoppingListEntry LIST_URL = 'api:shoppinglistentry-list' DETAIL_URL = 'api:shoppinglistentry-detail' @@ -129,3 +129,6 @@ def test_delete(u1_s1, u1_s2, obj_1): # TODO test create shopping list from recipe, excluding ingredients # TODO test auto creating shopping list from meal plan # TODO test excluding on-hand when auto creating shopping list +# test delay +# test completed_at when checked +# test completed_at cleared when unchecked diff --git a/cookbook/tests/factories/__init__.py b/cookbook/tests/factories/__init__.py index 614ba73ed..da84a6cd9 100644 --- a/cookbook/tests/factories/__init__.py +++ b/cookbook/tests/factories/__init__.py @@ -1,3 +1,6 @@ + +from decimal import Decimal + import factory import pytest from django.contrib import auth @@ -63,23 +66,20 @@ class FoodFactory(factory.django.DjangoModelFactory): name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=3)) description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10)) supermarket_category = factory.Maybe( - factory.LazyAttribute( - lambda x: - x.add_categories), + factory.LazyAttribute(lambda x: x.has_category), yes_declaration=factory.SubFactory(SupermarketCategoryFactory), no_declaration=None ) + recipe = factory.Maybe( + factory.LazyAttribute(lambda x: x.has_recipe), + yes_declaration=factory.SubFactory('cookbook.tests.factories.RecipeFactory'), + no_declaration=None + ) space = factory.SubFactory(SpaceFactory) - # this code will run immediately prior to creating the model object useful when you want a reverse relationship - # log = factory.RelatedFactory( - # UserLogFactory, - # factory_related_name='user', - # action=models.UserLog.ACTION_CREATE, - # ) - class Params: - add_categories = False + has_category = False + has_recipe = False class Meta: model = 'cookbook.Food' @@ -99,7 +99,7 @@ class IngredientFactory(factory.django.DjangoModelFactory): """Ingredient factory.""" food = factory.SubFactory(FoodFactory) unit = factory.SubFactory(UnitFactory) - amount = 1 + amount = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=10)) note = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5)) space = factory.SubFactory(SpaceFactory) @@ -107,20 +107,142 @@ class IngredientFactory(factory.django.DjangoModelFactory): model = 'cookbook.Ingredient' -class ShoppingListEntryFactory(factory.django.DjangoModelFactory): - """ShoppingListEntry factory.""" - # list_recipe = models.ForeignKey(ShoppingListRecipe, on_delete=models.CASCADE, null=True, blank=True, related_name='entries') - food = factory.SubFactory(FoodFactory) - unit = factory.SubFactory(UnitFactory) - ingredient = factory.SubFactory(IngredientFactory) - amount = 1 +class MealTypeFactory(factory.django.DjangoModelFactory): + name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5)) order = 0 - checked = False + # icon = + color = factory.LazyAttribute(lambda x: faker.safe_hex_color()) + default = False created_by = factory.SubFactory(UserFactory) - # created_at = models.DateTimeField(auto_now_add=True) - # completed_at = models.DateTimeField(null=True, blank=True) - # delay_until = models.DateTimeField(null=True, blank=True) space = factory.SubFactory(SpaceFactory) + class Meta: + model = 'cookbook.MealType' + + +class MealPlanFactory(factory.django.DjangoModelFactory): + recipe = factory.Maybe( + factory.LazyAttribute(lambda x: x.has_recipe), + yes_declaration=factory.SubFactory('cookbook.tests.factories.RecipeFactory'), + no_declaration=None + ) + servings = factory.LazyAttribute(lambda x: Decimal(faker.random_int(min=1, max=1000)/100)) + title = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5)) + created_by = factory.SubFactory(UserFactory) + meal_type = factory.SubFactory(MealTypeFactory) + note = factory.LazyAttribute(lambda x: faker.paragraph()) + date = factory.LazyAttribute(lambda x: faker.future_date()) + space = factory.SubFactory(SpaceFactory) + + class Params: + has_recipe = False + + class Meta: + model = 'cookbook.MealPlan' + + +class ShoppingListRecipeFactory(factory.django.DjangoModelFactory): + name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5)) + recipe = factory.Maybe( + factory.LazyAttribute(lambda x: x.has_recipe), + yes_declaration=factory.SubFactory('cookbook.tests.factories.RecipeFactory'), + no_declaration=None + ) + servings = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=10)) + mealplan = factory.SubFactory(MealPlanFactory) + + class Params: + has_recipe = False + + class Meta: + model = 'cookbook.ShoppingListRecipe' + + +class ShoppingListEntryFactory(factory.django.DjangoModelFactory): + """ShoppingListEntry factory.""" + list_recipe = factory.Maybe( + factory.LazyAttribute(lambda x: x.has_mealplan), + yes_declaration=factory.SubFactory(ShoppingListRecipeFactory), + no_declaration=None + ) + food = factory.SubFactory(FoodFactory) + unit = factory.SubFactory(UnitFactory) + ingredient = factory.SubFactory(IngredientFactory) + amount = factory.LazyAttribute(lambda x: Decimal(faker.random_int(min=1, max=10))/100) + order = 0 + checked = False + created_by = factory.SubFactory(UserFactory) + created_at = factory.LazyAttribute(lambda x: faker.past_date()) + completed_at = None + delay_until = None + space = factory.SubFactory(SpaceFactory) + + class Params: + has_mealplan = False + class Meta: model = 'cookbook.ShoppingListEntry' + + +class StepFactory(factory.django.DjangoModelFactory): + name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5)) + # type = models.CharField( + # choices=((TEXT, _('Text')), (TIME, _('Time')), (FILE, _('File')), (RECIPE, _('Recipe')),), + # default=TEXT, + # max_length=16 + # ) + instruction = factory.LazyAttribute(lambda x: ''.join(faker.paragraphs(nb=5))) + ingredients = factory.SubFactory(IngredientFactory) + time = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=1000)) + order = 0 + # file = models.ForeignKey('UserFile', on_delete=models.PROTECT, null=True, blank=True) + show_as_header = True + step_recipe = factory.Maybe( + factory.LazyAttribute(lambda x: x.has_recipe), + yes_declaration=factory.SubFactory('cookbook.tests.factories.RecipeFactory'), + no_declaration=None + ) + space = factory.SubFactory(SpaceFactory) + + class Params: + has_recipe = False + + class Meta: + model = 'cookbook.Step' + + +class RecipeFactory(factory.django.DjangoModelFactory): + name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=7)) + description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10)) + servings = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=20)) + servings_text = factory.LazyAttribute(lambda x: faker.sentence(nb_words=1)) + # image = models.ImageField(upload_to='recipes/', blank=True, null=True) + # storage = models.ForeignKey( + # Storage, on_delete=models.PROTECT, blank=True, null=True + # ) + # file_uid = models.CharField(max_length=256, default="", blank=True) + # file_path = models.CharField(max_length=512, default="", blank=True) + # link = models.CharField(max_length=512, null=True, blank=True) + # cors_link = models.CharField(max_length=1024, null=True, blank=True) + # keywords = factory.SubFactory(KeywordFactory) + steps = factory.SubFactory(StepFactory) + working_time = factory.LazyAttribute(lambda x: faker.random_int(min=0, max=360)) + waiting_time = factory.LazyAttribute(lambda x: faker.random_int(min=0, max=360)) + internal = False + # nutrition = models.ForeignKey( + # NutritionInformation, blank=True, null=True, on_delete=models.CASCADE + # ) + created_by = factory.SubFactory(UserFactory) + created_at = factory.LazyAttribute(lambda x: faker.date_this_decade()) + # updated_at = models.DateTimeField(auto_now=True) + space = factory.SubFactory(SpaceFactory) + + class Meta: + model = 'cookbook.Recipe' + + # this code will run immediately prior to creating the model object useful when you want a reverse relationship + # log = factory.RelatedFactory( + # UserLogFactory, + # factory_related_name='user', + # action=models.UserLog.ACTION_CREATE, + # )