From 4d6d84bf5b9dd12c62f3f18c1900ef2e9973817e Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Tue, 16 Mar 2021 23:46:54 +0100 Subject: [PATCH] fixed some tests + added user pref tests --- cookbook/serializer.py | 20 ++- cookbook/tests/api/test_api_userpreference.py | 149 ------------------ .../tests/pytest/api/test_api_meal_type.py | 6 +- .../tests/pytest/api/test_api_recipe_book.py | 1 + .../pytest/api/test_api_userpreference.py | 118 ++++++++++++++ cookbook/views/api.py | 11 +- 6 files changed, 138 insertions(+), 167 deletions(-) delete mode 100644 cookbook/tests/api/test_api_userpreference.py create mode 100644 cookbook/tests/pytest/api/test_api_userpreference.py diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 065c5c857..1b8bcc384 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -4,7 +4,8 @@ from django.contrib.auth.models import User from drf_writable_nested import (UniqueFieldsMixin, WritableNestedModelSerializer) from rest_framework import serializers -from rest_framework.exceptions import ValidationError, NotAuthenticated, NotFound +from rest_framework.exceptions import ValidationError, NotAuthenticated, NotFound, ParseError +from rest_framework.fields import ModelField from rest_framework.serializers import BaseSerializer, Serializer from cookbook.models import (Comment, CookLog, Food, Ingredient, Keyword, @@ -70,6 +71,12 @@ class UserNameSerializer(WritableNestedModelSerializer): class UserPreferenceSerializer(serializers.ModelSerializer): + + def create(self, validated_data): + if validated_data['user'] != self.context['request'].user: + raise NotFound() + return super().create(validated_data) + class Meta: model = UserPreference fields = ( @@ -77,7 +84,6 @@ class UserPreferenceSerializer(serializers.ModelSerializer): 'search_style', 'show_recent', 'plan_share', 'ingredient_decimals', 'comments' ) - read_only_fields = ['user'] class StorageSerializer(SpacedModelSerializer): @@ -295,16 +301,16 @@ class RecipeBookSerializer(SpacedModelSerializer): class Meta: model = RecipeBook fields = ('id', 'name', 'description', 'icon', 'shared', 'created_by') + read_only_fields = ('created_by',) class RecipeBookEntrySerializer(serializers.ModelSerializer): - def validate(self, data): - book = data['book'] - if book.get_owner() == self.context['request'].user: - return data - else: + def create(self, validated_data): + book = validated_data['book'] + if not book.get_owner() == self.context['request'].user: raise NotFound(detail=None, code=None) + return super().create(validated_data) class Meta: model = RecipeBookEntry diff --git a/cookbook/tests/api/test_api_userpreference.py b/cookbook/tests/api/test_api_userpreference.py deleted file mode 100644 index 7e8d051aa..000000000 --- a/cookbook/tests/api/test_api_userpreference.py +++ /dev/null @@ -1,149 +0,0 @@ -import json - -from cookbook.models import UserPreference -from cookbook.tests.views.test_views import TestViews -from django.contrib import auth -from django.urls import reverse - - -class TestApiUserPreference(TestViews): - - def setUp(self): - super(TestApiUserPreference, self).setUp() - - def test_preference_create(self): - r = self.user_client_1.post(reverse('api:userpreference-list')) - self.assertEqual(r.status_code, 201) - response = json.loads(r.content) - self.assertEqual( - response['user'], auth.get_user(self.user_client_1).id - ) - self.assertEqual( - response['theme'], - UserPreference._meta.get_field('theme').get_default() - ) - - def test_preference_list(self): - UserPreference.objects.create(user=auth.get_user(self.user_client_1)) - UserPreference.objects.create(user=auth.get_user(self.guest_client_1)) - - # users can only see own preference in list - r = self.user_client_1.get(reverse('api:userpreference-list')) - self.assertEqual(r.status_code, 200) - response = json.loads(r.content) - self.assertEqual(len(response), 1) - self.assertEqual( - response[0]['user'], auth.get_user(self.user_client_1).id - ) - - # superusers can see all user prefs in list - r = self.superuser_client.get(reverse('api:userpreference-list')) - self.assertEqual(r.status_code, 200) - response = json.loads(r.content) - self.assertEqual(len(response), 2) - - def test_preference_retrieve(self): - UserPreference.objects.create(user=auth.get_user(self.user_client_1)) - UserPreference.objects.create(user=auth.get_user(self.guest_client_1)) - - self.batch_requests( - [ - (self.guest_client_1, 404), - (self.user_client_1, 200), - (self.user_client_2, 404), - (self.anonymous_client, 403), - (self.admin_client_1, 404), - (self.superuser_client, 200) - ], - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_1).id} - ) - ) - - def test_preference_update(self): - UserPreference.objects.create(user=auth.get_user(self.user_client_1)) - UserPreference.objects.create(user=auth.get_user(self.guest_client_1)) - - # can update users preference - r = self.user_client_1.put( - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_1).id} - ), - {'theme': UserPreference.DARKLY}, - content_type='application/json' - ) - response = json.loads(r.content) - self.assertEqual(r.status_code, 200) - self.assertEqual(response['theme'], UserPreference.DARKLY) - - # cant set another users non existent pref - r = self.user_client_1.put( - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_2).id} - ), - {'theme': UserPreference.DARKLY}, - content_type='application/json' - ) - self.assertEqual(r.status_code, 404) - - # cant set another users existent pref - r = self.user_client_2.put( - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_1).id} - ), - {'theme': UserPreference.FLATLY}, - content_type='application/json' - ) - self.assertEqual(r.status_code, 404) - - # can set pref as superuser - r = self.superuser_client.put( - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_1).id} - ), - {'theme': UserPreference.FLATLY}, - content_type='application/json' - ) - self.assertEqual(r.status_code, 200) - - def test_preference_delete(self): - UserPreference.objects.create(user=auth.get_user(self.user_client_1)) - - # can delete own preference - r = self.user_client_1.delete( - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_1).id} - ) - ) - self.assertEqual(r.status_code, 204) - self.assertEqual(UserPreference.objects.count(), 0) - - UserPreference.objects.create(user=auth.get_user(self.user_client_1 - ) - ) - - # cant delete other preference - r = self.user_client_2.delete( - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_1).id} - ) - ) - self.assertEqual(r.status_code, 404) - self.assertEqual(UserPreference.objects.count(), 1) - - # superuser can delete everything - r = self.superuser_client.delete( - reverse( - 'api:userpreference-detail', - args={auth.get_user(self.user_client_1).id} - ) - ) - self.assertEqual(r.status_code, 204) - self.assertEqual(UserPreference.objects.count(), 0) diff --git a/cookbook/tests/pytest/api/test_api_meal_type.py b/cookbook/tests/pytest/api/test_api_meal_type.py index 61fae730b..17e0a7ea3 100644 --- a/cookbook/tests/pytest/api/test_api_meal_type.py +++ b/cookbook/tests/pytest/api/test_api_meal_type.py @@ -45,10 +45,10 @@ def test_list_space(obj_1, obj_2, u1_s1, u1_s2, space_2): @pytest.mark.parametrize("arg", [ ['a_u', 403], - ['g1_s1', 403], + ['g1_s1', 404], ['u1_s1', 200], - ['a1_s1', 200], - ['g1_s2', 403], + ['a1_s1', 404], + ['g1_s2', 404], ['u1_s2', 404], ['a1_s2', 404], ]) diff --git a/cookbook/tests/pytest/api/test_api_recipe_book.py b/cookbook/tests/pytest/api/test_api_recipe_book.py index cbf93fe87..3c5f4726a 100644 --- a/cookbook/tests/pytest/api/test_api_recipe_book.py +++ b/cookbook/tests/pytest/api/test_api_recipe_book.py @@ -99,6 +99,7 @@ def test_add(arg, request, u1_s2): content_type='application/json' ) response = json.loads(r.content) + print(r.content) assert r.status_code == arg[1] if r.status_code == 201: assert response['name'] == 'test' diff --git a/cookbook/tests/pytest/api/test_api_userpreference.py b/cookbook/tests/pytest/api/test_api_userpreference.py new file mode 100644 index 000000000..3f819e93d --- /dev/null +++ b/cookbook/tests/pytest/api/test_api_userpreference.py @@ -0,0 +1,118 @@ +import json + +from cookbook.models import UserPreference +from cookbook.tests.views.test_views import TestViews +from django.contrib import auth +from django.urls import reverse + +import json + +import pytest +from django.contrib import auth +from django.urls import reverse +from django_scopes import scopes_disabled + +from cookbook.models import RecipeBook, RecipeBookEntry + +LIST_URL = 'api:userpreference-list' +DETAIL_URL = 'api:userpreference-detail' + + +def test_add(u1_s1, u2_s1): + r = u1_s1.post(reverse(LIST_URL)) + assert r.status_code == 400 + + with scopes_disabled(): + UserPreference.objects.filter(user=auth.get_user(u1_s1)).delete() + + r = u2_s1.post(reverse(LIST_URL), {'user': auth.get_user(u1_s1).id}, content_type='application/json') + assert r.status_code == 404 + + r = u1_s1.post(reverse(LIST_URL), {'user': auth.get_user(u1_s1).id}, content_type='application/json') + assert r.status_code == 200 + + +def test_preference_list(u1_s1, u2_s1, u1_s2): + # users can only see own preference in list + r = u1_s1.get(reverse(LIST_URL)) + assert r.status_code == 200 + response = json.loads(r.content) + assert len(response) == 1 + assert response[0]['user'] == auth.get_user(u1_s1).id + + +@pytest.mark.parametrize("arg", [ + ['a_u', 403], + ['g1_s1', 404], + ['u1_s1', 200], + ['a1_s1', 404], +]) +def test_preference_retrieve(arg, request, u1_s1): + c = request.getfixturevalue(arg[0]) + + r = c.get( + reverse(DETAIL_URL, args={auth.get_user(u1_s1).id}), + ) + assert r.status_code == arg[1] + + +def test_preference_update(u1_s1, u2_s1): + # can update users preference + r = u1_s1.put( + reverse( + DETAIL_URL, + args={auth.get_user(u1_s1).id} + ), + {'user': auth.get_user(u1_s1).id, 'theme': UserPreference.DARKLY}, + content_type='application/json' + ) + response = json.loads(r.content) + assert r.status_code == 200 + assert response['theme'] == UserPreference.DARKLY + + # cant set another users non existent pref + r = u1_s1.put( + reverse( + DETAIL_URL, + args={auth.get_user(u2_s1).id} + ), + {'user': auth.get_user(u1_s1).id, 'theme': UserPreference.DARKLY}, + content_type='application/json' + ) + assert r.status_code == 404 + + # cant set another users existent pref + with scopes_disabled(): + UserPreference.objects.filter(user=auth.get_user(u2_s1)).delete() + + r = u1_s1.put( + reverse( + DETAIL_URL, + args={auth.get_user(u2_s1).id} + ), + {'user': auth.get_user(u1_s1).id, 'theme': UserPreference.FLATLY}, + content_type='application/json' + ) + assert r.status_code == 404 + with scopes_disabled(): + assert not UserPreference.objects.filter(user=auth.get_user(u2_s1)).exists() + + +def test_preference_delete(u1_s1, u2_s1): + # cant delete other preference + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={auth.get_user(u2_s1).id} + ) + ) + assert r.status_code == 404 + + # can delete own preference + r = u1_s1.delete( + reverse( + DETAIL_URL, + args={auth.get_user(u1_s1).id} + ) + ) + assert r.status_code == 204 diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 678fb6728..d95ae482e 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -16,8 +16,8 @@ from django.http import FileResponse, HttpResponse, JsonResponse from django.shortcuts import redirect from django.utils.translation import gettext as _ from icalendar import Calendar, Event -from rest_framework import decorators, viewsets -from rest_framework.exceptions import APIException, PermissionDenied +from rest_framework import decorators, viewsets, status +from rest_framework.exceptions import APIException, PermissionDenied, NotFound, MethodNotAllowed from rest_framework.parsers import MultiPartParser from rest_framework.response import Response from rest_framework.viewsets import ViewSetMixin @@ -97,7 +97,7 @@ class UserNameViewSet(viewsets.ReadOnlyModelViewSet): if filter_list is not None: queryset = queryset.filter(pk__in=json.loads(filter_list)) except ValueError: - raise APIException(_('Parameter filter_list incorrectly formatted')) + raise APIException('Parameter filter_list incorrectly formatted') return queryset @@ -107,11 +107,6 @@ class UserPreferenceViewSet(viewsets.ModelViewSet): serializer_class = UserPreferenceSerializer permission_classes = [CustomIsOwner, ] - def perform_create(self, serializer): - if UserPreference.objects.filter(user=self.request.user).exists(): - raise APIException(_('Preference for given user already exists')) - serializer.save(user=self.request.user) - def get_queryset(self): return self.queryset.filter(user=self.request.user)