summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2010-06-07 00:54:39 -0400
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2010-06-07 00:54:39 -0400
commit57033196f904477631c397fab50681f0d1aa7834 (patch)
tree59b49b40680af03ef5c0a31782c19737e404257b
parent430ce40aea1fddd086640bbd54242e6832478e49 (diff)
downloadaskbot-57033196f904477631c397fab50681f0d1aa7834.tar.gz
askbot-57033196f904477631c397fab50681f0d1aa7834.tar.bz2
askbot-57033196f904477631c397fab50681f0d1aa7834.zip
notification records are correct but response counters are exxagerated. added unit tests for response counters
-rw-r--r--forum/const/__init__.py2
-rw-r--r--forum/migrations/0013_add_response_count__to_user.py28
-rw-r--r--forum/models/answer.py3
-rw-r--r--forum/models/base.py11
-rw-r--r--forum/models/content.py1
-rw-r--r--forum/models/question.py2
-rw-r--r--forum/tests.py496
7 files changed, 526 insertions, 17 deletions
diff --git a/forum/const/__init__.py b/forum/const/__init__.py
index e3f086aa..0da9ec22 100644
--- a/forum/const/__init__.py
+++ b/forum/const/__init__.py
@@ -125,6 +125,7 @@ TYPE_ACTIVITY = (
)
+#MENTION activity is added implicitly, unfortunately
RESPONSE_ACTIVITY_TYPES_FOR_INSTANT_NOTIFICATIONS = (
TYPE_ACTIVITY_COMMENT_QUESTION,
TYPE_ACTIVITY_COMMENT_ANSWER,
@@ -136,6 +137,7 @@ RESPONSE_ACTIVITY_TYPES_FOR_INSTANT_NOTIFICATIONS = (
#the same as for instant notifications for now
+#MENTION activity is added implicitly, unfortunately
RESPONSE_ACTIVITY_TYPES_FOR_DISPLAY = (
TYPE_ACTIVITY_ANSWER,
TYPE_ACTIVITY_ASK_QUESTION,
diff --git a/forum/migrations/0013_add_response_count__to_user.py b/forum/migrations/0013_add_response_count__to_user.py
index 5cd906a7..30ca164e 100644
--- a/forum/migrations/0013_add_response_count__to_user.py
+++ b/forum/migrations/0013_add_response_count__to_user.py
@@ -7,19 +7,27 @@ from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
-
- # Adding field 'Activity.junk'
- db.add_column(
- u'auth_user',
- 'response_count',
- self.gf('django.db.models.fields.IntegerField')(default=0, ),
- keep_default=False
- )
+ """adds integer field User.response_counter
+ if the field does not yet exist
+ this case checking is necessary to support syncdb of auth models
+ a bit hacky but we have to do it as long as we keep patching auth models
+ within the forum application
+ """
+ try:
+ db.add_column(
+ u'auth_user',
+ 'response_count',
+ self.gf('django.db.models.fields.IntegerField')(default=0, ),
+ keep_default=False
+ )
+ except:
+ print 'probably already have column User.response_count'
+ pass
def backwards(self, orm):
-
- # Deleting field 'Activity.junk'
+ """remove field User.respose_count
+ """
db.delete_column(u'auth_user', 'response_count')
diff --git a/forum/models/answer.py b/forum/models/answer.py
index 48b1c464..b4e8963e 100644
--- a/forum/models/answer.py
+++ b/forum/models/answer.py
@@ -172,6 +172,9 @@ class Answer(content.Content, DeletableContent):
include_comments = True
)
)
+ for answer in self.question.answers.all():
+ receiving_users.update(answer.get_author_list())
+
receiving_users -= set(exclude_list)
return list(receiving_users)
diff --git a/forum/models/base.py b/forum/models/base.py
index 964c6142..d832b71c 100644
--- a/forum/models/base.py
+++ b/forum/models/base.py
@@ -126,11 +126,12 @@ def save_post(post, **kwargs):
#create new mentions
for u in newly_mentioned_users:
from forum.models.user import Activity
- Activity.objects.create_new_mention(
- mentioned_whom = u,
- mentioned_in = post,
- mentioned_by = last_author
- )
+ if u != last_author:
+ Activity.objects.create_new_mention(
+ mentioned_whom = u,
+ mentioned_in = post,
+ mentioned_by = last_author
+ )
#todo: this is handled in signal because models for posts
#are too spread out
diff --git a/forum/models/content.py b/forum/models/content.py
index 441f7133..eb2b423e 100644
--- a/forum/models/content.py
+++ b/forum/models/content.py
@@ -75,6 +75,7 @@ class Content(models.Model):
comment.save()
self.comment_count = self.comment_count + 1
self.save()
+ return comment
def get_instant_notification_subscribers(
self,
diff --git a/forum/models/question.py b/forum/models/question.py
index 88f01e4f..c6c16578 100644
--- a/forum/models/question.py
+++ b/forum/models/question.py
@@ -437,7 +437,7 @@ class Question(content.Content, DeletableContent):
def add_revision(self,author=None, text=None, comment=None, revised_at=None):
if None in (author, text, comment):
- raise Exception('author, text and revised_at are required arguments')
+ raise Exception('author, text and comment are required arguments')
rev_no = self.revisions.all().count() + 1
if comment in (None, ''):
if rev_no == 1:
diff --git a/forum/tests.py b/forum/tests.py
index 2096386b..c2e1765f 100644
--- a/forum/tests.py
+++ b/forum/tests.py
@@ -1,8 +1,502 @@
+import datetime
+import time
from django.test import TestCase
-from django.contrib.auth.models import User
from django.template import defaultfilters
from django.core.urlresolvers import reverse
+from forum.models import User, Question, Answer, Activity
+from forum.models import EmailFeedSetting
+from forum import const
+def create_user(username = None, email = None):
+ user = User.objects.create_user(username, email)
+ for feed_type in EmailFeedSetting.FEED_TYPES:
+ feed = EmailFeedSetting(
+ feed_type = feed_type[0],
+ frequency = 'n',
+ subscriber = user
+ )
+ feed.save()
+ return user
+
+def get_re_notif_after(timestamp):
+ notifications = Activity.objects.filter(
+ activity_type__in = const.RESPONSE_ACTIVITY_TYPES_FOR_DISPLAY,
+ active_at__gte = timestamp
+ )
+ return notifications
+
+class UpdateNotificationTests(TestCase):
+
+ def reset_response_counts(self):
+ self.reload_users()
+ for user in self.users:
+ user.response_count = 0
+ user.save()
+
+ def reload_users(self):
+ self.u11 = User.objects.get(id=self.u11.id)
+ self.u12 = User.objects.get(id=self.u12.id)
+ self.u13 = User.objects.get(id=self.u13.id)
+ self.u14 = User.objects.get(id=self.u14.id)
+ self.u21 = User.objects.get(id=self.u21.id)
+ self.u22 = User.objects.get(id=self.u22.id)
+ self.u23 = User.objects.get(id=self.u23.id)
+ self.u24 = User.objects.get(id=self.u24.id)
+ self.u31 = User.objects.get(id=self.u31.id)
+ self.u32 = User.objects.get(id=self.u32.id)
+ self.u33 = User.objects.get(id=self.u33.id)
+ self.u34 = User.objects.get(id=self.u34.id)
+ self.users = [
+ self.u11,
+ self.u12,
+ self.u13,
+ self.u14,
+ self.u21,
+ self.u22,
+ self.u23,
+ self.u24,
+ self.u31,
+ self.u32,
+ self.u33,
+ self.u34,
+ ]
+
+ def setUp(self):
+ #users for the question
+ self.u11 = create_user('user11', 'user11@example.com')
+ self.u12 = create_user('user12', 'user12@example.com')
+ self.u13 = create_user('user13', 'user13@example.com')
+ self.u14 = create_user('user14', 'user14@example.com')
+
+ #users for first answer
+ self.u21 = create_user('user21', 'user21@example.com')#post answer
+ self.u22 = create_user('user22', 'user22@example.com')#edit answer
+ self.u23 = create_user('user23', 'user23@example.com')
+ self.u24 = create_user('user24', 'user24@example.com')
+
+ #users for second answer
+ self.u31 = create_user('user31', 'user31@example.com')#post answer
+ self.u32 = create_user('user32', 'user32@example.com')#edit answer
+ self.u33 = create_user('user33', 'user33@example.com')
+ self.u34 = create_user('user34', 'user34@example.com')
+
+ #a hack to initialize .users list
+ self.reload_users()
+
+ #pre-populate forum with some content
+ self.question = Question.objects.create_new(
+ title = 'test question',
+ author = self.u11,
+ added_at = datetime.datetime.now(),
+ wiki = False,
+ tagnames = 'test',
+ text = 'hey listen up',
+ )
+ self.comment12 = self.question.add_comment(
+ user = self.u12,
+ comment = 'comment12'
+ )
+ self.comment13 = self.question.add_comment(
+ user = self.u13,
+ comment = 'comment13'
+ )
+ self.answer1 = Answer.objects.create_new(
+ question = self.question,
+ author = self.u21,
+ added_at = datetime.datetime.now(),
+ text = 'answer1'
+ )
+ self.comment22 = self.answer1.add_comment(
+ user = self.u22,
+ comment = 'comment22'
+ )
+ self.comment23 = self.answer1.add_comment(
+ user = self.u23,
+ comment = 'comment23'
+ )
+ self.answer2 = Answer.objects.create_new(
+ question = self.question,
+ author = self.u31,
+ added_at = datetime.datetime.now(),
+ text = 'answer2'
+ )
+ self.comment32 = self.answer2.add_comment(
+ user = self.u32,
+ comment = 'comment32'
+ )
+ self.comment33 = self.answer2.add_comment(
+ user = self.u33,
+ comment = 'comment33'
+ )
+
+ def test_self_comments(self):
+ self.reset_response_counts()
+ time.sleep(1)
+ timestamp = datetime.datetime.now()
+ self.question.add_comment(
+ user = self.u11,
+ comment = 'self-comment 1',
+ added_at = timestamp
+ )
+ notifications = get_re_notif_after(timestamp)
+ self.assertEqual(len(notifications), 1)
+ self.assertEqual(
+ set(notifications[0].receiving_users.all()),
+ set([self.u12, self.u13]),
+ )
+ self.reload_users()
+ self.assertEqual(
+ [
+ self.u11.response_count,
+ self.u12.response_count,
+ self.u13.response_count,
+ self.u14.response_count,
+ self.u21.response_count,
+ self.u22.response_count,
+ self.u23.response_count,
+ self.u24.response_count,
+ self.u31.response_count,
+ self.u32.response_count,
+ self.u33.response_count,
+ self.u34.response_count,
+ ],
+ [
+ 0, 1, 1, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ ]
+ )
+ self.reset_response_counts()
+ time.sleep(1)
+ timestamp = datetime.datetime.now()
+ self.answer1.add_comment(
+ user = self.u21,
+ comment = 'self-comment 2',
+ added_at = timestamp
+ )
+ notifications = get_re_notif_after(timestamp)
+ self.assertEqual(len(notifications), 1)
+ self.assertEqual(
+ set(notifications[0].receiving_users.all()),
+ set([self.u22, self.u23]),
+ )
+ self.reload_users()
+ self.assertEqual(
+ [
+ self.u11.response_count,
+ self.u12.response_count,
+ self.u13.response_count,
+ self.u14.response_count,
+ self.u21.response_count,
+ self.u22.response_count,
+ self.u23.response_count,
+ self.u24.response_count,
+ self.u31.response_count,
+ self.u32.response_count,
+ self.u33.response_count,
+ self.u34.response_count,
+ ],
+ [
+ 0, 0, 0, 0,
+ 0, 1, 1, 0,
+ 0, 0, 0, 0,
+ ]
+ )
+
+ def test_comments_to_post_authors(self):
+ self.reset_response_counts()
+ self.question.apply_edit(
+ edited_by = self.u14,
+ text = 'now much better',
+ comment = 'improved text'
+ )
+ time.sleep(1)
+ timestamp = datetime.datetime.now()
+ self.question.add_comment(
+ user = self.u12,
+ comment = 'self-comment 1',
+ added_at = timestamp
+ )
+ notifications = get_re_notif_after(timestamp)
+ self.assertEqual(len(notifications), 1)
+ self.assertEqual(
+ set(notifications[0].receiving_users.all()),
+ set([self.u11, self.u13, self.u14]),
+ )
+ self.reload_users()
+ self.assertEqual(
+ [
+ self.u11.response_count,
+ self.u12.response_count,
+ self.u13.response_count,
+ self.u14.response_count,
+ self.u21.response_count,
+ self.u22.response_count,
+ self.u23.response_count,
+ self.u24.response_count,
+ self.u31.response_count,
+ self.u32.response_count,
+ self.u33.response_count,
+ self.u34.response_count,
+ ],
+ [
+ 1, 0, 1, 1,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ ]
+ )
+ self.answer1.apply_edit(
+ edited_by = self.u24,
+ text = 'now much better',
+ comment = 'improved text'
+ )
+ self.reset_repsonse_counters()
+ time.sleep(1)
+ timestamp = datetime.datetime.now()
+ self.answer1.add_comment(
+ user = self.u22,
+ comment = 'self-comment 1',
+ added_at = timestamp
+ )
+ notifications = get_re_notif_after(timestamp)
+ self.assertEqual(len(notifications), 1)
+ self.assertEqual(
+ set(notifications[0].receiving_users.all()),
+ set([self.u21, self.u23, self.u24]),
+ )
+ self.reload_users()
+ self.assertEqual(
+ [
+ self.u11.response_count,
+ self.u12.response_count,
+ self.u13.response_count,
+ self.u14.response_count,
+ self.u21.response_count,
+ self.u22.response_count,
+ self.u23.response_count,
+ self.u24.response_count,
+ self.u31.response_count,
+ self.u32.response_count,
+ self.u33.response_count,
+ self.u34.response_count,
+ ],
+ [
+ 0, 0, 0, 0,
+ 1, 0, 1, 1,
+ 0, 0, 0, 0,
+ ]
+ )
+
+ def test_question_edit(self):
+ """when question is edited
+ response receivers are question authors, commenters
+ and answer authors, but not answer commenters
+ """
+ self.reset_response_counts()
+ time.sleep(1)
+ timestamp = datetime.datetime.now()
+ self.question.apply_edit(
+ edited_by = self.u14,
+ text = 'waaay better question!',
+ comment = 'improved question',
+ )
+ notifications = get_re_notif_after(timestamp)
+ self.assertEqual(len(notifications), 1)
+ self.assertEqual(
+ set(notifications[0].receiving_users.all()),
+ set([self.u11, self.u12, self.u13, self.u21, self.u31])
+ )
+ self.reload_users()
+ self.assertEqual(
+ [
+ self.u11.response_count,
+ self.u12.response_count,
+ self.u13.response_count,
+ self.u14.response_count,
+ self.u21.response_count,
+ self.u22.response_count,
+ self.u23.response_count,
+ self.u24.response_count,
+ self.u31.response_count,
+ self.u32.response_count,
+ self.u33.response_count,
+ self.u34.response_count,
+ ],
+ [
+ 1, 1, 1, 0,
+ 1, 0, 0, 0,
+ 1, 0, 0, 0,
+ ]
+ )
+ self.reset_response_counts()
+ time.sleep(1)
+ timestamp = datetime.datetime.now()
+ self.question.apply_edit(
+ edited_by = self.u31,
+ text = 'waaay even better question!',
+ comment = 'improved question',
+ )
+ notifications = get_re_notif_after(timestamp)
+ self.assertEqual(len(notifications), 1)
+ self.assertEqual(
+ set(notifications[0].receiving_users.all()),
+ set([self.u11, self.u12, self.u13, self.u14, self.u21])
+ )
+ self.reload_users()
+ self.assertEqual(
+ [
+ self.u11.response_count,
+ self.u12.response_count,
+ self.u13.response_count,
+ self.u14.response_count,
+ self.u21.response_count,
+ self.u22.response_count,
+ self.u23.response_count,
+ self.u24.response_count,
+ self.u31.response_count,
+ self.u32.response_count,
+ self.u33.response_count,
+ self.u34.response_count,
+ ],
+ [
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ ]
+ )
+
+ def test_answer_edit(self):
+ """
+ """
+ self.reset_response_counts()
+ time.sleep(1)
+ timestamp = datetime.datetime.now()
+ self.answer1.apply_edit(
+ edited_by = self.u24,
+ text = 'waaay better answer!',
+ comment = 'improved answer1',
+ )
+ notifications = get_re_notif_after(timestamp)
+ self.assertEqual(len(notifications), 1)
+ self.assertEqual(
+ set(notifications[0].receiving_users.all()),
+ set(
+ [
+ self.u11, self.u12, self.u13,
+ self.u21, self.u22, self.u23,
+ self.u31
+ ]
+ )
+ )
+ self.reload_users()
+ self.assertEqual(
+ [
+ self.u11.response_count,
+ self.u12.response_count,
+ self.u13.response_count,
+ self.u14.response_count,
+ self.u21.response_count,
+ self.u22.response_count,
+ self.u23.response_count,
+ self.u24.response_count,
+ self.u31.response_count,
+ self.u32.response_count,
+ self.u33.response_count,
+ self.u34.response_count,
+ ],
+ [
+ 1, 1, 1, 0,
+ 1, 1, 1, 0,
+ 1, 0, 0, 0,
+ ]
+ )
+
+ def test_new_answer(self):
+ self.reset_response_counts()
+ time.sleep(1)
+ timestamp = datetime.datetime.now()
+ self.answer3 = Answer.objects.create_new(
+ question = self.question,
+ author = self.u11,
+ added_at = timestamp,
+ text = 'answer3'
+ )
+ time_end = datetime.datetime.now()
+ notifications = get_re_notif_after(timestamp)
+ self.assertEqual(len(notifications), 1)
+ self.assertEqual(
+ set(notifications[0].receiving_users.all()),
+ set(
+ [
+ self.u12, self.u13,
+ self.u21, self.u31
+ ]
+ )
+ )
+ self.reload_users()
+ self.assertEqual(
+ [
+ self.u11.response_count,
+ self.u12.response_count,
+ self.u13.response_count,
+ self.u14.response_count,
+ self.u21.response_count,
+ self.u22.response_count,
+ self.u23.response_count,
+ self.u24.response_count,
+ self.u31.response_count,
+ self.u32.response_count,
+ self.u33.response_count,
+ self.u34.response_count,
+ ],
+ [
+ 0, 1, 1, 0,
+ 1, 0, 0, 0,
+ 1, 0, 0, 0,
+ ]
+ )
+ self.reset_response_counts()
+ time.sleep(1)
+ timestamp = datetime.datetime.now()
+ self.answer3 = Answer.objects.create_new(
+ question = self.question,
+ author = self.u31,
+ added_at = timestamp,
+ text = 'answer4'
+ )
+ notifications = get_re_notif_after(timestamp)
+ self.assertEqual(len(notifications), 1)
+ self.assertEqual(
+ set(notifications[0].receiving_users.all()),
+ set(
+ [
+ self.u11, self.u12, self.u13,
+ self.u21
+ ]
+ )
+ )
+ self.reload_users()
+ self.assertEqual(
+ [
+ self.u11.response_count,
+ self.u12.response_count,
+ self.u13.response_count,
+ self.u14.response_count,
+ self.u21.response_count,
+ self.u22.response_count,
+ self.u23.response_count,
+ self.u24.response_count,
+ self.u31.response_count,
+ self.u32.response_count,
+ self.u33.response_count,
+ self.u34.response_count,
+ ],
+ [
+ 1, 1, 1, 0,
+ 1, 0, 0, 0,
+ 0, 0, 0, 0,
+ ]
+ )
class AnonymousVisitorTests(TestCase):