from copy import deepcopy
from datetime import datetime, timezone # pylint: disable=E0611
try:
import mock
except ImportError:
from unittest import mock
from django.contrib.auth.models import User
from django.core import mail
from django.test import RequestFactory
from django.urls import reverse
from django.utils.timezone import make_aware
from oioioi.base.notification import NotificationHandler
from oioioi.base.tests import TestCase, check_not_accessible, fake_time
from oioioi.contests.models import Contest, ProblemInstance
from oioioi.programs.controllers import ProgrammingContestController
from oioioi.questions.forms import FilterMessageForm
from oioioi.questions.management.commands.mailnotifyd import (
candidate_messages,
mailnotify,
)
from oioioi.questions.models import Message, ReplyTemplate
from oioioi.questions.utils import unanswered_questions
from .views import visible_messages
[docs]class TestContestControllerMixin(object):
[docs] def users_to_receive_public_message_notification(self):
return self.registration_controller().filter_participants(User.objects.all())
ProgrammingContestController.mix_in(TestContestControllerMixin)
[docs]class TestQuestions(TestCase):
[docs] fixtures = [
'test_users',
'test_contest',
'test_full_package',
'test_problem_instance',
'test_messages',
'test_templates',
'test_subscriptions',
]
[docs] def test_visibility(self):
contest = Contest.objects.get()
all_messages = [
'problem-question',
'contest-question',
'public-answer',
'private-answer',
]
url = reverse('contest_messages', kwargs={'contest_id': contest.id})
def check_visibility(*should_be_visible):
response = self.client.get(url)
for m in all_messages:
if m in should_be_visible:
self.assertContains(response, m)
else:
self.assertNotContains(response, m)
self.assertTrue(self.client.login(username='test_user'))
check_visibility('public-answer', 'private-answer')
self.assertTrue(self.client.login(username='test_user2'))
check_visibility('public-answer')
self.assertTrue(self.client.login(username='test_admin'))
check_visibility('public-answer', 'private-answer')
[docs] def test_pub_date(self):
contest = Contest.objects.get()
all_messages = [
'question-visible-title',
'question-hidden1-title',
'question-hidden2-title',
'response-hidden-title',
'visible-response-to-hidden',
]
url = reverse('contest_messages', kwargs={'contest_id': contest.id})
timestamp = datetime(2013, 9, 7, 13, 40, 0, tzinfo=timezone.utc)
def check_visibility(*should_be_visible):
with fake_time(timestamp):
response = self.client.get(url)
for m in all_messages:
if m in should_be_visible:
self.assertContains(response, m)
else:
self.assertNotContains(response, m)
self.assertTrue(self.client.login(username='test_user'))
check_visibility('question-visible-title')
self.assertTrue(self.client.login(username='test_admin'))
check_visibility(
'response-hidden-title',
'question-hidden1-title',
'visible-response-to-hidden',
)
[docs] def test_user_date(self):
ta = datetime(1970, 1, 1, 12, 30, tzinfo=timezone.utc)
tb = datetime(1970, 1, 1, 13, 30, tzinfo=timezone.utc)
self.assertEqual(Message(date=ta, pub_date=None).get_user_date(), ta)
self.assertEqual(Message(date=ta, pub_date=tb).get_user_date(), tb)
[docs] def test_visible_messages(self):
contest = Contest.objects.get()
timestamp = datetime(2013, 9, 7, 13, 40, 0, tzinfo=timezone.utc)
def make_request(username):
request = RequestFactory().request()
request.timestamp = timestamp
request.contest = contest
request.user = User.objects.get(username=username)
return request
self.assertListEqual(
[5, 4, 3, 2, 1], [m.id for m in visible_messages(make_request('test_user'))]
)
self.assertListEqual(
[5, 4], [m.id for m in visible_messages(make_request('test_user2'))]
)
self.assertListEqual(
[9, 8, 7, 6, 5, 4, 10, 3, 2, 1],
[m.id for m in visible_messages(make_request('test_admin'))],
)
[docs] def test_new_labels(self):
self.assertTrue(self.client.login(username='test_user'))
contest = Contest.objects.get()
list_url = reverse('contest_messages', kwargs={'contest_id': contest.id})
timestamp = make_aware(datetime.utcfromtimestamp(1347025200))
with fake_time(timestamp):
response = self.client.get(list_url)
self.assertContains(response, '>NEW<', count=2)
public_answer = Message.objects.get(topic='public-answer')
with fake_time(timestamp):
response = self.client.get(
reverse(
'message',
kwargs={'contest_id': contest.id, 'message_id': public_answer.id},
)
)
self.assertContains(response, 'public-answer-body')
self.assertNotContains(response, 'contest-question')
self.assertNotContains(response, 'problem-question')
with fake_time(timestamp):
response = self.client.get(list_url)
self.assertContains(response, '>NEW<', count=1)
[docs] def check_unread_num(self, num):
self.assertEqual(num, len(unanswered_questions(Message.objects.all())))
[docs] def mark_read(self, message_id):
contest = Message.objects.get(id=message_id).contest
url_kwargs = {'contest_id': contest.id, 'message_id': message_id}
read_url = reverse('mark_question_read', kwargs=url_kwargs)
response = self.client.post(read_url, follow=True)
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Success!")
self.assertContains(response, "Mark unread")
self.assertContains(response, "Marked read by")
[docs] def mark_unread(self, message_id):
contest = Message.objects.get(id=message_id).contest
url_kwargs = {'contest_id': contest.id, 'message_id': message_id}
unread_url = reverse('mark_question_unread', kwargs=url_kwargs)
response = self.client.post(unread_url, follow=True)
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Success!")
self.assertContains(response, "Mark read")
self.assertNotContains(response, "Marked read by")
[docs] def test_mark_read(self):
self.assertTrue(self.client.login(username='test_admin'))
contest = Contest.objects.get()
url_kwargs = {'contest_id': contest.id, 'message_id': 1}
message_url = reverse('message', kwargs=url_kwargs)
read_url = reverse('mark_question_read', kwargs=url_kwargs)
unread_url = reverse('mark_question_unread', kwargs=url_kwargs)
# View the message
self.check_unread_num(1)
response = self.client.get(message_url)
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Mark read")
# Mark the message as read
self.mark_read(1)
self.check_unread_num(0)
# Try to mark it again
response = self.client.post(read_url, follow=True)
self.assertEqual(response.status_code, 200)
self.check_unread_num(0)
self.assertContains(response, "This question has already been marked read!")
# Unmark the message
self.mark_unread(1)
self.check_unread_num(1)
# Try to unmark it again
response = self.client.post(unread_url, follow=True)
self.assertEqual(response.status_code, 200)
self.check_unread_num(1)
self.assertContains(response, "This question has already been marked unread!")
# You should be able to mark an answered message as read
url_kwargs['message_id'] = 2
message_url = reverse('message', kwargs=url_kwargs)
response = self.client.get(message_url)
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Mark read")
self.mark_read(2)
self.mark_unread(2)
# Only questions should be markable as read
for i in (5, 6):
url_kwargs['message_id'] = i
message_url = reverse('message', kwargs=url_kwargs)
response = self.client.get(message_url)
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, "Mark read")
[docs] def test_ask_and_reply(self):
self.assertTrue(self.client.login(username='test_user2'))
contest = Contest.objects.get()
pi = ProblemInstance.objects.get()
url = reverse('add_contest_message', kwargs={'contest_id': contest.id})
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertIn('form', response.context)
form = response.context['form']
self.assertEqual(len(form.fields['category'].choices) - 1, 2)
post_data = {
'category': 'p_%d' % (pi.id,),
'topic': 'the-new-question',
'content': 'the-new-body',
}
response = self.client.post(url, post_data)
self.assertEqual(response.status_code, 302)
new_question = Message.objects.get(topic='the-new-question')
self.assertEqual(new_question.content, 'the-new-body')
self.assertEqual(new_question.kind, 'QUESTION')
self.assertIsNone(new_question.top_reference)
self.assertEqual(new_question.contest, contest)
self.assertEqual(new_question.problem_instance, pi)
self.assertEqual(new_question.author.username, 'test_user2')
self.assertTrue(self.client.login(username='test_admin'))
list_url = reverse('contest_messages', kwargs={'contest_id': contest.id})
response = self.client.get(list_url)
self.assertContains(response, 'the-new-question')
url = reverse(
'message', kwargs={'contest_id': contest.id, 'message_id': new_question.id}
)
response = self.client.get(url)
self.assertIn('form', response.context)
post_data = {
'kind': 'PUBLIC',
'topic': 're-new-question',
'content': 're-new-body',
'save_template': True,
}
response = self.client.post(url, post_data)
self.assertEqual(response.status_code, 302)
post_data = {
'kind': 'PUBLIC',
'topic': 'another-re-new-question',
'content': 'another-re-new-body',
'save_template': False,
}
response = self.client.post(url, post_data)
self.assertRaises(
ReplyTemplate.DoesNotExist,
lambda: ReplyTemplate.objects.get(content='another-re-new-body'),
)
self.assertEqual(response.status_code, 302)
new_reply = Message.objects.get(topic='re-new-question')
self.assertEqual(new_reply.content, 're-new-body')
self.assertEqual(new_reply.kind, 'PUBLIC')
self.assertEqual(new_reply.top_reference, new_question)
self.assertEqual(new_reply.contest, contest)
self.assertEqual(new_reply.problem_instance, pi)
self.assertEqual(new_reply.author.username, 'test_admin')
self.assertTrue(self.client.login(username='test_user'))
q_url = reverse(
'message', kwargs={'contest_id': contest.id, 'message_id': new_question.id}
)
check_not_accessible(self, q_url)
repl_url = reverse(
'message', kwargs={'contest_id': contest.id, 'message_id': new_reply.id}
)
response = self.client.get(repl_url)
self.assertEqual(response.status_code, 200)
self.assertContains(response, 're-new-question')
self.assertContains(response, 're-new-body')
self.assertNotContains(response, 'the-new-question')
self.assertNotContains(response, 'the-new-body')
response = self.client.get(list_url)
self.assertContains(response, repl_url)
self.assertContains(response, 're-new-question')
self.assertNotContains(response, 'the-new-question')
self.assertTrue(self.client.login(username='test_user2'))
response = self.client.get(q_url)
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'the-new-question')
self.assertContains(response, 'the-new-body')
self.assertContains(response, 're-new-body')
response = self.client.get(list_url)
self.assertContains(response, q_url)
self.assertContains(response, 're-new-question')
self.assertNotContains(response, 'the-new-question')
[docs] def test_reply_notification(self):
flags = {}
flags['user_1001_got_notification'] = False
flags['user_1002_got_notification'] = False
@classmethod
def fake_send_notification(
cls,
user,
notification_type,
notification_message,
notificaion_message_arguments,
):
if user.pk == 1002:
flags['user_1002_got_notification'] = True
if user.pk == 1001:
flags['user_1001_got_notification'] = True
send_notification_backup = NotificationHandler.send_notification
NotificationHandler.send_notification = fake_send_notification
# Test user asks a new question
self.assertTrue(self.client.login(username='test_user2'))
contest = Contest.objects.get()
pi = ProblemInstance.objects.get()
url = reverse('add_contest_message', kwargs={'contest_id': contest.id})
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
post_data = {
'category': 'p_%d' % (pi.id,),
'topic': 'the-new-question',
'content': 'the-new-body',
}
response = self.client.post(url, post_data)
self.assertEqual(response.status_code, 302)
new_question = Message.objects.get(topic='the-new-question')
# Test admin replies his question
self.assertTrue(self.client.login(username='test_admin'))
list_url = reverse('contest_messages', kwargs={'contest_id': contest.id})
response = self.client.get(list_url)
self.assertContains(response, 'the-new-question')
url = reverse(
'message', kwargs={'contest_id': contest.id, 'message_id': new_question.id}
)
response = self.client.get(url)
self.assertIn('form', response.context)
post_data = {
'kind': 'PRIVATE',
'topic': 're-new-question',
'content': 're-new-body',
'save_template': True,
}
response = self.client.post(url, post_data)
self.assertEqual(response.status_code, 302)
# Check if a notification for user was send
self.assertTrue(flags['user_1002_got_notification'])
self.assertFalse(flags['user_1001_got_notification'])
NotificationHandler.send_notification = send_notification_backup
[docs] def test_public_message_notification(self):
flags = {}
flags['user_1001_got_notification'] = False
flags['user_1002_got_notification'] = False
@classmethod
def fake_send_notification(
cls,
user,
notification_type,
notification_message,
notificaion_message_arguments,
):
if user.pk == 1002:
flags['user_1002_got_notification'] = True
if user.pk == 1001:
flags['user_1001_got_notification'] = True
send_notification_backup = NotificationHandler.send_notification
NotificationHandler.send_notification = fake_send_notification
# Test user asks a new question
self.assertTrue(self.client.login(username='test_user2'))
contest = Contest.objects.get()
pi = ProblemInstance.objects.get()
url = reverse('add_contest_message', kwargs={'contest_id': contest.id})
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
post_data = {
'category': 'p_%d' % (pi.id,),
'topic': 'the-new-question',
'content': 'the-new-body',
}
response = self.client.post(url, post_data)
self.assertEqual(response.status_code, 302)
new_question = Message.objects.get(topic='the-new-question')
# Test admin replies his question
self.assertTrue(self.client.login(username='test_admin'))
list_url = reverse('contest_messages', kwargs={'contest_id': contest.id})
response = self.client.get(list_url)
self.assertContains(response, 'the-new-question')
url = reverse(
'message', kwargs={'contest_id': contest.id, 'message_id': new_question.id}
)
response = self.client.get(url)
self.assertIn('form', response.context)
post_data = {
'kind': 'PUBLIC',
'topic': 're-new-question',
'content': 're-new-body',
'save_template': True,
}
response = self.client.post(url, post_data)
self.assertEqual(response.status_code, 302)
self.assertTrue(flags['user_1002_got_notification'])
self.assertTrue(flags['user_1001_got_notification'])
NotificationHandler.send_notification = send_notification_backup
[docs] def test_filtering(self):
self.assertTrue(self.client.login(username='test_admin'))
contest = Contest.objects.get()
url = reverse('contest_messages', kwargs={'contest_id': contest.id})
get_data = {'author': 'test_admin'}
response = self.client.get(url, get_data)
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, 'general-question')
self.assertNotContains(response, 'problem-question')
self.assertContains(response, 'public-answer')
self.assertContains(response, 'private-answer')
get_data['author'] = 'test_user'
response = self.client.get(url, get_data)
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'general-question')
self.assertContains(response, 'problem-question')
self.assertNotContains(response, 'public-answer')
self.assertNotContains(response, 'private-answer')
get_data['category'] = 'r_1'
response = self.client.get(url, get_data)
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'general-question')
self.assertNotContains(response, 'problem-question')
self.assertNotContains(response, 'public-answer')
self.assertNotContains(response, 'private-answer')
get_data['category'] = 'p_1'
response = self.client.get(url, get_data)
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, 'general-question')
self.assertContains(response, 'problem-question')
self.assertNotContains(response, 'public-answer')
self.assertNotContains(response, 'private-answer')
self.assertTrue(self.client.login(username='test_user'))
response = self.client.get(url, get_data)
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, 'general-question')
self.assertNotContains(response, 'problem-question')
self.assertNotContains(response, 'public-answer')
self.assertContains(response, 'private-answer')
[docs] def test_authors_list(self):
self.assertTrue(self.client.login(username='test_admin'))
contest = Contest.objects.get()
url = reverse('get_messages_authors', kwargs={'contest_id': contest.id})
response = self.client.get(url, {'substr': ''})
self.assertEqual(404, response.status_code)
response = self.client.get(url)
self.assertEqual(404, response.status_code)
response = self.client.get(url, {'substr': 'te'})
self.assertEqual(200, response.status_code)
response = response.json()
self.assertListEqual(
['test_admin (Test Admin)', 'test_user (Test User)'], response
)
response = self.client.get(url, {'substr': 'test admin'})
response = response.json()
self.assertListEqual(['test_admin (Test Admin)'], response)
self.assertTrue(self.client.login(username='test_user'))
check_not_accessible(self, url)
[docs] def test_change_category(self):
pi = ProblemInstance.objects.get()
r = pi.round
q = Message.objects.get(topic="problem-question")
a1, a2 = Message.objects.filter(top_reference=q)
self.client.get('/c/c/') # 'c' becomes the current contest
def change_category(msg, cat):
url = reverse('oioioiadmin:questions_message_change', args=(msg.id,))
self.assertTrue(self.client.login(username='test_admin'))
response = self.client.get(url)
self.assertIn('form', response.context)
post_data = {
'kind': msg.kind,
'category': cat,
'topic': msg.topic,
'content': msg.content,
}
response = self.client.post(url, post_data)
self.assertEqual(response.status_code, 302)
# Change a1 to round question
change_category(a1, 'r_%d' % r.id)
q = Message.objects.get(topic="problem-question")
a1, a2 = Message.objects.filter(top_reference=q)
self.assertEqual(a1.round, r)
self.assertEqual(a2.round, r)
self.assertEqual(q.round, r)
self.assertTrue(a1.problem_instance is None)
self.assertTrue(a2.problem_instance is None)
self.assertTrue(q.problem_instance is None)
# Change q to problem question
change_category(q, 'p_%d' % pi.id)
q = Message.objects.get(topic="problem-question")
a1, a2 = Message.objects.filter(top_reference=q)
self.assertEqual(a1.problem_instance, pi)
self.assertEqual(a2.problem_instance, pi)
self.assertEqual(q.problem_instance, pi)
self.assertEqual(a1.round, pi.round)
self.assertEqual(a2.round, pi.round)
self.assertEqual(q.round, pi.round)
[docs] def test_change_denied(self):
self.assertTrue(self.client.login(username='test_user'))
self.client.get('/c/c/') # 'c' becomes the current contest
msg = Message.objects.filter(author__username='test_admin')[0]
url = reverse('oioioiadmin:questions_message_change', args=(msg.id,))
check_not_accessible(self, url)
[docs] def test_reply_templates(self):
contest = Contest.objects.get()
self.assertTrue(self.client.login(username='test_admin'))
url1 = reverse('get_reply_templates', kwargs={'contest_id': contest.id})
response = self.client.get(url1)
templates = response.json()
self.assertEqual(templates[0]['name'], "N/A")
self.assertEqual(templates[0]['content'], "No answer.")
self.assertEqual(templates[3]['name'], "What contest is this?")
self.assertEqual(len(templates), 4)
url_inc = reverse(
'increment_template_usage',
kwargs={'contest_id': contest.id, 'template_id': 4},
)
for _i in range(12):
response = self.client.get(url_inc)
response = self.client.get(url1)
templates = response.json()
self.assertEqual(templates[0]['name'], "What contest is this?")
self.assertEqual(len(templates), 4)
self.assertTrue(self.client.login(username='test_user'))
check_not_accessible(self, url1)
[docs] def test_check_new_messages(self):
self.assertTrue(self.client.login(username='test_user'))
url = reverse('check_new_messages', kwargs={'contest_id': 'c', 'topic_id': 2})
resp = self.client.get(url, {'timestamp': 1347000000})
data = resp.json()['messages']
self.assertEqual(data[1][0], u'private-answer')
[docs] def test_message_type_filter(self):
contest = Contest.objects.get()
url = reverse('contest_messages', kwargs={'contest_id': contest.id})
# Admin and regular users have slightly different filter forms,
# so let's test both types of users.
for username in ['test_user', 'test_admin']:
self.assertTrue(self.client.login(username=username))
response = self.client.get(
url, {'message_type': FilterMessageForm.TYPE_ALL_MESSAGES}
)
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'private-answer')
self.assertContains(response, 'public-answer')
response = self.client.get(
url, {'message_type': FilterMessageForm.TYPE_PUBLIC_ANNOUNCEMENTS}
)
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, 'private-answer')
self.assertContains(response, 'public-answer')
[docs] def test_candidate_notifications(self):
timestamp = datetime(2000, 9, 7, 13, 40, 0, tzinfo=timezone.utc)
self.assertEqual(len(candidate_messages(timestamp)), 5)
timestamp = datetime(2015, 9, 7, 13, 40, 0, tzinfo=timezone.utc)
self.assertEqual(len(candidate_messages(timestamp)), 10)
[docs] def test_unescaped(self):
message = Message.objects.get(pk=10)
mailnotify(message)
m = mail.outbox[0]
self.assertIn(">", m.subject)
self.assertIn("& <> !! #$*&$!#", m.body)
[docs] def test_mailnotify(self):
def assertMessageId(id, body):
self.assertIn("/questions/{}/".format(id), body)
# Notify about a private message
message = Message.objects.get(pk=3)
mailnotify(message)
self.assertEqual(len(mail.outbox), 1)
m = mail.outbox[0]
self.assertIn("[OIOIOI][Test contest]", m.subject)
self.assertEqual("test_user@example.com", m.to[0])
self.assertIn("A new message has just appeared", m.body)
self.assertIn("private-answer-body", m.body)
# Private answer, the user has access to the top reference, so they
# should receive it in the e-mail
assertMessageId(message.top_reference.id, m.body)
# Do not notify about a question
question = Message.objects.get(pk=2)
mailnotify(question)
self.assertEqual(len(mail.outbox), 1)
# Do not notify again about the same question
with self.assertRaises(AssertionError):
mailnotify(message)
# Notify two users about a public message
pubmsg = Message.objects.get(pk=4)
mailnotify(pubmsg)
self.assertEqual(len(mail.outbox), 3)
m = mail.outbox[1]
mm = mail.outbox[2]
self.assertIn("[OIOIOI][Test contest]", m.subject)
self.assertEqual("test_user@example.com", m.to[0])
self.assertEqual("test_user2@example.com", mm.to[0])
self.assertIn("A new message has just appeared", m.body)
self.assertIn("public-answer-body", m.body)
self.assertIn("A new message has just appeared", mm.body)
self.assertIn("public-answer-body", mm.body)
self.assertEqual(m.subject, mm.subject)
# the author should receive the link to the top_reference
# and the original question
assertMessageId(pubmsg.top_reference.id, m.body)
self.assertIn("question-body", m.body)
# the non-author should receive the link to the answer
# and should not receive the original question
assertMessageId(pubmsg.id, mm.body)
self.assertNotIn("question-body", mm.body)
[docs] def test_unseen_mail_notifications(self):
"""Test whether the notifications are correctly *not* sent for messages
which are not visible to the user"""
mock_name = 'oioioi.questions.management.commands.mailnotifyd.visible_messages'
with mock.patch(mock_name, return_value=Message.objects.none()):
message = Message.objects.get(pk=4)
mailnotify(message)
self.assertEqual(len(mail.outbox), 0)
[docs]class TestAllMessagesView(TestCase):
[docs] fixtures = [
'test_users',
'test_contest',
'test_full_package',
'test_problem_instance',
'test_messages',
'test_second_user_messages',
]
[docs] def test_visible_messages(self):
contest = Contest.objects.get()
url = reverse('contest_all_messages', kwargs={'contest_id': contest.id})
visible_to_user = [
'general-question',
'problem-question',
'question-body',
'private-answer-body',
'public-answer-body',
'user2-public-answer-body',
]
hidden_to_user = [
'user2-answered-question',
'user2-unanswered-question',
'user2-question-body',
'user2-private-answer-body',
]
# Note: reply topics are not displayed and regular users can not see
# questions of another users, so they can see reply as a single
# message with its topic.
visible_for_non_admins = [
'user2-public-answer-topic',
]
hidden_to_all = [
'user2-private-answer-topic',
]
test_data = [
{
'username': 'test_user',
'visible': visible_to_user + visible_for_non_admins,
'hidden': hidden_to_user + hidden_to_all,
},
{
'username': 'test_admin',
'visible': visible_to_user + hidden_to_user,
'hidden': visible_for_non_admins + hidden_to_all,
},
]
for d in test_data:
self.assertTrue(self.client.login(username=d['username']))
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
for content in d['visible']:
self.assertContains(response, content)
for content in d['hidden']:
self.assertNotContains(response, content)
[docs] def test_marking_as_read(self):
contest = Contest.objects.get()
url = reverse('contest_all_messages', kwargs={'contest_id': contest.id})
self.assertTrue(self.client.login(username='test_user'))
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'NEW')
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, 'NEW')
[docs] def test_marking_as_needs_reply(self):
contest = Contest.objects.get()
url = reverse('contest_all_messages', kwargs={'contest_id': contest.id})
self.assertTrue(self.client.login(username='test_admin'))
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
unanswered = unanswered_questions(Message.objects.all())
# We need additional modules like django-webtest or beuatiful soup
# to gracefully inspect HTML instead of template context
for entry in response.context['tree_list']:
self.assertEqual(entry['needs_reply'], entry['message'] in unanswered)
[docs] def test_messages_ordering(self):
contest = Contest.objects.get()
url = reverse('contest_all_messages', kwargs={'contest_id': contest.id})
test_data = [
{
'username': 'test_user',
'sort_key': lambda x: (
x['has_new_message'],
x['needs_reply'],
x['timestamp'],
),
'visit_messages': [2, 7],
},
{
'username': 'test_admin',
'sort_key': lambda x: (
x['needs_reply'],
x['has_new_message'],
x['timestamp'],
),
'visit_messages': [2, 7],
},
]
for d in test_data:
self.assertTrue(self.client.login(username=d['username']))
for mid in d['visit_messages']:
url_visit = reverse(
'message_visit',
kwargs={'contest_id': contest.id, 'message_id': mid},
)
response = self.client.get(url_visit)
self.assertEqual(response.status_code, 201)
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
# We need additional modules like django-webtest or beuatiful soup
# to gracefully inspect HTML instead of template context
correct_tree_list = deepcopy(response.context['tree_list'])
correct_tree_list.sort(key=d['sort_key'], reverse=True)
for entry in correct_tree_list:
entry['replies'].sort(key=d['sort_key'], reverse=True)
self.assertEqual(response.context['tree_list'], correct_tree_list)
[docs] def test_filter_presence(self):
# Note: already tested in TestQuestions. Here, we are only testing
# if filter form is supported in this view.
contest = Contest.objects.get()
url = reverse('contest_all_messages', kwargs={'contest_id': contest.id})
# Admin and regular users have slightly different filter forms,
# so let's test both types of users.
for username in ['test_user', 'test_admin']:
self.assertTrue(self.client.login(username=username))
response = self.client.get(
url, {'message_type': FilterMessageForm.TYPE_ALL_MESSAGES}
)
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'private-answer')
self.assertContains(response, 'public-answer')
response = self.client.get(
url, {'message_type': FilterMessageForm.TYPE_PUBLIC_ANNOUNCEMENTS}
)
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, 'private-answer')
self.assertContains(response, 'public-answer')
[docs]class TestUserInfo(TestCase):
[docs] fixtures = [
'test_users',
'test_contest',
'test_full_package',
'test_problem_instance',
'test_messages',
'test_templates',
]
[docs] def test_user_info_page(self):
contest = Contest.objects.get()
user = User.objects.get(pk=1001)
url = reverse(
'user_info', kwargs={'contest_id': contest.id, 'user_id': user.id}
)
self.assertTrue(self.client.login(username='test_admin'))
response = self.client.get(url)
self.assertContains(response, 'User info')
self.assertContains(response, "User's messages")
self.assertContains(response, 'general-question')