""" Tests for the ingredients API. """ from decimal import Decimal from django.contrib.auth import get_user_model from django.urls import reverse from django.test import TestCase from rest_framework import status from rest_framework.test import APIClient from core.models import ( Ingredient, Recipe, ) from recipe.serializers import IngredientSerializer INGREDIENTS_URL = reverse('recipe:ingredient-list') def detail_url(ingredient_id): """Create and return an ingredient detail URL.""" return reverse('recipe:ingredient-detail', args=[ingredient_id]) def create_user(email='user@example.com', password='testpass123'): """Create and return user.""" return get_user_model().objects.create_user(email=email, password=password) class PublicIngredientsApiTests(TestCase): """Test unanthenticated API requests.""" def setUp(self): self.client = APIClient() def test_auth_required(self): """Test auth is required for retrieving ingredients.""" res = self.client.get(INGREDIENTS_URL) self.assertEqual(res.status_code, status.HTTP_401_UNAUTHORIZED) class PrivateIngredientsApiTests(TestCase): """Test authenticated API requests.""" def setUp(self): self.user = create_user() self.client = APIClient() self.client.force_authenticate(self.user) def test_retrieve_ingredients(self): """Test retrieving a list of ingredients.""" Ingredient.objects.create(user=self.user, name='Harina') Ingredient.objects.create(user=self.user, name='Panela') res = self.client.get(INGREDIENTS_URL) ingredients = Ingredient.objects.all().order_by('-name') serializer = IngredientSerializer(ingredients, many=True) self.assertEqual(res.status_code, status.HTTP_200_OK) self.assertEqual(res.data, serializer.data) def test_ingredients_limited_to_user(self): """Test list of ingredients is limited to authenticated user.""" user2 = create_user(email='user2@example.com') Ingredient.objects.create(user=user2, name='Sal') ingredient = Ingredient.objects.create(user=self.user, name='Pimienta') res = self.client.get(INGREDIENTS_URL) self.assertEqual(res.status_code, status.HTTP_200_OK) self.assertEqual(len(res.data), 1) self.assertEqual(res.data[0]['name'], ingredient.name) self.assertEqual(res.data[0]['id'], ingredient.id) def test_update_ingredient(self): """Test updating an ingredient.""" ingredient = Ingredient.objects.create( user=self.user, name='Coriandro' ) payload = {'name': 'Cilantro'} url = detail_url(ingredient.id) res = self.client.patch(url, payload) self.assertEqual(res.status_code, status.HTTP_200_OK) ingredient.refresh_from_db() self.assertEqual(ingredient.name, payload['name']) def test_delete_ingredient(self): """Test deleting an ingredient.""" ingredient = Ingredient.objects.create(user=self.user, name='Lechuga') url = detail_url(ingredient.id) res = self.client.delete(url) self.assertEqual(res.status_code, status.HTTP_204_NO_CONTENT) ingredients = Ingredient.objects.filter(user=self.user) self.assertFalse(ingredients.exists()) def test_filter_ingredients_assigned_to_recipes(self): """Test listing ingredients by those assigned to recipes.""" in1 = Ingredient.objects.create(user=self.user, name='Manzana') in2 = Ingredient.objects.create(user=self.user, name='Pavo') recipe = Recipe.objects.create( title='Pure de Manzana', time_minutes=5, price=Decimal('4.5'), user=self.user, ) recipe.ingredients.add(in1) res = self.client.get(INGREDIENTS_URL, {'assigned_only': 1}) s1 = IngredientSerializer(in1) s2 = IngredientSerializer(in2) self.assertIn(s1.data, res.data) self.assertNotIn(s2.data, res.data) def test_filtered_ingredients_unique(self): """Test filtered ingredients returns a unique list.""" ing = Ingredient.objects.create(user=self.user, name='Huevo') Ingredient.objects.create(user=self.user, name='Lentejas') recipe1 = Recipe.objects.create( title='Huevos a la copa', time_minutes=4, price=Decimal('1.0'), user=self.user, ) recipe2 = Recipe.objects.create( title='Huevos a cocidos', time_minutes=5, price=Decimal('1.0'), user=self.user, ) recipe1.ingredients.add(ing) recipe2.ingredients.add(ing) res = self.client.get(INGREDIENTS_URL, {'assigned_only': 1}) self.assertEqual(len(res.data), 1)