fix food tests

This commit is contained in:
smilerz 2023-04-21 13:14:23 -05:00
parent 8a8be7fb2d
commit 8c3195937b
No known key found for this signature in database
GPG Key ID: 39444C7606D47126
6 changed files with 328 additions and 223 deletions

View File

@ -56,23 +56,32 @@ def obj_tree_1(request, space_1):
params = request.param # request.param is a magic variable
except AttributeError:
params = {}
objs = []
inherit = params.pop('inherit', False)
objs.extend(FoodFactory.create_batch(3, space=space_1, **params))
FoodFactory.create_batch(3, space=space_1, **params)
objs = Food.objects.values_list('id', flat=True)
obj_id = objs[1]
child_id = objs[0]
parent_id = objs[2]
# set all foods to inherit everything
if inherit:
inherit = Food.inheritable_fields
Through = Food.objects.filter(space=space_1).first().inherit_fields.through
Through = Food.objects.filter(
space=space_1).first().inherit_fields.through
for i in inherit:
Through.objects.bulk_create([
Through(food_id=x, foodinheritfield_id=i.id)
for x in Food.objects.filter(space=space_1).values_list('id', flat=True)
])
objs[0].move(objs[1], node_location)
objs[1].move(objs[2], node_location)
return Food.objects.get(id=objs[1].id) # whenever you move/merge a tree it's safest to re-get the object
Food.objects.get(id=child_id).move(
Food.objects.get(id=obj_id), node_location)
Food.objects.get(id=obj_id).move(
Food.objects.get(id=parent_id), node_location)
# whenever you move/merge a tree it's safest to re-get the object
return Food.objects.get(id=obj_id)
@pytest.mark.parametrize("arg", [
@ -107,19 +116,23 @@ def test_list_filter(obj_1, obj_2, u1_s1):
assert obj_2.name in [x['name'] for x in response['results']]
assert response['results'][0]['name'] < response['results'][1]['name']
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?page_size=1').content)
response = json.loads(
u1_s1.get(f'{reverse(LIST_URL)}?page_size=1').content)
assert len(response['results']) == 1
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?limit=1').content)
assert len(response['results']) == 1
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query=''&limit=1').content)
response = json.loads(
u1_s1.get(f'{reverse(LIST_URL)}?query=''&limit=1').content)
assert len(response['results']) == 1
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query=chicken').content)
response = json.loads(
u1_s1.get(f'{reverse(LIST_URL)}?query=chicken').content)
assert response['count'] == 0
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?query={obj_1.name[:-4]}').content)
response = json.loads(
u1_s1.get(f'{reverse(LIST_URL)}?query={obj_1.name[:-4]}').content)
assert response['count'] == 1
@ -262,8 +275,9 @@ def test_integrity(u1_s1, recipe_1_s1):
def test_move(u1_s1, obj_tree_1, obj_2, obj_3, space_1):
with scope(space=space_1):
# for some reason the 'path' attribute changes between the factory and the test when using both obj_tree and obj
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
parent = obj_tree_1.get_parent()
child = obj_tree_1.get_descendants()[0]
assert parent.get_num_children() == 1
assert parent.get_descendant_count() == 2
assert Food.get_root_nodes().filter(space=space_1).count() == 2
@ -295,8 +309,9 @@ def test_move(u1_s1, obj_tree_1, obj_2, obj_3, space_1):
def test_move_errors(u1_s1, obj_tree_1, obj_3, space_1):
with scope(space=space_1):
# for some reason the 'path' attribute changes between the factory and the test when using both obj_tree and obj
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
parent = obj_tree_1.get_parent()
child = obj_tree_1.get_descendants()[0]
# move child to root
r = u1_s1.put(reverse(MOVE_URL, args=[obj_tree_1.id, 0]))
assert r.status_code == 200
@ -351,7 +366,7 @@ def test_merge_shopping_entries(obj_tree_1, u1_s1, space_1):
with scope(space=space_1):
parent = obj_tree_1.get_parent()
child = obj_tree_1.get_descendants()[0]
ShoppingListEntryFactory.create(food=parent, space=space_1)
ShoppingListEntryFactory.create(food=parent, space=space_1)
ShoppingListEntryFactory.create(food=child, space=space_1)
assert parent.get_num_children() == 1
assert parent.get_descendant_count() == 2
@ -371,8 +386,10 @@ def test_merge_shopping_entries(obj_tree_1, u1_s1, space_1):
assert obj_tree_1.shopping_entries.count() == 1 # now has child's ingredient
def test_merge(u1_s1, obj_tree_1, obj_1, obj_3, space_1):
def test_merge(u1_s1, obj_tree_1, obj_1, obj_3, space_1):
with scope(space=space_1):
# for some reason the 'path' attribute changes between the factory and the test when using both obj_tree and obj
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
parent = obj_tree_1.get_parent()
child = obj_tree_1.get_descendants()[0]
assert parent.get_num_children() == 1
@ -417,7 +434,6 @@ def test_merge(u1_s1, obj_tree_1, obj_1, obj_3, space_1):
def test_merge_errors(u1_s1, obj_tree_1, obj_3, space_1):
with scope(space=space_1):
parent = obj_tree_1.get_parent()
child = obj_tree_1.get_descendants()[0]
# attempt to merge with non-existent parent
r = u1_s1.put(
@ -451,8 +467,9 @@ def test_merge_errors(u1_s1, obj_tree_1, obj_3, space_1):
def test_root_filter(obj_tree_1, obj_2, obj_3, u1_s1):
with scope(space=obj_tree_1.space):
# for some reason the 'path' attribute changes between the factory and the test when using both obj_tree and obj
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
parent = obj_tree_1.get_parent()
child = obj_tree_1.get_descendants()[0]
# should return root objects in the space (obj_1, obj_2), ignoring query filters
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?root=0').content)
@ -461,34 +478,46 @@ def test_root_filter(obj_tree_1, obj_2, obj_3, u1_s1):
with scopes_disabled():
obj_2.move(parent, node_location)
# should return direct children of parent (obj_tree_1, obj_2), ignoring query filters
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?root={parent.id}').content)
response = json.loads(
u1_s1.get(f'{reverse(LIST_URL)}?root={parent.id}').content)
assert response['count'] == 2
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?root={parent.id}&query={obj_2.name[4:]}').content)
response = json.loads(u1_s1.get(
f'{reverse(LIST_URL)}?root={parent.id}&query={obj_2.name[4:]}').content)
assert response['count'] == 2
def test_tree_filter(obj_tree_1, obj_2, obj_3, u1_s1):
with scope(space=obj_tree_1.space):
# for some reason the 'path' attribute changes between the factory and the test when using both obj_tree and obj
obj_tree_1 = Food.objects.get(id=obj_tree_1.id)
parent = obj_tree_1.get_parent()
child = obj_tree_1.get_descendants()[0]
obj_2.move(parent, node_location)
# should return full tree starting at parent (obj_tree_1, obj_2), ignoring query filters
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?tree={parent.id}').content)
response = json.loads(
u1_s1.get(f'{reverse(LIST_URL)}?tree={parent.id}').content)
assert response['count'] == 4
response = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?tree={parent.id}&query={obj_2.name[4:]}').content)
response = json.loads(u1_s1.get(
f'{reverse(LIST_URL)}?tree={parent.id}&query={obj_2.name[4:]}').content)
assert response['count'] == 4
# 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", [
({'has_category': True, 'inherit': True}, 'supermarket_category', True, 'cat_1'),
({'has_category': 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'),
({'substitute_children': True, 'inherit': True}, 'substitute_children', True, 'false'),
({'substitute_children': True, 'inherit': False}, 'substitute_children', False, 'false'),
({'substitute_siblings': True, 'inherit': True}, 'substitute_siblings', True, 'false'),
({'substitute_siblings': True, 'inherit': False}, 'substitute_siblings', False, 'false'),
({'ignore_shopping': True, 'inherit': False},
'ignore_shopping', False, 'false'),
({'substitute_children': True, 'inherit': True},
'substitute_children', True, 'false'),
({'substitute_children': True, 'inherit': False},
'substitute_children', False, 'false'),
({'substitute_siblings': True, 'inherit': True},
'substitute_siblings', True, 'false'),
({'substitute_siblings': True, 'inherit': False},
'substitute_siblings', False, 'false'),
], indirect=['obj_tree_1']) # indirect=True populates magic variable request.param of obj_tree_1 with the parameter
def test_inherit(request, obj_tree_1, field, inherit, new_val, u1_s1):
with scope(space=obj_tree_1.space):
@ -498,8 +527,10 @@ def test_inherit(request, obj_tree_1, field, inherit, new_val, u1_s1):
new_val = request.getfixturevalue(new_val)
# if this test passes it demonstrates that inheritance works
# when moving to a parent as each food is created with a different category
assert (getattr(parent, field) == getattr(obj_tree_1, field)) in [inherit, True]
assert (getattr(obj_tree_1, field) == getattr(child, field)) in [inherit, True]
assert (getattr(parent, field) == getattr(
obj_tree_1, field)) in [inherit, True]
assert (getattr(obj_tree_1, field) == getattr(
child, field)) in [inherit, True]
# change parent to a new value
setattr(parent, field, new_val)
with scope(space=parent.space):
@ -515,7 +546,8 @@ def test_inherit(request, obj_tree_1, field, inherit, new_val, u1_s1):
@pytest.mark.parametrize("obj_tree_1", [
({'has_category': True, 'inherit': False, 'ignore_shopping': True, 'substitute_children': True, 'substitute_siblings': True}),
({'has_category': True, 'inherit': False, 'ignore_shopping': True,
'substitute_children': True, 'substitute_siblings': True}),
], indirect=['obj_tree_1'])
@pytest.mark.parametrize("global_reset", [True, False])
@pytest.mark.parametrize("field", ['ignore_shopping', 'substitute_children', 'substitute_siblings', 'supermarket_category'])
@ -534,10 +566,13 @@ def test_reset_inherit_space_fields(obj_tree_1, space_1, global_reset, field):
assert getattr(parent, field) != getattr(obj_tree_1, field)
if global_reset:
space_1.food_inherit.add(*Food.inheritable_fields.values_list('id', flat=True)) # set default inherit fields
# set default inherit fields
space_1.food_inherit.add(
*Food.inheritable_fields.values_list('id', flat=True))
parent.reset_inheritance(space=space_1)
else:
obj_tree_1.child_inherit_fields.set(Food.inheritable_fields.values_list('id', flat=True))
obj_tree_1.child_inherit_fields.set(
Food.inheritable_fields.values_list('id', flat=True))
obj_tree_1.save()
parent.reset_inheritance(space=space_1, food=obj_tree_1)
# djangotree bypasses ORM and need to be retrieved again
@ -545,12 +580,14 @@ def test_reset_inherit_space_fields(obj_tree_1, space_1, global_reset, field):
parent = Food.objects.get(id=parent.id)
child = Food.objects.get(id=child.id)
assert (getattr(parent, field) == getattr(obj_tree_1, field)) == global_reset
assert (getattr(parent, field) == getattr(
obj_tree_1, field)) == global_reset
assert getattr(obj_tree_1, field) == getattr(child, field)
@pytest.mark.parametrize("obj_tree_1", [
({'has_category': True, 'inherit': False, 'ignore_shopping': True, 'substitute_children': True, 'substitute_siblings': True}),
({'has_category': True, 'inherit': False, 'ignore_shopping': True,
'substitute_children': True, 'substitute_siblings': True}),
], indirect=['obj_tree_1'])
@pytest.mark.parametrize("field", ['ignore_shopping', 'substitute_children', 'substitute_siblings', 'supermarket_category'])
def test_reset_inherit_no_food_instances(obj_tree_1, space_1, field):
@ -558,13 +595,17 @@ def test_reset_inherit_no_food_instances(obj_tree_1, space_1, field):
parent = obj_tree_1.get_parent()
Food.objects.all().delete()
space_1.food_inherit.add(*Food.inheritable_fields.values_list('id', flat=True)) # set default inherit fields
# set default inherit fields
space_1.food_inherit.add(
*Food.inheritable_fields.values_list('id', flat=True))
parent.reset_inheritance(space=space_1)
def test_onhand(obj_1, u1_s1, u2_s1):
assert json.loads(u1_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)['food_onhand'] == False
assert json.loads(u2_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)['food_onhand'] == False
assert json.loads(u1_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)[
'food_onhand'] == False
assert json.loads(u2_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)[
'food_onhand'] == False
u1_s1.patch(
reverse(
@ -574,10 +615,13 @@ def test_onhand(obj_1, u1_s1, u2_s1):
{'food_onhand': True},
content_type='application/json'
)
assert json.loads(u1_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)['food_onhand'] == True
assert json.loads(u2_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)['food_onhand'] == False
assert json.loads(u1_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)[
'food_onhand'] == True
assert json.loads(u2_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)[
'food_onhand'] == False
user1 = auth.get_user(u1_s1)
user2 = auth.get_user(u2_s1)
user1.userpreference.shopping_share.add(user2)
assert json.loads(u2_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)['food_onhand'] == True
assert json.loads(u2_s1.get(reverse(DETAIL_URL, args={obj_1.id})).content)[
'food_onhand'] == True

View File

@ -1,20 +1,14 @@
import json
from datetime import timedelta
import factory
import pytest
# work around for bug described here https://stackoverflow.com/a/70312265/15762829
from django.conf import settings
from django.contrib import auth
from django.forms import model_to_dict
from django.urls import reverse
from django.utils import timezone
from django_scopes import scope, scopes_disabled
from pytest_factoryboy import LazyFixture, register
from django_scopes import scopes_disabled
from cookbook.models import Food, Ingredient, ShoppingListEntry, Step
from cookbook.tests.factories import (IngredientFactory, MealPlanFactory, RecipeFactory,
StepFactory, UserFactory)
from cookbook.models import Food, Ingredient
from cookbook.tests.factories import MealPlanFactory, RecipeFactory, StepFactory, UserFactory
if settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2',
'django.db.backends.postgresql']:
@ -32,9 +26,12 @@ def user2(request, u1_s1):
except AttributeError:
params = {}
user = auth.get_user(u1_s1)
user.userpreference.mealplan_autoadd_shopping = params.get('mealplan_autoadd_shopping', True)
user.userpreference.mealplan_autoinclude_related = params.get('mealplan_autoinclude_related', True)
user.userpreference.mealplan_autoexclude_onhand = params.get('mealplan_autoexclude_onhand', True)
user.userpreference.mealplan_autoadd_shopping = params.get(
'mealplan_autoadd_shopping', True)
user.userpreference.mealplan_autoinclude_related = params.get(
'mealplan_autoinclude_related', True)
user.userpreference.mealplan_autoexclude_onhand = params.get(
'mealplan_autoexclude_onhand', True)
user.userpreference.save()
return u1_s1
@ -50,7 +47,6 @@ def recipe(request, space_1, u1_s1):
return RecipeFactory(**params)
@pytest.mark.parametrize("arg", [
['g1_s1', 204],
['u1_s1', 204],
@ -59,11 +55,14 @@ def recipe(request, space_1, u1_s1):
])
@pytest.mark.parametrize("recipe, sle_count", [
({}, 10),
({'steps__recipe_count': 1}, 20), # shopping list from recipe with StepRecipe
({'steps__food_recipe_count': {'step': 0, 'count': 1}}, 19), # shopping list from recipe with food recipe
({'steps__food_recipe_count': {'step': 0, 'count': 1}, 'steps__recipe_count': 1}, 29), # shopping list from recipe with StepRecipe and food recipe
# shopping list from recipe with StepRecipe
({'steps__recipe_count': 1}, 20),
# shopping list from recipe with food recipe
({'steps__food_recipe_count': {'step': 0, 'count': 1}}, 19),
# shopping list from recipe with StepRecipe and food recipe
({'steps__food_recipe_count': {'step': 0, 'count': 1}, 'steps__recipe_count': 1}, 29),
], indirect=['recipe'])
def test_shopping_recipe_method(request, arg, recipe, sle_count, u1_s1, u2_s1):
def test_shopping_recipe_method(request, arg, recipe, sle_count, u1_s1, u2_s1):
c = request.getfixturevalue(arg[0])
user = auth.get_user(c)
user.userpreference.mealplan_autoadd_shopping = True
@ -78,16 +77,20 @@ def test_shopping_recipe_method(request, arg, recipe, sle_count, u1_s1, u2_s1):
if r.status_code == 204: # skip anonymous user
r = json.loads(c.get(reverse(SHOPPING_LIST_URL)).content)
assert len(r) == sle_count # recipe factory creates 10 ingredients by default
# recipe factory creates 10 ingredients by default
assert len(r) == sle_count
assert [x['created_by']['id'] for x in r].count(user.id) == sle_count
# user in space can't see shopping list
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 0
assert len(json.loads(
u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 0
user.userpreference.shopping_share.add(auth.get_user(u2_s1))
# after share, user in space can see shopping list
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
assert len(json.loads(
u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
# confirm that the author of the recipe doesn't have access to shopping list
if c != u1_s1:
assert len(json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 0
assert len(json.loads(
u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 0
r = c.get(url)
assert r.status_code == 405
@ -99,9 +102,12 @@ def test_shopping_recipe_method(request, arg, recipe, sle_count, u1_s1, u2_s1):
@pytest.mark.parametrize("recipe, sle_count", [
({}, 10),
({'steps__recipe_count': 1}, 20), # shopping list from recipe with StepRecipe
({'steps__food_recipe_count': {'step': 0, 'count': 1}}, 19), # shopping list from recipe with food recipe
({'steps__food_recipe_count': {'step': 0, 'count': 1}, 'steps__recipe_count': 1}, 29), # shopping list from recipe with StepRecipe and food recipe
# shopping list from recipe with StepRecipe
({'steps__recipe_count': 1}, 20),
# shopping list from recipe with food recipe
({'steps__food_recipe_count': {'step': 0, 'count': 1}}, 19),
# shopping list from recipe with StepRecipe and food recipe
({'steps__food_recipe_count': {'step': 0, 'count': 1}, 'steps__recipe_count': 1}, 29),
], indirect=['recipe'])
@pytest.mark.parametrize("use_mealplan", [(False), (True), ])
def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u2_s1):
@ -115,31 +121,33 @@ def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u
user.userpreference.save()
if use_mealplan:
mealplan = MealPlanFactory(space=recipe.space, created_by=user, servings=recipe.servings, recipe=recipe)
mealplan = MealPlanFactory(
space=recipe.space, created_by=user, servings=recipe.servings, recipe=recipe)
else:
u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}))
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
assert [x['created_by']['id'] for x in r].count(user.id) == sle_count
all_ing = [x['ingredient'] for x in r]
keep_ing = all_ing[1:-1] # remove first and last element
del keep_ing[int(len(keep_ing)/2)] # remove a middle element
del keep_ing[int(len(keep_ing) / 2)] # remove a middle element
list_recipe = r[0]['list_recipe']
amount_sum = sum([x['amount'] for x in r])
# test modifying shopping list as different user
# test increasing servings size of recipe shopping list
if use_mealplan:
mealplan.servings = 2*recipe.servings
mealplan.servings = 2 * recipe.servings
mealplan.save()
else:
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
{'list_recipe': list_recipe, 'servings': 2*recipe.servings},
{'list_recipe': list_recipe, 'servings': 2 * recipe.servings},
content_type='application/json'
)
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
assert sum([x['amount'] for x in r]) == amount_sum * 2
assert len(r) == sle_count
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
assert len(json.loads(
u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
# testing decreasing servings size of recipe shopping list
if use_mealplan:
@ -153,7 +161,8 @@ def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
assert sum([x['amount'] for x in r]) == amount_sum * .5
assert len(r) == sle_count
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
assert len(json.loads(
u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
# test removing 3 items from shopping list
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
@ -162,7 +171,8 @@ def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u
)
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
assert len(r) == sle_count - 3
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count - 3
assert len(json.loads(
u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count - 3
# add all ingredients to existing shopping list - don't change serving size
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
@ -172,14 +182,16 @@ def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
assert sum([x['amount'] for x in r]) == amount_sum * .5
assert len(r) == sle_count
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
assert len(json.loads(
u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
@pytest.mark.parametrize("user2, sle_count", [
({'mealplan_autoadd_shopping': False}, (0, 18)),
({'mealplan_autoinclude_related': False}, (9, 9)),
({'mealplan_autoexclude_onhand': False}, (20, 20)),
({'mealplan_autoexclude_onhand': False, 'mealplan_autoinclude_related': False}, (10, 10)),
({'mealplan_autoexclude_onhand': False,
'mealplan_autoinclude_related': False}, (10, 10)),
], indirect=['user2'])
@pytest.mark.parametrize("use_mealplan", [(False), (True), ])
@pytest.mark.parametrize("recipe", [({'steps__recipe_count': 1})], indirect=['recipe'])
@ -191,20 +203,24 @@ def test_shopping_recipe_userpreference(recipe, sle_count, use_mealplan, user2):
food = Food.objects.get(id=ingredients[2].food.id)
food.onhand_users.add(user)
food.save()
food = recipe.steps.exclude(step_recipe=None).first().step_recipe.steps.first().ingredients.first().food
food = recipe.steps.exclude(step_recipe=None).first(
).step_recipe.steps.first().ingredients.first().food
food = Food.objects.get(id=food.id)
food.onhand_users.add(user)
food.save()
if use_mealplan:
mealplan = MealPlanFactory(space=recipe.space, created_by=user, servings=recipe.servings, recipe=recipe)
assert len(json.loads(user2.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count[0]
MealPlanFactory(
space=recipe.space, created_by=user, servings=recipe.servings, recipe=recipe)
assert len(json.loads(
user2.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count[0]
else:
user2.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}))
assert len(json.loads(user2.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count[1]
assert len(json.loads(
user2.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count[1]
def test_shopping_recipe_mixed_authors(u1_s1, u2_s1,space_1):
def test_shopping_recipe_mixed_authors(u1_s1, u2_s1, space_1):
with scopes_disabled():
user1 = auth.get_user(u1_s1)
user2 = auth.get_user(u2_s1)
@ -213,15 +229,19 @@ def test_shopping_recipe_mixed_authors(u1_s1, u2_s1,space_1):
recipe1 = RecipeFactory(created_by=user1, space=space)
recipe2 = RecipeFactory(created_by=user2, space=space)
recipe3 = RecipeFactory(created_by=user3, space=space)
food = Food.objects.get(id=recipe1.steps.first().ingredients.first().food.id)
food = Food.objects.get(
id=recipe1.steps.first().ingredients.first().food.id)
food.recipe = recipe2
food.save()
recipe1.steps.add(StepFactory(step_recipe=recipe3, ingredients__count=0, space=space))
recipe1.steps.add(StepFactory(step_recipe=recipe3,
ingredients__count=0, space=space))
recipe1.save()
u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe1.id}))
assert len(json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 29
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 0
assert len(json.loads(
u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 29
assert len(json.loads(
u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 0
@pytest.mark.parametrize("recipe", [{'steps__ingredients__header': 1}], indirect=['recipe'])
@ -230,4 +250,5 @@ def test_shopping_with_header_ingredient(u1_s1, recipe):
# recipe.step_set.first().ingredient_set.add(IngredientFactory(ingredients__header=1))
u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}))
assert len(json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 10
assert len(json.loads(u1_s1.get(reverse('api:ingredient-list')).content)['results']) == 11
assert len(json.loads(
u1_s1.get(reverse('api:ingredient-list')).content)['results']) == 11

View File

@ -4,13 +4,12 @@ from decimal import Decimal
import factory
import pytest
from django.contrib import auth
from django.contrib.auth.models import Group, User
from django_scopes import scopes_disabled
from faker import Factory as FakerFactory
from pytest_factoryboy import register
from cookbook.models import Recipe, Step, UserSpace
from cookbook.models import UserSpace
# this code will run immediately prior to creating the model object useful when you want a reverse relationship
# log = factory.RelatedFactory(
@ -53,7 +52,8 @@ class SpaceFactory(factory.django.DjangoModelFactory):
class UserFactory(factory.django.DjangoModelFactory):
"""User factory."""
username = factory.LazyAttribute(lambda x: faker.simple_profile()['username'])
username = factory.LazyAttribute(
lambda x: faker.simple_profile()['username'])
first_name = factory.LazyAttribute(lambda x: faker.first_name())
last_name = factory.LazyAttribute(lambda x: faker.last_name())
email = factory.LazyAttribute(lambda x: faker.email())
@ -65,7 +65,8 @@ class UserFactory(factory.django.DjangoModelFactory):
return
if extracted:
us = UserSpace.objects.create(space=self.space, user=self, active=True)
us = UserSpace.objects.create(
space=self.space, user=self, active=True)
us.groups.add(Group.objects.get(name=extracted))
@factory.post_generation
@ -75,7 +76,8 @@ class UserFactory(factory.django.DjangoModelFactory):
if extracted:
for prefs in extracted:
self.userpreference[prefs] = extracted[prefs]/0 # intentionally break so it can be debugged later
# intentionally break so it can be debugged later
self.userpreference[prefs] = extracted[prefs]/0
class Meta:
model = User
@ -98,18 +100,22 @@ class SupermarketCategoryFactory(factory.django.DjangoModelFactory):
class FoodFactory(factory.django.DjangoModelFactory):
"""Food factory."""
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10)[:128])
plural_name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=3, variable_nb_words=False))
plural_name = factory.LazyAttribute(
lambda x: faker.sentence(nb_words=3, variable_nb_words=False))
description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10))
supermarket_category = factory.Maybe(
factory.LazyAttribute(lambda x: x.has_category),
yes_declaration=factory.SubFactory(SupermarketCategoryFactory, space=factory.SelfAttribute('..space')),
factory.LazyAttribute(lambda x: x.has_category),
yes_declaration=factory.SubFactory(
SupermarketCategoryFactory, space=factory.SelfAttribute('..space')),
no_declaration=None
)
recipe = factory.Maybe(
factory.LazyAttribute(lambda x: x.has_recipe),
yes_declaration=factory.SubFactory('cookbook.tests.factories.RecipeFactory', space=factory.SelfAttribute('..space')),
factory.LazyAttribute(lambda x: x.has_recipe),
yes_declaration=factory.SubFactory(
'cookbook.tests.factories.RecipeFactory', space=factory.SelfAttribute('..space')),
no_declaration=None
)
path = None
space = factory.SubFactory(SpaceFactory)
@factory.post_generation
@ -127,17 +133,19 @@ class FoodFactory(factory.django.DjangoModelFactory):
class Meta:
model = 'cookbook.Food'
django_get_or_create = ('name', 'plural_name', 'space',)
django_get_or_create = ('name', 'plural_name', 'path', 'space',)
@register
class RecipeBookFactory(factory.django.DjangoModelFactory):
"""RecipeBook factory."""
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=3, variable_nb_words=False))
name = factory.LazyAttribute(lambda x: faker.sentence(
nb_words=3, variable_nb_words=False))
description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10))
icon = None
# shared = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
created_by = factory.SubFactory(
UserFactory, space=factory.SelfAttribute('..space'))
filter = None
space = factory.SubFactory(SpaceFactory)
@ -149,7 +157,8 @@ class RecipeBookFactory(factory.django.DjangoModelFactory):
@register
class RecipeBookEntryFactory(factory.django.DjangoModelFactory):
"""RecipeBookEntry factory."""
book = factory.SubFactory(RecipeBookFactory, space=factory.SelfAttribute('..recipe.space'))
book = factory.SubFactory(
RecipeBookFactory, space=factory.SelfAttribute('..recipe.space'))
recipe = None
class Meta:
@ -173,7 +182,8 @@ class UnitFactory(factory.django.DjangoModelFactory):
@register
class KeywordFactory(factory.django.DjangoModelFactory):
"""Keyword factory."""
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=2, variable_nb_words=False))
name = factory.LazyAttribute(lambda x: faker.sentence(
nb_words=2, variable_nb_words=False))
# icon = models.CharField(max_length=16, blank=True, null=True)
description = factory.LazyAttribute(lambda x: faker.sentence(nb_words=10))
space = factory.SubFactory(SpaceFactory)
@ -184,15 +194,17 @@ class KeywordFactory(factory.django.DjangoModelFactory):
class Meta:
model = 'cookbook.Keyword'
django_get_or_create = ('name', 'space',)
django_get_or_create = ('name', 'space')
exclude = ('num')
@register
class IngredientFactory(factory.django.DjangoModelFactory):
"""Ingredient factory."""
food = factory.SubFactory(FoodFactory, space=factory.SelfAttribute('..space'))
unit = factory.SubFactory(UnitFactory, space=factory.SelfAttribute('..space'))
food = factory.SubFactory(
FoodFactory, space=factory.SelfAttribute('..space'))
unit = factory.SubFactory(
UnitFactory, space=factory.SelfAttribute('..space'))
amount = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=10))
note = factory.LazyAttribute(lambda x: faker.sentence(nb_words=8))
is_header = False
@ -210,7 +222,8 @@ class MealTypeFactory(factory.django.DjangoModelFactory):
# icon =
color = factory.LazyAttribute(lambda x: faker.safe_hex_color())
default = False
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
created_by = factory.SubFactory(
UserFactory, space=factory.SelfAttribute('..space'))
space = factory.SubFactory(SpaceFactory)
class Meta:
@ -221,13 +234,17 @@ class MealTypeFactory(factory.django.DjangoModelFactory):
class MealPlanFactory(factory.django.DjangoModelFactory):
recipe = factory.Maybe(
factory.LazyAttribute(lambda x: x.has_recipe),
yes_declaration=factory.SubFactory('cookbook.tests.factories.RecipeFactory', space=factory.SelfAttribute('..space')),
yes_declaration=factory.SubFactory(
'cookbook.tests.factories.RecipeFactory', space=factory.SelfAttribute('..space')),
no_declaration=None
)
servings = factory.LazyAttribute(lambda x: Decimal(faker.random_int(min=1, max=1000)/100))
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, space=factory.SelfAttribute('..space'))
meal_type = factory.SubFactory(MealTypeFactory, space=factory.SelfAttribute('..space'))
created_by = factory.SubFactory(
UserFactory, space=factory.SelfAttribute('..space'))
meal_type = factory.SubFactory(
MealTypeFactory, space=factory.SelfAttribute('..space'))
note = factory.LazyAttribute(lambda x: faker.paragraph())
date = factory.LazyAttribute(lambda x: faker.future_date())
space = factory.SubFactory(SpaceFactory)
@ -243,12 +260,14 @@ class MealPlanFactory(factory.django.DjangoModelFactory):
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', space=factory.SelfAttribute('..space')),
factory.LazyAttribute(lambda x: x.has_recipe),
yes_declaration=factory.SubFactory(
'cookbook.tests.factories.RecipeFactory', space=factory.SelfAttribute('..space')),
no_declaration=None
)
servings = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=10))
mealplan = factory.SubFactory(MealPlanFactory, space=factory.SelfAttribute('..space'))
mealplan = factory.SubFactory(
MealPlanFactory, space=factory.SelfAttribute('..space'))
space = factory.SubFactory(SpaceFactory)
class Params:
@ -263,26 +282,33 @@ class ShoppingListEntryFactory(factory.django.DjangoModelFactory):
"""ShoppingListEntry factory."""
list_recipe = factory.Maybe(
factory.LazyAttribute(lambda x: x.has_mealplan),
yes_declaration=factory.SubFactory(ShoppingListRecipeFactory, space=factory.SelfAttribute('..space')),
factory.LazyAttribute(lambda x: x.has_mealplan),
yes_declaration=factory.SubFactory(
ShoppingListRecipeFactory, space=factory.SelfAttribute('..space')),
no_declaration=None
)
food = factory.SubFactory(FoodFactory, space=factory.SelfAttribute('..space'))
unit = factory.SubFactory(UnitFactory, space=factory.SelfAttribute('..space'))
food = factory.SubFactory(
FoodFactory, space=factory.SelfAttribute('..space'))
unit = factory.SubFactory(
UnitFactory, space=factory.SelfAttribute('..space'))
# # ingredient = factory.SubFactory(IngredientFactory)
amount = factory.LazyAttribute(lambda x: Decimal(faker.random_int(min=1, max=100))/10)
amount = factory.LazyAttribute(
lambda x: Decimal(faker.random_int(min=1, max=100)) / 10)
order = factory.Sequence(int)
checked = False
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
created_by = factory.SubFactory(
UserFactory, space=factory.SelfAttribute('..space'))
created_at = factory.LazyAttribute(lambda x: faker.past_date())
completed_at = None
delay_until = None
space = factory.SubFactory(SpaceFactory)
@classmethod
def _create(cls, target_class, *args, **kwargs): # override create to prevent auto_add_now from changing the created_at date
# override create to prevent auto_add_now from changing the created_at date
def _create(cls, target_class, *args, **kwargs):
created_at = kwargs.pop('created_at', None)
obj = super(ShoppingListEntryFactory, cls)._create(target_class, *args, **kwargs)
obj = super(ShoppingListEntryFactory, cls)._create(
target_class, *args, **kwargs)
if created_at is not None:
obj.created_at = created_at
obj.save()
@ -298,7 +324,8 @@ class ShoppingListEntryFactory(factory.django.DjangoModelFactory):
@register
class StepFactory(factory.django.DjangoModelFactory):
name = factory.LazyAttribute(lambda x: faker.sentence(nb_words=5))
instruction = factory.LazyAttribute(lambda x: ''.join(faker.paragraphs(nb=5)))
instruction = factory.LazyAttribute(
lambda x: ''.join(faker.paragraphs(nb=5)))
# TODO add optional recipe food, make dependent on recipe, make number of recipes a Params
ingredients__count = 10 # default number of ingredients to add
ingredients__header = 0
@ -330,14 +357,16 @@ class StepFactory(factory.django.DjangoModelFactory):
for i in range(num_ing):
if num_food_recipe > 0:
has_recipe = True
num_food_recipe = num_food_recipe-1
num_food_recipe = num_food_recipe - 1
else:
has_recipe = False
self.ingredients.add(IngredientFactory(space=self.space, food__has_recipe=has_recipe))
self.ingredients.add(IngredientFactory(
space=self.space, food__has_recipe=has_recipe))
num_header = kwargs.get('header', 0)
if num_header > 0:
for i in range(num_header):
self.ingredients.add(IngredientFactory(food=None, unit=None, amount=0, is_header=True, space=self.space))
self.ingredients.add(IngredientFactory(
food=None, unit=None, amount=0, is_header=True, space=self.space))
elif extracted:
for ing in extracted:
self.ingredients.add(ing)
@ -351,20 +380,27 @@ 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)) # TODO generate list of expected servings text that can be iterated through
# TODO generate list of expected servings text that can be iterated through
servings_text = factory.LazyAttribute(lambda x: faker.sentence(nb_words=1))
keywords__count = 5 # default number of keywords to generate
steps__count = 1 # default number of steps to create
steps__recipe_count = 0 # default number of step recipes to create
steps__food_recipe_count = {} # by default, don't create food recipes, to override {'steps__food_recipe_count': {'step': 0, 'count': 1}}
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))
# by default, don't create food recipes, to override {'steps__food_recipe_count': {'step': 0, 'count': 1}}
steps__food_recipe_count = {}
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
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
created_at = factory.LazyAttribute(lambda x: faker.date_between_dates(date_start=date(2000, 1, 1), date_end=date(2020, 12, 31)))
created_by = factory.SubFactory(
UserFactory, space=factory.SelfAttribute('..space'))
created_at = factory.LazyAttribute(lambda x: faker.date_between_dates(
date_start=date(2000, 1, 1), date_end=date(2020, 12, 31)))
space = factory.SubFactory(SpaceFactory)
@classmethod
def _create(cls, target_class, *args, **kwargs): # override create to prevent auto_add_now from changing the created_at date
# override create to prevent auto_add_now from changing the created_at date
def _create(cls, target_class, *args, **kwargs):
created_at = kwargs.pop('created_at', None)
# updated_at = kwargs.pop('updated_at', None)
obj = super(RecipeFactory, cls)._create(target_class, *args, **kwargs)
@ -401,11 +437,13 @@ class RecipeFactory(factory.django.DjangoModelFactory):
ing_recipe_count = 0
if food_recipe_count.get('step', None) == i:
ing_recipe_count = food_recipe_count.get('count', 0)
self.steps.add(StepFactory(space=self.space, ingredients__food_recipe_count=ing_recipe_count, ingredients__header=num_ing_headers))
num_ing_headers+-1
self.steps.add(StepFactory(
space=self.space, ingredients__food_recipe_count=ing_recipe_count, ingredients__header=num_ing_headers))
num_ing_headers + - 1
if num_recipe_steps > 0:
for j in range(num_recipe_steps):
self.steps.add(StepFactory(space=self.space, step_recipe__has_recipe=True, ingredients__count=0))
self.steps.add(StepFactory(
space=self.space, step_recipe__has_recipe=True, ingredients__count=0))
if extracted and (num_steps + num_recipe_steps == 0):
for step in extracted:
self.steps.add(step)
@ -428,15 +466,18 @@ class RecipeFactory(factory.django.DjangoModelFactory):
@register
class CookLogFactory(factory.django.DjangoModelFactory):
"""CookLog factory."""
recipe = factory.SubFactory(RecipeFactory, space=factory.SelfAttribute('..space'))
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
recipe = factory.SubFactory(
RecipeFactory, space=factory.SelfAttribute('..space'))
created_by = factory.SubFactory(
UserFactory, space=factory.SelfAttribute('..space'))
created_at = factory.LazyAttribute(lambda x: faker.date_this_decade())
rating = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=5))
servings = factory.LazyAttribute(lambda x: faker.random_int(min=1, max=32))
space = factory.SubFactory(SpaceFactory)
@classmethod
def _create(cls, target_class, *args, **kwargs): # override create to prevent auto_add_now from changing the created_at date
# override create to prevent auto_add_now from changing the created_at date
def _create(cls, target_class, *args, **kwargs):
created_at = kwargs.pop('created_at', None)
obj = super(CookLogFactory, cls)._create(target_class, *args, **kwargs)
if created_at is not None:
@ -451,13 +492,17 @@ class CookLogFactory(factory.django.DjangoModelFactory):
@register
class ViewLogFactory(factory.django.DjangoModelFactory):
"""ViewLog factory."""
recipe = factory.SubFactory(RecipeFactory, space=factory.SelfAttribute('..space'))
created_by = factory.SubFactory(UserFactory, space=factory.SelfAttribute('..space'))
created_at = factory.LazyAttribute(lambda x: faker.past_datetime(start_date='-365d'))
recipe = factory.SubFactory(
RecipeFactory, space=factory.SelfAttribute('..space'))
created_by = factory.SubFactory(
UserFactory, space=factory.SelfAttribute('..space'))
created_at = factory.LazyAttribute(
lambda x: faker.past_datetime(start_date='-365d'))
space = factory.SubFactory(SpaceFactory)
@classmethod
def _create(cls, target_class, *args, **kwargs): # override create to prevent auto_add_now from changing the created_at date
# override create to prevent auto_add_now from changing the created_at date
def _create(cls, target_class, *args, **kwargs):
created_at = kwargs.pop('created_at', None)
obj = super(ViewLogFactory, cls)._create(target_class, *args, **kwargs)
if created_at is not None:

View File

@ -259,33 +259,35 @@ def test_fuzzy_lookup(found_recipe, recipes, param_type, user1, space_1):
# commenting this out for general use - it is really slow
# it should be run on occasion to ensure everything still works
# @pytest.mark.skipif(sqlite and True, reason="requires PostgreSQL")
# @pytest.mark.parametrize("user1", itertools.product(
# [
# ('fuzzy_search', True), ('fuzzy_search', False),
# ('fulltext', True), ('fulltext', False),
# ('icontains', True), ('icontains', False),
# ('istartswith', True), ('istartswith', False),
# ],
# [('unaccent', True), ('unaccent', False)]
# ), indirect=['user1'])
# @pytest.mark.parametrize("found_recipe", [
# ({'name': True}),
# ({'description': True}),
# ({'instruction': True}),
# ({'keyword': True}),
# ({'food': True}),
# ], indirect=['found_recipe'])
# def test_search_string(found_recipe, recipes, user1, space_1):
# with scope(space=space_1):
# param1 = f"query={user1[3]}"
# param2 = f"query={user1[4]}"
# r = json.loads(user1[0].get(reverse(LIST_URL) + f'?{param1}').content)
# assert len([x['id'] for x in r['results'] if x['id'] in [found_recipe[0].id, found_recipe[1].id]]) == user1[1]
# r = json.loads(user1[0].get(reverse(LIST_URL) + f'?{param2}').content)
# assert len([x['id'] for x in r['results'] if x['id'] in [found_recipe[0].id, found_recipe[1].id]]) == user1[2]
@pytest.mark.skipif(sqlite and True, reason="requires PostgreSQL")
@pytest.mark.parametrize("user1", itertools.product(
[
('fuzzy_search', True), ('fuzzy_search', False),
('fulltext', True), ('fulltext', False),
('icontains', True), ('icontains', False),
('istartswith', True), ('istartswith', False),
],
[('unaccent', True), ('unaccent', False)]
), indirect=['user1'])
@pytest.mark.parametrize("found_recipe", [
({'name': True}),
({'description': True}),
({'instruction': True}),
({'keyword': True}),
({'food': True}),
], indirect=['found_recipe'])
def test_search_string(found_recipe, recipes, user1, space_1):
with scope(space=space_1):
param1 = f"query={user1[3]}"
param2 = f"query={user1[4]}"
r = json.loads(user1[0].get(reverse(LIST_URL) + f'?{param1}').content)
assert len([x['id'] for x in r['results'] if x['id'] in [found_recipe[0].id, found_recipe[1].id]]) == user1[1]
r = json.loads(user1[0].get(reverse(LIST_URL) + f'?{param2}').content)
assert len([x['id'] for x in r['results'] if x['id'] in [found_recipe[0].id, found_recipe[1].id]]) == user1[2]
@pytest.mark.parametrize("found_recipe, param_type, result", [
@ -322,33 +324,33 @@ def test_search_date(found_recipe, recipes, param_type, result, u1_s1, u2_s1, sp
# TODO this is somehow screwed, probably the search itself, dont want to fix it for now
# @pytest.mark.parametrize("found_recipe, param_type", [
# ({'rating': True}, 'rating'),
# ({'timescooked': True}, 'timescooked'),
# ], indirect=['found_recipe'])
# def test_search_count(found_recipe, recipes, param_type, u1_s1, u2_s1, space_1):
# param1 = f'?{param_type}=3'
# param2 = f'?{param_type}=-3'
# param3 = f'?{param_type}=0'
#
# r = json.loads(u1_s1.get(reverse(LIST_URL) + param1).content)
# assert r['count'] == 1
# assert found_recipe[0].id in [x['id'] for x in r['results']]
#
# r = json.loads(u1_s1.get(reverse(LIST_URL) + param2).content)
# assert r['count'] == 1
# assert found_recipe[1].id in [x['id'] for x in r['results']]
#
# # test search for not rated/cooked
# r = json.loads(u1_s1.get(reverse(LIST_URL) + param3).content)
# assert r['count'] == 11
# assert (found_recipe[0].id or found_recipe[1].id) not in [x['id'] for x in r['results']]
#
# # test matched returns for lte and gte searches
# r = json.loads(u2_s1.get(reverse(LIST_URL) + param1).content)
# assert r['count'] == 1
# assert found_recipe[2].id in [x['id'] for x in r['results']]
#
# r = json.loads(u2_s1.get(reverse(LIST_URL) + param2).content)
# assert r['count'] == 1
# assert found_recipe[2].id in [x['id'] for x in r['results']]
@pytest.mark.parametrize("found_recipe, param_type", [
({'rating': True}, 'rating'),
({'timescooked': True}, 'timescooked'),
], indirect=['found_recipe'])
def test_search_count(found_recipe, recipes, param_type, u1_s1, u2_s1, space_1):
param1 = f'?{param_type}=3'
param2 = f'?{param_type}=-3'
param3 = f'?{param_type}=0'
r = json.loads(u1_s1.get(reverse(LIST_URL) + param1).content)
assert r['count'] == 1
assert found_recipe[0].id in [x['id'] for x in r['results']]
r = json.loads(u1_s1.get(reverse(LIST_URL) + param2).content)
assert r['count'] == 1
assert found_recipe[1].id in [x['id'] for x in r['results']]
# test search for not rated/cooked
r = json.loads(u1_s1.get(reverse(LIST_URL) + param3).content)
assert r['count'] == 11
assert (found_recipe[0].id or found_recipe[1].id) not in [x['id'] for x in r['results']]
# test matched returns for lte and gte searches
r = json.loads(u2_s1.get(reverse(LIST_URL) + param1).content)
assert r['count'] == 1
assert found_recipe[2].id in [x['id'] for x in r['results']]
r = json.loads(u2_s1.get(reverse(LIST_URL) + param2).content)
assert r['count'] == 1
assert found_recipe[2].id in [x['id'] for x in r['results']]

View File

@ -30,11 +30,11 @@ Jinja2==3.1.2
django-webpack-loader==1.8.1
git+https://github.com/BITSOLVER/django-js-reverse@071e304fd600107bc64bbde6f2491f1fe049ec82
django-allauth==0.52.0
recipe-scrapers==14.35.0
recipe-scrapers==14.36.1
django-scopes==1.2.0.post1
pytest==7.2.2
pytest==7.3.1
pytest-django==4.5.2
django-treebeard==4.5.1
django-treebeard==4.7
django-cors-headers==3.13.0
django-storages==1.13.2
boto3==1.26.41
@ -42,7 +42,7 @@ django-prometheus==2.2.0
django-hCaptcha==0.2.0
python-ldap==3.4.3
django-auth-ldap==4.2.0
pytest-factoryboy==2.5.0
pytest-factoryboy==2.5.1
pyppeteer==1.0.2
validators==0.20.0
pytube==12.1.0
pytube==12.1.0

View File

@ -12,18 +12,17 @@
<i class="far fa-check-circle text-primary" v-if="!ingredient.checked"></i>
</td>
<td class="text-nowrap" @click="done">
<span v-if="ingredient.amount !== 0 && !ingredient.no_amount"
v-html="calculateAmount(ingredient.amount)"></span>
<span v-if="ingredient.amount !== 0 && !ingredient.no_amount" v-html="calculateAmount(ingredient.amount)"></span>
</td>
<td @click="done">
<template v-if="ingredient.unit !== null && !ingredient.no_amount">
<template >
<template>
<template v-if="ingredient.unit.plural_name === '' || ingredient.unit.plural_name === null">
<span>{{ ingredient.unit.name }}</span>
</template>
<template v-else>
<span v-if="ingredient.always_use_plural_unit">{{ ingredient.unit.plural_name}}</span>
<span v-else-if="(ingredient.amount * this.ingredient_factor) > 1">{{ ingredient.unit.plural_name }}</span>
<span v-if="ingredient.always_use_plural_unit">{{ ingredient.unit.plural_name }}</span>
<span v-else-if="ingredient.amount * this.ingredient_factor > 1">{{ ingredient.unit.plural_name }}</span>
<span v-else>{{ ingredient.unit.name }}</span>
</template>
</template>
@ -31,11 +30,10 @@
</td>
<td @click="done">
<template v-if="ingredient.food !== null">
<a :href="resolveDjangoUrl('view_recipe', ingredient.food.recipe.id)"
v-if="ingredient.food.recipe !== null" target="_blank"
rel="noopener noreferrer">{{ ingredient.food.name }}</a>
<a :href="resolveDjangoUrl('view_recipe', ingredient.food.recipe.id)" v-if="ingredient.food.recipe !== null" target="_blank" rel="noopener noreferrer">{{
ingredient.food.name
}}</a>
<template v-if="ingredient.food.recipe === null">
<template>
<template v-if="ingredient.food.plural_name === '' || ingredient.food.plural_name === null">
<span>{{ ingredient.food.name }}</span>
@ -43,7 +41,7 @@
<template v-else>
<span v-if="ingredient.always_use_plural_food">{{ ingredient.food.plural_name }}</span>
<span v-else-if="ingredient.no_amount">{{ ingredient.food.name }}</span>
<span v-else-if="(ingredient.amount * this.ingredient_factor) > 1">{{ ingredient.food.plural_name }}</span>
<span v-else-if="ingredient.amount * this.ingredient_factor > 1">{{ ingredient.food.plural_name }}</span>
<span v-else>{{ ingredient.food.name }}</span>
</template>
</template>
@ -56,10 +54,7 @@
<i class="far fa-comment"></i>
</span>
<div class="d-none d-print-block"><i class="far fa-comment-alt d-print-none"></i> {{
ingredient.note
}}
</div>
<div class="d-none d-print-block"><i class="far fa-comment-alt d-print-none"></i> {{ ingredient.note }}</div>
</div>
</td>
</template>
@ -67,19 +62,19 @@
</template>
<script>
import {calculateAmount, ResolveUrlMixin} from "@/utils/utils"
import { calculateAmount, ResolveUrlMixin } from "@/utils/utils"
import Vue from "vue"
import VueSanitize from "vue-sanitize";
import VueSanitize from "vue-sanitize"
Vue.use(VueSanitize);
Vue.use(VueSanitize)
export default {
name: "IngredientComponent",
props: {
ingredient: Object,
ingredient_factor: {type: Number, default: 1},
detailed: {type: Boolean, default: true},
ingredient_factor: { type: Number, default: 1 },
detailed: { type: Boolean, default: true },
},
mixins: [ResolveUrlMixin],
data() {
@ -88,9 +83,7 @@ export default {
}
},
watch: {},
mounted() {
},
mounted() {},
methods: {
calculateAmount: function (x) {
return this.$sanitize(calculateAmount(x, this.ingredient_factor))
@ -107,8 +100,8 @@ export default {
/* increase size of hover/touchable space without changing spacing */
.touchable {
padding-right: 2em;
padding-left: 2em;
margin-right: -2em;
padding-left: 3em;
margin-right: -3em;
margin-left: -2em;
}
</style>