Testing for karma events #306
authorCharles Connell <charles@connells.org>
Sun, 26 Jan 2014 20:31:38 +0000 (15:31 -0500)
committerCharles Connell <charles@connells.org>
Sun, 26 Jan 2014 20:31:38 +0000 (15:31 -0500)
karmaworld/apps/document_upload/tests.py
karmaworld/apps/notes/models.py
karmaworld/apps/notes/search.py
karmaworld/apps/notes/tests.py
karmaworld/apps/users/tests.py [new file with mode: 0644]

index 88600f09e9ec32fd9901e33b9811c57aeb98af28..507718f0b200fdd0930f3c237e44d1b18dfc2170 100644 (file)
@@ -5,6 +5,7 @@ when you run "manage.py test".
 Replace this with more appropriate tests for your application.
 """
 from django.contrib.sessions.backends.db import SessionStore
+from django.http import HttpRequest
 
 from django.test import TestCase, Client
 from karmaworld.apps.courses.models import Course
@@ -16,9 +17,6 @@ from karmaworld.apps.notes.models import find_orphan_notes
 
 TEST_USERNAME = 'alice'
 
-class _FakeRequest:
-    def __init__(self, session):
-        self.session = session
 
 class ConversionTest(TestCase):
 
@@ -84,8 +82,10 @@ class ConversionTest(TestCase):
                                  user=user)
         note = Note.objects.all()[0]
         self.assertEqual(note.user, user)
-        karma_event = NoteKarmaEvent.objects.all()[0]
-        self.assertEqual(karma_event.user, user)
+        try:
+            NoteKarmaEvent.objects.get(note=note, event_type=NoteKarmaEvent.UPLOAD)
+        except ObjectDoesNotExist:
+            self.fail("Karma event not created")
 
     def testSessionUserAssociation2(self):
         """If a user logs in after convert_raw_document has finished,
@@ -100,11 +100,15 @@ class ConversionTest(TestCase):
                                  'mimetype': 'text/plain'})
         user = User(username=TEST_USERNAME)
         user.save()
-        find_orphan_notes(None, user=user, request=_FakeRequest(s))
+        request = HttpRequest()
+        request.session = s
+        find_orphan_notes(None, user=user, request=request)
         note = Note.objects.all()[0]
         self.assertEqual(note.user, user)
-        karma_event = NoteKarmaEvent.objects.all()[0]
-        self.assertEqual(karma_event.user, user)
+        try:
+            NoteKarmaEvent.objects.get(note=note, event_type=NoteKarmaEvent.UPLOAD)
+        except ObjectDoesNotExist:
+            self.fail("Karma event not created")
 
     def testSessionUserAssociation3(self):
         """If a user logs in WHILE convert_raw_document is running,
@@ -114,7 +118,9 @@ class ConversionTest(TestCase):
         s.save()
         user = User(username=TEST_USERNAME)
         user.save()
-        find_orphan_notes(None, user=user, request=_FakeRequest(s))
+        request = HttpRequest()
+        request.session = s
+        find_orphan_notes(None, user=user, request=request)
         self.doConversionForPost({'fp_file': 'https://www.filepicker.io/api/file/S2lhT3INSFCVFURR2RV7',
                                  'course': str(self.course.id),
                                  'name': 'graph3.txt',
@@ -123,5 +129,7 @@ class ConversionTest(TestCase):
                                  session=s)
         note = Note.objects.all()[0]
         self.assertEqual(note.user, user)
-        karma_event = NoteKarmaEvent.objects.all()[0]
-        self.assertEqual(karma_event.user, user)
+        try:
+            NoteKarmaEvent.objects.get(note=note, event_type=NoteKarmaEvent.UPLOAD)
+        except ObjectDoesNotExist:
+            self.fail("Karma event not created")
index 309d202e8e37432a29a3b324a89486adb6e1e4b7..eec394fc2985c08ca5c7850131439f1f1b35cbb4 100644 (file)
@@ -387,7 +387,8 @@ def note_delete_receiver(sender, **kwargs):
     index = SearchIndex()
     index.remove_note(note)
 
-    GenericKarmaEvent.create_event(note.user, note.name, GenericKarmaEvent.NOTE_DELETED)
+    if note.user:
+        GenericKarmaEvent.create_event(note.user, note.name, GenericKarmaEvent.NOTE_DELETED)
 
 
 class UserUploadMapping(models.Model):
index d578f5db9c5c95a54b99e1a0374e9de3f9428aa5..3ae352d40e9bf8950b684bf55c721b3fed999bef 100644 (file)
@@ -4,6 +4,7 @@
 
 import calendar
 import time
+import uuid
 
 import indextank.client as itc
 import karmaworld.secret.indexden as secret
@@ -51,12 +52,21 @@ class SearchIndex(object):
 
     __metaclass__ = Singleton
 
-    def __init__(self):
-        api_client = itc.ApiClient(secret.PRIVATE_URL)
-        if not api_client.get_index(secret.INDEX).exists():
-            api_client.create_index(secret.INDEX, {'public_search': False})
+    def __init__(self, testing=False):
+        if not testing:
+            self.setup()
 
-        self.index = api_client.get_index(secret.INDEX)
+    def setup(self, testing=False):
+        if testing:
+            self.index_name = uuid.uuid4().hex
+        else:
+            self.index_name = secret.INDEX
+
+        self.api_client = itc.ApiClient(secret.PRIVATE_URL)
+        if not self.api_client.get_index(self.index_name).exists():
+            self.api_client.create_index(self.index_name, {'public_search': False})
+
+        self.index = self.api_client.get_index(self.index_name)
 
         while not self.index.has_started():
             time.sleep(0.5)
@@ -67,6 +77,11 @@ class SearchIndex(object):
         # "Relevance" is a black box provided by IndexDen.
         self.index.add_function(0, 'relevance * log(doc.var[0])')
 
+    def delete_index(self):
+        """This is meant for test cases that want to clean up
+        after themselves."""
+        self.api_client.delete_index(self.index_name)
+
     @staticmethod
     def _tags_to_str(tags):
         return ' '.join([str(tag) for tag in tags.all()])
index c0daea30d36d63b848a2fe774bb038f19f1c84d8..c313c8db8ef9efe1b0282c034f2d33bdd93aadd2 100644 (file)
@@ -4,12 +4,6 @@
 """
 """
 import karmaworld.secret.indexden as secret
-import uuid
-
-# This needs to happen before other things
-# are imported to avoid putting test data
-# in our production search index
-secret.INDEX = uuid.uuid4().hex
 
 import datetime
 from django.test import TestCase
@@ -18,9 +12,13 @@ from karmaworld.apps.notes.search import SearchIndex
 from karmaworld.apps.notes.models import Note
 from karmaworld.apps.courses.models import Course
 from karmaworld.apps.courses.models import School
-import indextank.client as itc
 
-class TestNoes(TestCase):
+# Tell SearchIndex to put its entries
+# in a separate index
+secret.testing = True
+
+
+class TestNotes(TestCase):
 
     def setUp(self):
         # create base values to test db representations
@@ -50,12 +48,17 @@ class TestNoes(TestCase):
         self.note.text = "This is the plaintext version of a note. It's pretty cool. Alpaca."
         self.note.save()
 
+    @classmethod
+    def setUpClass(cls):
+        index = SearchIndex(testing=True)
+        index.setup(testing=True)
+
     @classmethod
     def tearDownClass(cls):
         """Delete the test index that was automatically
         created by notes/search.py"""
-        api = itc.ApiClient(secret.PRIVATE_URL)
-        api.delete_index(secret.INDEX)
+        index = SearchIndex()
+        index.delete_index()
 
     def test_course_fkey(self):
         self.assertEqual(self.course, self.note.course)
@@ -103,4 +106,8 @@ class TestNoes(TestCase):
         results = index.search('alpaca', self.note.course.id)
         self.assertIn(self.note.id, results.ordered_ids)
 
+        # Delete the note, see if it's removed from the index
+        self.note.delete()
+        results = index.search('alpaca')
+        self.assertNotIn(self.note.id, results.ordered_ids)
 
diff --git a/karmaworld/apps/users/tests.py b/karmaworld/apps/users/tests.py
new file mode 100644 (file)
index 0000000..d4e2b11
--- /dev/null
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+# -*- coding:utf8 -*-
+# Copyright (C) 2013  FinalsClub Foundation
+import datetime
+from django.contrib.sessions.backends.db import SessionStore
+from django.core.exceptions import ObjectDoesNotExist
+from django.http import HttpRequest
+from django.test import TestCase
+
+from django.contrib.auth.models import User
+from karmaworld.apps.courses.views import flag_course
+from karmaworld.apps.notes.models import Note
+from karmaworld.apps.courses.models import Course
+from karmaworld.apps.courses.models import School
+from karmaworld.apps.notes.search import SearchIndex
+from karmaworld.apps.notes.views import thank_note, flag_note, downloaded_note
+from karmaworld.apps.users.models import NoteKarmaEvent, GenericKarmaEvent, CourseKarmaEvent, give_email_confirm_karma
+
+
+class TestUsers(TestCase):
+
+    def setUp(self):
+        # create base values to test db representations
+        self.now = datetime.datetime.utcnow()
+
+        # create a school to satisfy course requirements
+        self.school = School()
+        self.school.name = 'Marshall College'
+        self.school.save()
+
+        # create a course to test relationships
+        self.course = Course()
+        self.course.school = self.school
+        self.course.name = u'Archaeology 101'
+        self.course.save()
+        # override Course.save() appending an ID to the slug
+        self.course.slug = u'archaeology-101'
+        self.course.save()
+
+        self.user1 = User(username='Alice')
+        self.user1.save()
+
+        self.user2 = User(username='Bob')
+        self.user2.save()
+
+        # create a note to test against
+        self.note = Note()
+        self.note.course = self.course
+        self.note.name = u"Lecture notes concerning the use of therefore ∴"
+        self.note.text = "This is the plaintext version of a note. It's pretty cool."
+        self.note.user = self.user1
+        self.note.save()
+
+        self.request1 = HttpRequest()
+        self.request1.user = self.user1
+        self.request1.method = 'POST'
+        self.request1.META = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'}
+        self.request1.session = SessionStore()
+
+        self.request2 = HttpRequest()
+        self.request2.user = self.user2
+        self.request2.method = 'POST'
+        self.request2.META = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'}
+        self.request2.session = SessionStore()
+
+    @classmethod
+    def setUpClass(cls):
+        index = SearchIndex(testing=True)
+        index.setup(testing=True)
+
+    @classmethod
+    def tearDownClass(cls):
+        """Delete the test index that was automatically
+        created by notes/search.py"""
+        index = SearchIndex()
+        index.delete_index()
+
+    def test_thank_own_note_karma(self):
+        """Make sure you don't get karma for thanking your own note"""
+        thank_note(self.request1, self.note.pk)
+        try:
+            NoteKarmaEvent.objects.get(note=self.note)
+            self.fail("You can't thank your own note")
+        except ObjectDoesNotExist:
+            pass
+
+    def test_thank_anothers_note_karma(self):
+        """Get karma for having your note thanked"""
+        thank_note(self.request2, self.note.pk)
+        try:
+            NoteKarmaEvent.objects.get(note=self.note)
+        except ObjectDoesNotExist:
+            self.fail("Karma event not created")
+
+    def test_note_deleted_karma(self):
+        """Lose karma if your note is deleted"""
+        thank_note(self.request2, self.note.pk)
+        self.note.delete()
+        try:
+            GenericKarmaEvent.objects.get(event_type=GenericKarmaEvent.NOTE_DELETED)
+        except ObjectDoesNotExist:
+            self.fail("Karma event not created")
+        try:
+            NoteKarmaEvent.objects.get(note=self.note)
+            self.fail("Karma event not deleted")
+        except ObjectDoesNotExist:
+            pass
+
+    def test_note_give_flag_karma(self):
+        """Lose karma for flagging a note"""
+        flag_note(self.request2, self.note.pk)
+        try:
+            NoteKarmaEvent.objects.get(event_type=NoteKarmaEvent.GIVE_FLAG, user=self.user2)
+        except ObjectDoesNotExist:
+            self.fail("Karma event not created")
+
+    def test_course_give_flag_karma(self):
+        """Lose karma for flagging a course"""
+        flag_course(self.request2, self.course.pk)
+        try:
+            CourseKarmaEvent.objects.get(event_type=CourseKarmaEvent.GIVE_FLAG, user=self.user2)
+        except ObjectDoesNotExist:
+            self.fail("Karma event not created")
+
+    def test_note_get_flagged_karma(self):
+        """Lose karma for having your note flagged many times"""
+        flag_note(self.request2, self.note.pk)
+        flag_note(self.request2, self.note.pk)
+        flag_note(self.request2, self.note.pk)
+        flag_note(self.request2, self.note.pk)
+        flag_note(self.request2, self.note.pk)
+        flag_note(self.request2, self.note.pk)
+        try:
+            NoteKarmaEvent.objects.get(event_type=NoteKarmaEvent.GET_FLAGGED, user=self.user1)
+        except ObjectDoesNotExist:
+            self.fail("Karma event not created")
+
+    def test_note_download_karma(self):
+        """You lose karma for downloading a note, person who uploaded it gains karma"""
+        downloaded_note(self.request2, self.note.pk)
+        try:
+            NoteKarmaEvent.objects.get(event_type=NoteKarmaEvent.DOWNLOADED_NOTE, user=self.user2)
+        except ObjectDoesNotExist:
+            self.fail("Karma event not created")
+        try:
+            NoteKarmaEvent.objects.get(event_type=NoteKarmaEvent.HAD_NOTE_DOWNLOADED, user=self.user1)
+        except ObjectDoesNotExist:
+            self.fail("Karma event not created")
+
+    def test_email_confirm_karma(self):
+        class FakeEmailAddress:
+            user = self.user1
+            email = self.user1.email
+
+        give_email_confirm_karma(None, email_address=FakeEmailAddress())
+        try:
+            GenericKarmaEvent.objects.get(event_type=GenericKarmaEvent.EMAIL_CONFIRMED, user=self.user1)
+        except ObjectDoesNotExist:
+            self.fail("Karma event not created")