# coding=utf-8 import time import logging from django.core.paginator import Paginator from django.test import TestCase from django.test.client import Client from django.core.urlresolvers import reverse, NoReverseMatch from boards.models import Post, Tag, Thread from boards import urls from neboard import settings PAGE_404 = 'boards/404.html' TEST_TEXT = 'test text' NEW_THREAD_PAGE = '/' THREAD_PAGE_ONE = '/thread/1/' THREAD_PAGE = '/thread/' TAG_PAGE = '/tag/' HTTP_CODE_REDIRECT = 302 HTTP_CODE_OK = 200 HTTP_CODE_NOT_FOUND = 404 logger = logging.getLogger(__name__) class PostTests(TestCase): def _create_post(self): return Post.objects.create_post(title='title', text='text') def test_post_add(self): """Test adding post""" post = self._create_post() self.assertIsNotNone(post, 'No post was created') def test_delete_post(self): """Test post deletion""" post = self._create_post() post_id = post.id Post.objects.delete_post(post) self.assertFalse(Post.objects.filter(id=post_id).exists()) def test_delete_thread(self): """Test thread deletion""" opening_post = self._create_post() thread = opening_post.get_thread() reply = Post.objects.create_post("", "", thread=thread) thread.delete_with_posts() self.assertFalse(Post.objects.filter(id=reply.id).exists()) def test_post_to_thread(self): """Test adding post to a thread""" op = self._create_post() post = Post.objects.create_post("", "", thread=op.get_thread()) self.assertIsNotNone(post, 'Reply to thread wasn\'t created') self.assertEqual(op.get_thread().last_edit_time, post.pub_time, 'Post\'s create time doesn\'t match thread last edit' ' time') def test_delete_posts_by_ip(self): """Test deleting posts with the given ip""" post = self._create_post() post_id = post.id Post.objects.delete_posts_by_ip('0.0.0.0') self.assertFalse(Post.objects.filter(id=post_id).exists()) def test_get_thread(self): """Test getting all posts of a thread""" opening_post = self._create_post() for i in range(0, 2): Post.objects.create_post('title', 'text', thread=opening_post.get_thread()) thread = opening_post.get_thread() self.assertEqual(3, thread.replies.count()) def test_create_post_with_tag(self): """Test adding tag to post""" tag = Tag.objects.create(name='test_tag') post = Post.objects.create_post(title='title', text='text', tags=[tag]) thread = post.get_thread() self.assertIsNotNone(post, 'Post not created') self.assertTrue(tag in thread.tags.all(), 'Tag not added to thread') self.assertTrue(thread in tag.threads.all(), 'Thread not added to tag') def test_thread_max_count(self): """Test deletion of old posts when the max thread count is reached""" for i in range(settings.MAX_THREAD_COUNT + 1): self._create_post() self.assertEqual(settings.MAX_THREAD_COUNT, len(Thread.objects.filter(archived=False))) def test_pages(self): """Test that the thread list is properly split into pages""" for i in range(settings.MAX_THREAD_COUNT): self._create_post() all_threads = Thread.objects.filter(archived=False) paginator = Paginator(Thread.objects.filter(archived=False), settings.THREADS_PER_PAGE) posts_in_second_page = paginator.page(2).object_list first_post = posts_in_second_page[0] self.assertEqual(all_threads[settings.THREADS_PER_PAGE].id, first_post.id) def test_linked_tag(self): """Test adding a linked tag""" linked_tag = Tag.objects.create(name=u'tag1') tag = Tag.objects.create(name=u'tag2', linked=linked_tag) post = Post.objects.create_post("", "", tags=[tag]) self.assertTrue(linked_tag in post.get_thread().tags.all(), 'Linked tag was not added') class PagesTest(TestCase): def test_404(self): """Test receiving error 404 when opening a non-existent page""" tag_name = u'test_tag' tag = Tag.objects.create(name=tag_name) client = Client() Post.objects.create_post('title', TEST_TEXT, tags=[tag]) existing_post_id = Post.objects.all()[0].id response_existing = client.get(THREAD_PAGE + str(existing_post_id) + '/') self.assertEqual(HTTP_CODE_OK, response_existing.status_code, u'Cannot open existing thread') response_not_existing = client.get(THREAD_PAGE + str( existing_post_id + 1) + '/') self.assertEqual(PAGE_404, response_not_existing.templates[0].name, u'Not existing thread is opened') response_existing = client.get(TAG_PAGE + tag_name + '/') self.assertEqual(HTTP_CODE_OK, response_existing.status_code, u'Cannot open existing tag') response_not_existing = client.get(TAG_PAGE + u'not_tag' + '/') self.assertEqual(PAGE_404, response_not_existing.templates[0].name, u'Not existing tag is opened') reply_id = Post.objects.create_post('', TEST_TEXT, thread=Post.objects.all()[0] .get_thread()) response_not_existing = client.get(THREAD_PAGE + str( reply_id) + '/') self.assertEqual(PAGE_404, response_not_existing.templates[0].name, u'Reply is opened as a thread') class FormTest(TestCase): def test_post_validation(self): # Disable captcha for the test captcha_enabled = settings.ENABLE_CAPTCHA settings.ENABLE_CAPTCHA = False client = Client() valid_tags = u'tag1 tag_2 тег_3' invalid_tags = u'$%_356 ---' response = client.post(NEW_THREAD_PAGE, {'title': 'test title', 'text': TEST_TEXT, 'tags': valid_tags}) self.assertEqual(response.status_code, HTTP_CODE_REDIRECT, msg='Posting new message failed: got code ' + str(response.status_code)) self.assertEqual(1, Post.objects.count(), msg='No posts were created') client.post(NEW_THREAD_PAGE, {'text': TEST_TEXT, 'tags': invalid_tags}) self.assertEqual(1, Post.objects.count(), msg='The validation passed ' 'where it should fail') # Change posting delay so we don't have to wait for 30 seconds or more old_posting_delay = settings.POSTING_DELAY # Wait fot the posting delay or we won't be able to post settings.POSTING_DELAY = 1 time.sleep(settings.POSTING_DELAY + 1) response = client.post(THREAD_PAGE_ONE, {'text': TEST_TEXT, 'tags': valid_tags}) self.assertEqual(HTTP_CODE_REDIRECT, response.status_code, msg=u'Posting new message failed: got code ' + str(response.status_code)) # Restore posting delay settings.POSTING_DELAY = old_posting_delay self.assertEqual(2, Post.objects.count(), msg=u'No posts were created') # Restore captcha setting settings.ENABLE_CAPTCHA = captcha_enabled class ViewTest(TestCase): def test_all_views(self): ''' Try opening all views defined in ulrs.py that don't need additional parameters ''' client = Client() for url in urls.urlpatterns: try: view_name = url.name logger.debug('Testing view %s' % view_name) try: response = client.get(reverse(view_name)) self.assertEqual(HTTP_CODE_OK, response.status_code, '%s view not opened' % view_name) except NoReverseMatch: # This view just needs additional arguments pass except Exception, e: self.fail('Got exception %s at %s view' % (e, view_name)) except AttributeError: # This is normal, some views do not have names pass