test shoppingFood API
This commit is contained in:
parent
1364f75f21
commit
ee4ab41c1c
@ -104,18 +104,18 @@ def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None
|
||||
x_ing = Ingredient.objects.filter(step__recipe=x, food__on_hand=False, space=space)
|
||||
else:
|
||||
x_ing = Ingredient.objects.filter(step__recipe=x, space=space)
|
||||
for i in [x for x in x_ing if not x.food.ignore_shopping]:
|
||||
ShoppingListEntry.objects.create(
|
||||
list_recipe=list_recipe,
|
||||
food=i.food,
|
||||
unit=i.unit,
|
||||
ingredient=i,
|
||||
amount=i.amount * Decimal(servings_factor),
|
||||
created_by=created_by,
|
||||
space=space,
|
||||
)
|
||||
# dont' add food to the shopping list that are actually recipes that will be added as ingredients
|
||||
ingredients = ingredients.exclude(food__recipe=x)
|
||||
for i in [x for x in x_ing if not x.food.ignore_shopping]:
|
||||
ShoppingListEntry.objects.create(
|
||||
list_recipe=list_recipe,
|
||||
food=i.food,
|
||||
unit=i.unit,
|
||||
ingredient=i,
|
||||
amount=i.amount * Decimal(servings_factor),
|
||||
created_by=created_by,
|
||||
space=space,
|
||||
)
|
||||
# dont' add food to the shopping list that are actually recipes that will be added as ingredients
|
||||
ingredients = ingredients.exclude(food__recipe=x)
|
||||
|
||||
add_ingredients = list(ingredients.values_list('id', flat=True)) + related_step_ing
|
||||
if not append:
|
||||
|
92
cookbook/tests/api/test_api_food_shopping.py
Normal file
92
cookbook/tests/api/test_api_food_shopping.py
Normal file
@ -0,0 +1,92 @@
|
||||
# test create
|
||||
# test create units
|
||||
# test amounts
|
||||
# test create wrong space
|
||||
# test sharing
|
||||
# test delete
|
||||
# test delete checked (nothing should happen)
|
||||
# test delete not shared (nothing happens)
|
||||
# test delete shared
|
||||
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from django.contrib import auth
|
||||
from django.urls import reverse
|
||||
from django_scopes import scope, scopes_disabled
|
||||
|
||||
from cookbook.models import Food, ShoppingListEntry
|
||||
from cookbook.tests.factories import FoodFactory
|
||||
|
||||
SHOPPING_LIST_URL = 'api:shoppinglistentry-list'
|
||||
SHOPPING_FOOD_URL = 'api:food-shopping'
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def food(request, space_1, u1_s1):
|
||||
return FoodFactory(space=space_1)
|
||||
|
||||
|
||||
def test_shopping_forbidden_methods(food, u1_s1):
|
||||
r = u1_s1.post(
|
||||
reverse(SHOPPING_FOOD_URL, args={food.id}))
|
||||
assert r.status_code == 405
|
||||
|
||||
r = u1_s1.delete(
|
||||
reverse(SHOPPING_FOOD_URL, args={food.id}))
|
||||
assert r.status_code == 405
|
||||
|
||||
r = u1_s1.get(
|
||||
reverse(SHOPPING_FOOD_URL, args={food.id}))
|
||||
assert r.status_code == 405
|
||||
|
||||
|
||||
@pytest.mark.parametrize("arg", [
|
||||
['a_u', 403],
|
||||
['g1_s1', 403],
|
||||
['u1_s1', 204],
|
||||
['u1_s2', 404],
|
||||
['a1_s1', 204],
|
||||
])
|
||||
def test_shopping_food_create(request, arg, food):
|
||||
c = request.getfixturevalue(arg[0])
|
||||
r = c.put(reverse(SHOPPING_FOOD_URL, args={food.id}))
|
||||
assert r.status_code == arg[1]
|
||||
if r.status_code == 204:
|
||||
assert len(json.loads(c.get(reverse(SHOPPING_LIST_URL)).content)) == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize("arg", [
|
||||
['a_u', 403],
|
||||
['g1_s1', 403],
|
||||
['u1_s1', 204],
|
||||
['u1_s2', 404],
|
||||
['a1_s1', 204],
|
||||
])
|
||||
def test_shopping_food_delete(request, arg, food):
|
||||
c = request.getfixturevalue(arg[0])
|
||||
r = c.put(
|
||||
reverse(SHOPPING_FOOD_URL, args={food.id}),
|
||||
{'_delete': "true"},
|
||||
content_type='application/json'
|
||||
)
|
||||
assert r.status_code == arg[1]
|
||||
if r.status_code == 204:
|
||||
assert len(json.loads(c.get(reverse(SHOPPING_LIST_URL)).content)) == 0
|
||||
|
||||
|
||||
def test_shopping_food_share(u1_s1, u2_s1, food, space_1):
|
||||
with scope(space=space_1):
|
||||
food2 = FoodFactory(space=space_1)
|
||||
r = u1_s1.put(reverse(SHOPPING_FOOD_URL, args={food.id}))
|
||||
r = u2_s1.put(reverse(SHOPPING_FOOD_URL, args={food.id}))
|
||||
assert len(json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 1
|
||||
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 1
|
||||
|
||||
with scopes_disabled():
|
||||
user = auth.get_user(u1_s1)
|
||||
user2 = auth.get_user(u2_s1)
|
||||
user.userpreference.shopping_share.add(user2)
|
||||
user.userpreference.save()
|
||||
assert len(json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 1
|
||||
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 2
|
@ -10,7 +10,7 @@ from django.utils import timezone
|
||||
from django_scopes import scopes_disabled
|
||||
from pytest_factoryboy import LazyFixture, register
|
||||
|
||||
from cookbook.models import Food, Ingredient, ShoppingListEntry
|
||||
from cookbook.models import Food, Ingredient, ShoppingListEntry, Step
|
||||
from cookbook.tests.factories import MealPlanFactory, RecipeFactory, StepFactory, UserFactory
|
||||
|
||||
SHOPPING_LIST_URL = 'api:shoppinglistentry-list'
|
||||
@ -176,8 +176,9 @@ def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u
|
||||
|
||||
@pytest.mark.parametrize("user2, sle_count", [
|
||||
({'mealplan_autoadd_shopping': False}, (0, 17)),
|
||||
({'mealplan_autoinclude_related': False}, (7, 7)),
|
||||
({'mealplan_autoinclude_related': False}, (8, 8)),
|
||||
({'mealplan_autoexclude_onhand': False}, (19, 19)),
|
||||
({'mealplan_autoexclude_onhand': False, 'mealplan_autoinclude_related': False}, (9, 9)),
|
||||
], indirect=['user2'])
|
||||
@pytest.mark.parametrize("use_mealplan", [(False), (True), ])
|
||||
@pytest.mark.parametrize("recipe", [({'steps__recipe_count': 1})], indirect=['recipe'])
|
||||
@ -186,13 +187,14 @@ def test_shopping_recipe_userpreference(recipe, sle_count, use_mealplan, user2):
|
||||
user = auth.get_user(user2)
|
||||
# setup recipe with 10 ingredients, 1 step recipe with 10 ingredients, 2 food onhand(from recipe and step_recipe), 1 food ignore shopping
|
||||
ingredients = Ingredient.objects.filter(step__recipe=recipe)
|
||||
food = Food.objects.get(id=ingredients[0].food.id)
|
||||
food.on_hand = True
|
||||
food.save()
|
||||
food = Step.objects.filter(type=Step.RECIPE).first().ingredients.first()
|
||||
food.on_hand = True
|
||||
food.save()
|
||||
food = Food.objects.get(id=ingredients[2].food.id)
|
||||
food.on_hand = True
|
||||
food.save()
|
||||
food = recipe.steps.filter(type=Step.RECIPE).first().step_recipe.steps.first().ingredients.first().food
|
||||
food = Food.objects.get(id=food.id)
|
||||
food.on_hand = True
|
||||
food.save()
|
||||
food = Food.objects.get(id=ingredients[4].food.id)
|
||||
food.ignore_shopping = True
|
||||
food.save()
|
||||
|
||||
|
@ -413,7 +413,10 @@ class FoodViewSet(viewsets.ModelViewSet, TreeMixin):
|
||||
pagination_class = DefaultPagination
|
||||
|
||||
@decorators.action(detail=True, methods=['PUT'], serializer_class=FoodShoppingUpdateSerializer,)
|
||||
# TODO DRF only allows one action in a decorator action without overriding get_operation_id_base() this should be PUT and DELETE probably
|
||||
def shopping(self, request, pk):
|
||||
if self.request.space.demo:
|
||||
raise PermissionDenied(detail='Not available in demo', code=None)
|
||||
obj = self.get_object()
|
||||
shared_users = list(self.request.user.get_shopping_share())
|
||||
shared_users.append(request.user)
|
||||
@ -652,12 +655,16 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
||||
return Response(serializer.data)
|
||||
return Response(serializer.errors, 400)
|
||||
|
||||
# TODO: refactor API to use post/put/delete or leave as put and change VUE to use list_recipe after creating
|
||||
# DRF only allows one action in a decorator action without overriding get_operation_id_base()
|
||||
@decorators.action(
|
||||
detail=True,
|
||||
methods=['PUT'],
|
||||
serializer_class=RecipeShoppingUpdateSerializer,
|
||||
)
|
||||
def shopping(self, request, pk):
|
||||
if self.request.space.demo:
|
||||
raise PermissionDenied(detail='Not available in demo', code=None)
|
||||
obj = self.get_object()
|
||||
ingredients = request.data.get('ingredients', None)
|
||||
servings = request.data.get('servings', None)
|
||||
|
@ -254,13 +254,13 @@ def latest_shopping_list(request):
|
||||
|
||||
|
||||
@group_required('user')
|
||||
def shopping_list(request, pk=None):
|
||||
def shopping_list(request, pk=None): # TODO deprecate
|
||||
html_list = request.GET.getlist('r')
|
||||
|
||||
recipes = []
|
||||
for r in html_list:
|
||||
r = r.replace('[', '').replace(']', '')
|
||||
if re.match(r'^([0-9])+,([0-9])+[.]*([0-9])*$', r):
|
||||
if re.match(r'^([0-9])+,([0-9])+[.]*([0-9])*$', r): # vulnerable to DoS
|
||||
rid, multiplier = r.split(',')
|
||||
if recipe := Recipe.objects.filter(pk=int(rid), space=request.space).first():
|
||||
recipes.append({'recipe': recipe.id, 'multiplier': multiplier})
|
||||
|
Loading…
Reference in New Issue
Block a user