Commit 5d861cbfb8e4b0316de8ccec0c804809ed7090f3

Authored by Rohan Rangray
1 parent 61c43267c4
Exists in master

Wrote tests for FlashcardViewSet.edit

Showing 4 changed files with 77 additions and 20 deletions Side-by-side Diff

flashcards/models.py View file @ 5d861cb
1 1 from datetime import datetime
2 2  
3 3 from django.contrib.auth.models import AbstractUser, UserManager
4   -from django.core.exceptions import PermissionDenied
  4 +from django.core.exceptions import PermissionDenied, SuspiciousOperation
  5 +from django.db import IntegrityError
5 6 from django.db.models import *
6 7 from django.utils.timezone import now
7 8 from simple_email_confirmation import SimpleEmailConfirmationUserMixin
8 9  
... ... @@ -109,11 +110,12 @@
109 110 section = ForeignKey('Section', help_text='The section with which the card is associated')
110 111 pushed = DateTimeField(auto_now_add=True, help_text="When the card was first pushed")
111 112 material_date = DateTimeField(default=now, help_text="The date with which the card is associated")
112   - previous = ForeignKey('Flashcard', null=True, blank=True,
  113 + previous = ForeignKey('Flashcard', null=True, blank=True, default=None,
113 114 help_text="The previous version of this card, if one exists")
114 115 author = ForeignKey(User)
115 116 is_hidden = BooleanField(default=False)
116   - hide_reason = CharField(blank=True, max_length=255, help_text="Reason for hiding this card")
  117 + hide_reason = CharField(blank=True, null=True, max_length=255,
  118 + default=None, help_text="Reason for hiding this card")
117 119 mask = MaskField(max_length=255, null=True, blank=True, help_text="The mask on the card")
118 120  
119 121 class Meta:
... ... @@ -131,6 +133,16 @@
131 133 if not result.exists(): return self.is_hidden
132 134 return result[0].is_hidden()
133 135  
  136 + def add_to_deck(self, user):
  137 + if not user.is_in_section(self.section):
  138 + raise PermissionDenied("You don't have the permission to add this card")
  139 + try:
  140 + user_flashcard = UserFlashcard.objects.create(user=user, flashcard=self, mask=self.mask)
  141 + except IntegrityError:
  142 + raise SuspiciousOperation("The flashcard is already in the user's deck")
  143 + user_flashcard.save()
  144 + return user_flashcard
  145 +
134 146 def edit(self, user, new_flashcard):
135 147 """
136 148 Creates a new flashcard if a new flashcard should be created when the given user edits this flashcard.
137 149  
138 150  
... ... @@ -155,10 +167,15 @@
155 167 content_changed |= True
156 168 self.text = new_flashcard['text']
157 169 if create_new and content_changed:
  170 + mask = self.mask
  171 + pk = self.pk
158 172 self.pk = None
159 173 if 'mask' in new_flashcard:
160   - self.mask = new_flashcard['mask']
  174 + mask = new_flashcard['mask']
  175 + self.mask = mask
  176 + self.previous_id = pk
161 177 self.save()
  178 + return create_new and content_changed
162 179  
163 180 @classmethod
164 181 def cards_visible_to(cls, user):
flashcards/serializers.py View file @ 5d861cb
... ... @@ -119,7 +119,7 @@
119 119 is_hidden = BooleanField(read_only=True)
120 120 hide_reason = CharField(read_only=True)
121 121 material_date = DateTimeField(default=now)
122   - mask = MaskFieldSerializer()
  122 + mask = MaskFieldSerializer(allow_null=True)
123 123  
124 124 def validate_material_date(self, value):
125 125 utc = pytz.UTC
... ... @@ -135,7 +135,7 @@
135 135 def validate_previous(self, value):
136 136 if value is None:
137 137 return value
138   - if Flashcard.objects.filter(pk=value).count() > 0:
  138 + if Flashcard.objects.filter(pk=value.pk).count() > 0:
139 139 return value
140 140 raise serializers.ValidationError("Invalid previous Flashcard object")
141 141  
... ... @@ -155,6 +155,8 @@
155 155 return value
156 156  
157 157 def validate_mask(self, value):
  158 + if value is None:
  159 + return None
158 160 if len(self.initial_data['text']) < value.max_offset():
159 161 raise serializers.ValidationError("Mask out of bounds")
160 162 return value
flashcards/tests/test_api.py View file @ 5d861cb
... ... @@ -4,6 +4,9 @@
4 4 from rest_framework.test import APITestCase
5 5 from re import search
6 6 from django.utils.timezone import now
  7 +from flashcards.validators import FlashcardMask
  8 +from flashcards.serializers import FlashcardSerializer
  9 +from pytz import UTC as utc
7 10  
8 11  
9 12 class LoginTests(APITestCase):
10 13  
11 14  
... ... @@ -181,17 +184,46 @@
181 184 fixtures = ['testusers', 'testsections']
182 185  
183 186 def setUp(self):
184   - section = Section.objects.get(pk=1)
185   - user = User.objects.get(email='none@none.com')
186   -
187   - self.flashcard = Flashcard(text="jason", section=section, material_date=now(), author=user)
  187 + self.section = Section.objects.get(pk=1)
  188 + self.section.save()
  189 + self.user = User.objects.get(email='none@none.com')
  190 + self.user.sections.add(self.section)
  191 + self.user.save()
  192 + self.flashcard = Flashcard(text="jason",
  193 + section=self.section,
  194 + material_date=now(),
  195 + author=self.user)
188 196 self.flashcard.save()
  197 + self.flashcard.add_to_deck(self.user)
189 198  
190 199 def test_edit_flashcard(self):
191 200 self.client.login(email='none@none.com', password='1234')
192   - user = User.objects.get(email='none@none.com')
193   - user.sections.add(Section.objects.get(pk=1))
194   - user.save()
  201 + user = self.user
  202 + flashcard = self.flashcard
  203 + url = "/api/flashcards/{}/".format(flashcard.pk)
  204 + data = {'text': 'new wow for the flashcard',
  205 + 'mask': '[[0,4]]'}
  206 + self.assertNotEqual(flashcard.text, data['text'])
  207 + response = self.client.patch(url, data, format='json')
  208 + self.assertEqual(response.status_code, HTTP_200_OK)
  209 + self.assertEqual(response.data['text'], data['text'])
  210 + data = {'material_date': datetime(2015, 4, 12, 2, 2, 2),
  211 + 'mask': '[[1, 3]]'}
  212 + user2 = User.objects.create(email='wow@wow.wow', password='wow')
  213 + user2.sections.add(self.section)
  214 + user2.save()
  215 + UserFlashcard.objects.create(user=user2, flashcard=flashcard).save()
  216 + response = self.client.patch(url, data, format='json')
  217 + serializer = FlashcardSerializer(data=response.data)
  218 + serializer.is_valid(raise_exception=True)
  219 + self.assertEqual(response.status_code, HTTP_200_OK)
  220 + # self.assertEqual(serializer.validated_data['material_date'], utc.localize(data['material_date']))
  221 + self.assertEqual(serializer.validated_data['mask'], FlashcardMask([[1, 3]]))
  222 + data = {'mask': '[[3,6]]'}
  223 + response = self.client.patch(url, data, format='json')
  224 + user_flashcard = UserFlashcard.objects.get(user=user, flashcard=flashcard)
  225 + self.assertEqual(response.status_code, HTTP_200_OK)
  226 + self.assertEqual(user_flashcard.mask, FlashcardMask([[3, 6]]))
195 227  
196 228 def test_create_flashcard(self):
197 229 self.client.login(email='none@none.com', password='1234')
... ... @@ -291,7 +323,10 @@
291 323 self.assertEqual(response.status_code, HTTP_200_OK)
292 324  
293 325 def test_section_feed(self):
294   - response = self.client.get('/api/sections/1/feed/')
  326 + Flashcard.objects.create(author=self.user, material_date=datetime.now(),
  327 + text='wow', section=self.section,
  328 + mask=None).save()
  329 + response = self.client.get('/api/sections/{}/feed/'.format(self.section.pk))
295 330 self.assertEqual(response.status_code, HTTP_200_OK)
296 331 self.assertEqual(response.data[0]['id'], 1)
297 332  
flashcards/views.py View file @ 5d861cb
... ... @@ -13,7 +13,7 @@
13 13 from django.core.mail import send_mail
14 14 from django.contrib.auth import authenticate
15 15 from django.contrib.auth.tokens import default_token_generator
16   -from rest_framework.status import HTTP_204_NO_CONTENT, HTTP_201_CREATED
  16 +from rest_framework.status import HTTP_204_NO_CONTENT, HTTP_201_CREATED, HTTP_200_OK
17 17 from rest_framework.response import Response
18 18 from rest_framework.exceptions import AuthenticationFailed, NotAuthenticated, ValidationError, PermissionDenied
19 19 from simple_email_confirmation import EmailAddress
20 20  
21 21  
... ... @@ -378,14 +378,17 @@
378 378 data.is_valid(raise_exception=True)
379 379 new_flashcard = data.validated_data
380 380  
381   - flashcard.edit(user, new_flashcard)
382   - user_card, created = UserFlashcard.objects.get_or_create(user=user, flashcard=flashcard)
383   - user_card.mask = flashcard.mask
  381 + new_card = flashcard.edit(user, new_flashcard)
  382 + if new_card:
  383 + user_card = flashcard.add_to_deck(user)
  384 + else:
  385 + user_card, created = UserFlashcard.objects.get_or_create(user=user, flashcard=flashcard)
  386 + if created and ('mask' not in new_flashcard):
  387 + user_card.save()
384 388  
385 389 if 'mask' in new_flashcard:
386 390 user_card.mask = new_flashcard['mask']
387   - if 'mask' in new_flashcard or created:
388 391 user_card.save()
389 392  
390   - return Response(status=HTTP_204_NO_CONTENT)
  393 + return Response(FlashcardSerializer(flashcard).data, status=HTTP_200_OK)