123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- from datetime import timedelta
- from django.contrib.auth import get_user_model
- from django.test import TestCase
- from django.utils import timezone
- from misago.categories.models import Category
- from misago.threads import testutils
- from misago.threads.models import Poll, Post, Thread, ThreadParticipant
- UserModel = get_user_model()
- class ThreadModelTests(TestCase):
- def setUp(self):
- datetime = timezone.now()
- self.category = Category.objects.all_categories()[:1][0]
- self.thread = Thread(
- category=self.category,
- started_on=datetime,
- starter_name="Tester",
- starter_slug="tester",
- last_post_on=datetime,
- last_poster_name="Tester",
- last_poster_slug="tester",
- )
- self.thread.set_title("Test thread")
- self.thread.save()
- Post.objects.create(
- category=self.category,
- thread=self.thread,
- poster_name="Tester",
- original="Hello! I am test message!",
- parsed="<p>Hello! I am test message!</p>",
- checksum="nope",
- posted_on=datetime,
- updated_on=datetime,
- )
- self.thread.synchronize()
- self.thread.save()
- def test_synchronize(self):
- """synchronize method updates thread data to reflect its contents"""
- user = UserModel.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
- self.assertEqual(self.thread.replies, 0)
- datetime = timezone.now() + timedelta(5)
- post = Post.objects.create(
- category=self.category,
- thread=self.thread,
- poster=user,
- poster_name=user.username,
- original="Hello! I am test message!",
- parsed="<p>Hello! I am test message!</p>",
- checksum="nope",
- posted_on=datetime,
- updated_on=datetime,
- )
- # first sync call, updates last thread
- self.thread.synchronize()
- self.assertEqual(self.thread.last_post, post)
- self.assertEqual(self.thread.last_post_on, post.posted_on)
- self.assertEqual(self.thread.last_poster, user)
- self.assertEqual(self.thread.last_poster_name, user.username)
- self.assertEqual(self.thread.last_poster_slug, user.slug)
- self.assertFalse(self.thread.has_reported_posts)
- self.assertFalse(self.thread.has_unapproved_posts)
- self.assertFalse(self.thread.has_hidden_posts)
- self.assertEqual(self.thread.replies, 1)
- # add unapproved post
- unapproved_post = Post.objects.create(
- category=self.category,
- thread=self.thread,
- poster=user,
- poster_name=user.username,
- original="Hello! I am test message!",
- parsed="<p>Hello! I am test message!</p>",
- checksum="nope",
- posted_on=datetime + timedelta(5),
- updated_on=datetime + timedelta(5),
- is_unapproved=True,
- )
- self.thread.synchronize()
- self.assertEqual(self.thread.last_post, post)
- self.assertEqual(self.thread.last_post_on, post.posted_on)
- self.assertEqual(self.thread.last_poster, user)
- self.assertEqual(self.thread.last_poster_name, user.username)
- self.assertEqual(self.thread.last_poster_slug, user.slug)
- self.assertFalse(self.thread.has_reported_posts)
- self.assertTrue(self.thread.has_unapproved_posts)
- self.assertFalse(self.thread.has_hidden_posts)
- self.assertEqual(self.thread.replies, 1)
- # add hidden post
- hidden_post = Post.objects.create(
- category=self.category,
- thread=self.thread,
- poster=user,
- poster_name=user.username,
- original="Hello! I am test message!",
- parsed="<p>Hello! I am test message!</p>",
- checksum="nope",
- posted_on=datetime + timedelta(10),
- updated_on=datetime + timedelta(10),
- is_hidden=True,
- )
- self.thread.synchronize()
- self.assertEqual(self.thread.last_post, hidden_post)
- self.assertEqual(self.thread.last_post_on, hidden_post.posted_on)
- self.assertEqual(self.thread.last_poster, user)
- self.assertEqual(self.thread.last_poster_name, user.username)
- self.assertEqual(self.thread.last_poster_slug, user.slug)
- self.assertFalse(self.thread.has_reported_posts)
- self.assertTrue(self.thread.has_unapproved_posts)
- self.assertTrue(self.thread.has_hidden_posts)
- self.assertEqual(self.thread.replies, 2)
- # unhide post
- hidden_post.is_hidden = False
- hidden_post.save()
- # last post changed to unhidden one
- self.thread.synchronize()
- self.assertEqual(self.thread.last_post, hidden_post)
- self.assertEqual(self.thread.last_post_on, hidden_post.posted_on)
- self.assertEqual(self.thread.last_poster, user)
- self.assertEqual(self.thread.last_poster_name, user.username)
- self.assertEqual(self.thread.last_poster_slug, user.slug)
- self.assertFalse(self.thread.has_reported_posts)
- self.assertTrue(self.thread.has_unapproved_posts)
- self.assertFalse(self.thread.has_hidden_posts)
- self.assertEqual(self.thread.replies, 2)
- # unmoderate post
- unapproved_post.is_unapproved = False
- unapproved_post.save()
- # last post not changed, but flags and count did
- self.thread.synchronize()
- self.assertEqual(self.thread.last_post, hidden_post)
- self.assertEqual(self.thread.last_post_on, hidden_post.posted_on)
- self.assertEqual(self.thread.last_poster, user)
- self.assertEqual(self.thread.last_poster_name, user.username)
- self.assertEqual(self.thread.last_poster_slug, user.slug)
- self.assertFalse(self.thread.has_reported_posts)
- self.assertFalse(self.thread.has_unapproved_posts)
- self.assertFalse(self.thread.has_hidden_posts)
- self.assertEqual(self.thread.replies, 3)
- # add event post
- event = Post.objects.create(
- category=self.category,
- thread=self.thread,
- poster=user,
- poster_name=user.username,
- original="-",
- parsed="-",
- checksum="nope",
- posted_on=datetime + timedelta(10),
- updated_on=datetime + timedelta(10),
- is_event=True,
- )
- self.thread.synchronize()
- self.assertEqual(self.thread.last_post, event)
- self.assertEqual(self.thread.last_post_on, event.posted_on)
- self.assertEqual(self.thread.last_poster, user)
- self.assertEqual(self.thread.last_poster_name, user.username)
- self.assertEqual(self.thread.last_poster_slug, user.slug)
- self.assertTrue(self.thread.last_post_is_event)
- self.assertTrue(self.thread.has_events)
- self.assertFalse(self.thread.has_reported_posts)
- self.assertFalse(self.thread.has_unapproved_posts)
- self.assertFalse(self.thread.has_hidden_posts)
- # events don't count to reply count
- self.assertEqual(self.thread.replies, 3)
- # create another post to provoke other has_events resolution path
- Post.objects.create(
- category=self.category,
- thread=self.thread,
- poster=user,
- poster_name=user.username,
- original="Hello! I am test message!",
- parsed="<p>Hello! I am test message!</p>",
- checksum="nope",
- posted_on=datetime,
- updated_on=datetime,
- )
- self.thread.synchronize()
- self.assertFalse(self.thread.last_post_is_event)
- self.assertTrue(self.thread.has_events)
- # remove event
- event.delete()
- self.thread.synchronize()
- self.assertFalse(self.thread.last_post_is_event)
- self.assertFalse(self.thread.has_events)
- # has poll flag
- self.assertFalse(self.thread.has_poll)
- Poll.objects.create(
- thread=self.thread,
- category=self.category,
- poster_name="test",
- poster_slug="test",
- choices=[],
- )
- self.thread.synchronize()
- self.assertTrue(self.thread.has_poll)
- def test_set_first_post(self):
- """set_first_post sets first post and poster data on thread"""
- user = UserModel.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
- datetime = timezone.now() + timedelta(5)
- post = Post.objects.create(
- category=self.category,
- thread=self.thread,
- poster=user,
- poster_name=user.username,
- original="Hello! I am test message!",
- parsed="<p>Hello! I am test message!</p>",
- checksum="nope",
- posted_on=datetime,
- updated_on=datetime,
- )
- self.thread.set_first_post(post)
- self.assertEqual(self.thread.first_post, post)
- self.assertEqual(self.thread.started_on, post.posted_on)
- self.assertEqual(self.thread.starter, user)
- self.assertEqual(self.thread.starter_name, user.username)
- self.assertEqual(self.thread.starter_slug, user.slug)
- def test_set_last_post(self):
- """set_last_post sets first post and poster data on thread"""
- user = UserModel.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
- datetime = timezone.now() + timedelta(5)
- post = Post.objects.create(
- category=self.category,
- thread=self.thread,
- poster=user,
- poster_name=user.username,
- original="Hello! I am test message!",
- parsed="<p>Hello! I am test message!</p>",
- checksum="nope",
- posted_on=datetime,
- updated_on=datetime,
- )
- self.thread.set_last_post(post)
- self.assertEqual(self.thread.last_post, post)
- self.assertEqual(self.thread.last_post_on, post.posted_on)
- self.assertEqual(self.thread.last_poster, user)
- self.assertEqual(self.thread.last_poster_name, user.username)
- self.assertEqual(self.thread.last_poster_slug, user.slug)
- def test_set_best_answer(self):
- """set_best_answer sets best answer and setter data on thread"""
- user = UserModel.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
- best_answer = Post.objects.create(
- category=self.category,
- thread=self.thread,
- poster=user,
- poster_name=user.username,
- original="Hello! I am test message!",
- parsed="<p>Hello! I am test message!</p>",
- checksum="nope",
- posted_on=timezone.now(),
- updated_on=timezone.now(),
- is_protected=True,
- )
- self.thread.synchronize()
- self.thread.save()
- self.thread.set_best_answer(user, best_answer)
- self.thread.save()
- self.assertEqual(self.thread.best_answer, best_answer)
- self.assertTrue(self.thread.has_best_answer)
- self.assertTrue(self.thread.best_answer_is_protected)
- self.assertTrue(self.thread.best_answer_marked_on)
- self.assertEqual(self.thread.best_answer_marked_by, user)
- self.assertEqual(self.thread.best_answer_marked_by_name, user.username)
- self.assertEqual(self.thread.best_answer_marked_by_slug, user.slug)
- # clear best answer
- self.thread.clear_best_answer()
- self.assertIsNone(self.thread.best_answer)
- self.assertFalse(self.thread.has_best_answer)
- self.assertFalse(self.thread.best_answer_is_protected)
- self.assertIsNone(self.thread.best_answer_marked_on)
- self.assertIsNone(self.thread.best_answer_marked_by)
- self.assertIsNone(self.thread.best_answer_marked_by_name)
- self.assertIsNone(self.thread.best_answer_marked_by_slug)
- def test_set_invalid_best_answer(self):
- """set_best_answer implements some assertions for data integrity"""
- user = UserModel.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
- other_thread = testutils.post_thread(self.category)
- with self.assertRaises(ValueError):
- self.thread.set_best_answer(user, other_thread.first_post)
- with self.assertRaises(ValueError):
- self.thread.set_best_answer(user, self.thread.first_post)
- with self.assertRaises(ValueError):
- reply = testutils.reply_thread(self.thread, is_hidden=True)
- self.thread.set_best_answer(user, reply)
- with self.assertRaises(ValueError):
- reply = testutils.reply_thread(self.thread, is_unapproved=True)
- self.thread.set_best_answer(user, reply)
- def test_move(self):
- """move(new_category) moves thread to other category"""
- root_category = Category.objects.root_category()
- Category(name="New Category", slug="new-category").insert_at(
- root_category, position="last-child", save=True
- )
- new_category = Category.objects.get(slug="new-category")
- self.thread.move(new_category)
- self.assertEqual(self.thread.category, new_category)
- for post in self.thread.post_set.all():
- self.assertEqual(post.category_id, new_category.id)
- def test_merge(self):
- """merge(other_thread) moves other thread content to this thread"""
- with self.assertRaises(ValueError):
- self.thread.merge(self.thread)
- datetime = timezone.now() + timedelta(5)
- other_thread = Thread(
- category=self.category,
- started_on=datetime,
- starter_name="Tester",
- starter_slug="tester",
- last_post_on=datetime,
- last_poster_name="Tester",
- last_poster_slug="tester",
- )
- other_thread.set_title("Other thread")
- other_thread.save()
- post = Post.objects.create(
- category=self.category,
- thread=other_thread,
- poster_name="Admin",
- original="Hello! I am other message!",
- parsed="<p>Hello! I am other message!</p>",
- checksum="nope",
- posted_on=datetime,
- updated_on=datetime,
- )
- other_thread.first_post = post
- other_thread.last_post = post
- other_thread.save()
- self.thread.merge(other_thread)
- self.thread.synchronize()
- self.assertEqual(self.thread.replies, 1)
- self.assertEqual(self.thread.last_post, post)
- self.assertEqual(self.thread.last_post_on, post.posted_on)
- self.assertEqual(self.thread.last_poster_name, "Admin")
- self.assertEqual(self.thread.last_poster_slug, "admin")
- def test_delete_private_thread(self):
- """
- private thread gets deleted automatically
- when there are no participants left in it
- """
- user_a = UserModel.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
- user_b = UserModel.objects.create_user(
- "Weebl", "weebl@weeblson.com", "Pass.123"
- )
- ThreadParticipant.objects.add_participants(self.thread, [user_a, user_b])
- self.assertEqual(self.thread.participants.count(), 2)
- user_a.delete()
- Thread.objects.get(id=self.thread.id)
- user_b.delete()
- with self.assertRaises(Thread.DoesNotExist):
- Thread.objects.get(id=self.thread.id)
|