From 17768114904009e2b6776400c739d2e3e6aad62b Mon Sep 17 00:00:00 2001
From: Rohan Rangray <rrangray@ucsd.edu>
Date: Wed, 20 May 2015 01:23:33 -0700
Subject: [PATCH] Fixed the Study-related views. Wrote tests for them.

---
 flashcards/fields.py            |  4 +--
 flashcards/serializers.py       | 12 ++++----
 flashcards/tests/test_models.py | 67 +++++++++++++++++++++++++++++++++++++++--
 flashcards/validators.py        |  2 +-
 flashcards/views.py             |  2 +-
 5 files changed, 74 insertions(+), 13 deletions(-)

diff --git a/flashcards/fields.py b/flashcards/fields.py
index c3b124e..6685491 100644
--- a/flashcards/fields.py
+++ b/flashcards/fields.py
@@ -40,7 +40,7 @@ class MaskField(models.Field):
     def to_python(self, value):
         if value is None:
             return value
-        return sorted(list(FlashcardMask(value)))
+        return FlashcardMask(value)
 
     def get_prep_value(self, value):
         if value is None:
@@ -65,7 +65,7 @@ class MaskField(models.Field):
     @classmethod
     def _varchar_parse_mask(cls, value):
         if not value:
-          return FlashcardMask([])
+            return FlashcardMask([])
 
         mask = [tuple(map(int, i.split('-'))) for i in value.split(',')]
         return FlashcardMask(mask)
diff --git a/flashcards/serializers.py b/flashcards/serializers.py
index 0293904..0057cce 100644
--- a/flashcards/serializers.py
+++ b/flashcards/serializers.py
@@ -6,7 +6,7 @@ import pytz
 from flashcards.models import Section, LecturePeriod, User, Flashcard, UserFlashcard, UserFlashcardQuiz
 from flashcards.validators import FlashcardMask, OverlapIntervalException
 from rest_framework import serializers
-from rest_framework.fields import EmailField, BooleanField, CharField, IntegerField, DateTimeField
+from rest_framework.fields import EmailField, BooleanField, CharField, IntegerField, DateTimeField, empty
 from rest_framework.serializers import ModelSerializer, Serializer, PrimaryKeyRelatedField, ListField
 from rest_framework.validators import UniqueValidator
 from flashy.settings import QUARTER_END, QUARTER_START
@@ -168,7 +168,8 @@ class FlashcardUpdateSerializer(serializers.Serializer):
 
 
 class QuizRequestSerializer(serializers.Serializer):
-    sections = PrimaryKeyRelatedField(queryset=Section.objects.all(),required=False, many=True)
+    # sections = PrimaryKeyRelatedField(queryset=Section.objects.all(),required=False, many=True)
+    sections = ListField(child=IntegerField(min_value=1), required=False)
     material_date_begin = DateTimeField(default=QUARTER_START)
     material_date_end = DateTimeField(default=QUARTER_END)
 
@@ -207,7 +208,6 @@ class QuizRequestSerializer(serializers.Serializer):
         raise serializers.ValidationError("Invalid end date for the flashcard range")
 
     def validate_sections(self, value):
-        print "VALUE", type(value), value
         if value is None:
             return self.user.sections
         section_filter = Section.objects.filter(pk__in=value)
@@ -230,7 +230,7 @@ class QuizResponseSerializer(ModelSerializer):
     text = CharField(max_length=255)
     mask = ListField(child=IntegerField())
 
-    def __init__(self, instance=None, mask=[], data=None, **kwargs):
+    def __init__(self, instance=None, mask=[], data=empty, **kwargs):
         super(QuizResponseSerializer, self).__init__(instance=instance, data=data, **kwargs)
         self.mask = self._validate_mask(mask)
 
@@ -247,7 +247,7 @@ class QuizResponseSerializer(ModelSerializer):
             raise serializers.ValidationError("The selected mask has to be a list")
         if value is None or len(value) == 0:
             return []
-        if len(value) == 2 and (0 <= value[0] and len(self.initial_data['text']) < value[1]):
+        if len(value) == 2 and (0 <= value[0] and value[1] <= len(self.instance.user_flashcard.flashcard.text)):
             return value
         raise serializers.ValidationError("Invalid mask for the flashcard")
 
@@ -261,7 +261,7 @@ class QuizAnswerRequestSerializer(ModelSerializer):
 
     def __init__(self, instance, data, **kwargs):
         assert isinstance(instance, UserFlashcardQuiz)
-        super(QuizAnswerRequestSerializer, self).__init__(instance, data, kwargs)
+        super(QuizAnswerRequestSerializer, self).__init__(instance, data, **kwargs)
 
     def validate_response(self, response):
         if response is None:
diff --git a/flashcards/tests/test_models.py b/flashcards/tests/test_models.py
index 287077a..22c3700 100644
--- a/flashcards/tests/test_models.py
+++ b/flashcards/tests/test_models.py
@@ -1,8 +1,10 @@
 from datetime import datetime
 
 from django.test import TestCase
-from flashcards.models import User, Section, Flashcard, UserFlashcard
+from flashcards.models import User, Section, Flashcard, UserFlashcard, UserFlashcardQuiz
 from flashcards.validators import FlashcardMask, OverlapIntervalException
+from flashcards.serializers import QuizRequestSerializer, QuizResponseSerializer, QuizAnswerRequestSerializer
+from flashy.settings import QUARTER_START, QUARTER_END
 
 
 class RegistrationTests(TestCase):
@@ -98,7 +100,6 @@ class FlashcardMaskTest(TestCase):
             self.assertEqual(oie.message, "Invalid interval offsets in the mask")
 
 
-
 class FlashcardTests(TestCase):
     def setUp(self):
         section = Section.objects.create(department='dept',
@@ -113,7 +114,7 @@ class FlashcardTests(TestCase):
                                              author=user,
                                              material_date=datetime.now(),
                                              previous=None,
-                                             mask={(24,34), (0, 4)})
+                                             mask={(24, 34), (0, 4)})
         user.save()
         section.save()
         flashcard.save()
@@ -148,3 +149,63 @@ class FlashcardTests(TestCase):
             self.fail()
         except OverlapIntervalException:
             self.assertTrue(True)
+
+
+class UserFlashcardQuizTests(TestCase):
+    def setUp(self):
+        self.section = Section.objects.create(department='dept',
+                                              course_num='101a',
+                                              course_title='how 2 test',
+                                              instructor='George Lucas',
+                                              quarter='SP15')
+        self.user = User.objects.create_user(email="none@none.com", password="1234")
+        self.user.sections.add(self.section)
+        self.flashcard = Flashcard.objects.create(text="This is the text of the Flashcard",
+                                                  section=self.section,
+                                                  author=self.user,
+                                                  material_date=datetime.now(),
+                                                  previous=None,
+                                                  mask=[(24, 33), (0, 4)])
+        self.user.save()
+        self.section.save()
+        self.flashcard.save()
+        self.user_flashcard = UserFlashcard.objects.create(flashcard=self.flashcard,
+                                                           user=self.user,
+                                                           mask=self.flashcard.mask,
+                                                           pulled=datetime.now())
+        self.user_flashcard.save()
+        self.user_flashcard.refresh_from_db()
+        self.flashcard.refresh_from_db()
+
+    def test_quiz_request(self):
+        data = {'sections': [1], 'material_date_begin': QUARTER_START, 'material_date_end': QUARTER_END}
+        serializer = QuizRequestSerializer(user=self.user, data=data)
+        serializer.is_valid(raise_exception=True)
+        user_flashcard_quiz = serializer.create(serializer.validated_data)
+        self.assertTrue(isinstance(user_flashcard_quiz, UserFlashcardQuiz))
+        mask = user_flashcard_quiz.user_flashcard.mask.get_random_blank()
+        self.assertIn(mask, [(24, 33), (0, 4)])
+        user_flashcard_quiz.blanked_word = user_flashcard_quiz.user_flashcard.flashcard.text[slice(*mask)]
+        self.assertIn(user_flashcard_quiz.blanked_word, ["This", "Flashcard"])
+        user_flashcard_quiz.save()
+        response = QuizResponseSerializer(instance=user_flashcard_quiz, mask=mask).data
+        self.assertEqual(response['pk'], 1)
+        self.assertEqual(response['section'], 1)
+        self.assertEqual(response['text'], user_flashcard_quiz.user_flashcard.flashcard.text)
+        self.assertEqual(response['mask'], mask)
+
+    def test_quiz_answer(self):
+        data = {'response': 'Flashcard'}
+        mask = self.user_flashcard.mask.get_random_blank()
+        word = self.flashcard.text[slice(*mask)]
+        user_flashcard_quiz = UserFlashcardQuiz(user_flashcard=self.user_flashcard, blanked_word=word)
+        user_flashcard_quiz.save()
+        serializer = QuizAnswerRequestSerializer(instance=user_flashcard_quiz, data=data)
+        serializer.is_valid()
+        serializer.update(user_flashcard_quiz, serializer.validated_data)
+        self.assertEqual(user_flashcard_quiz.response, data['response'])
+        data = {'correct': True}
+        serializer = QuizAnswerRequestSerializer(instance=user_flashcard_quiz, data=data)
+        serializer.is_valid()
+        serializer.update(user_flashcard_quiz, serializer.validated_data)
+        self.assertTrue(user_flashcard_quiz.correct)
diff --git a/flashcards/validators.py b/flashcards/validators.py
index 64ac37f..8295436 100644
--- a/flashcards/validators.py
+++ b/flashcards/validators.py
@@ -17,7 +17,7 @@ class FlashcardMask(set):
 
     def get_random_blank(self):
         if self.max_offset() > 0:
-            return sample(self, 1)
+            return sample(self, 1)[0]
         return ()
 
     def _iterable_check(self, iterable):
diff --git a/flashcards/views.py b/flashcards/views.py
index dd506e9..e0929b3 100644
--- a/flashcards/views.py
+++ b/flashcards/views.py
@@ -351,7 +351,7 @@ class UserFlashcardQuizViewSet(GenericViewSet, CreateModelMixin, UpdateModelMixi
         """
         serializer = QuizRequestSerializer(data=request.data)
         serializer.is_valid(raise_exception=True)
-        user_flashcard_quiz = serializer.create()
+        user_flashcard_quiz = serializer.create(serializer.validated_data)
         mask = sample(user_flashcard_quiz.user_flashcard.mask.get_random_blank(), 1)
         user_flashcard_quiz.blanked_word = user_flashcard_quiz.user_flashcard.flashcard.text[slice(*mask)]
         user_flashcard_quiz.save()
-- 
1.9.1