From abf2c1bb6102089f2ec67f4c389791143688cce5 Mon Sep 17 00:00:00 2001 From: Iacopo Spalletti Date: Sun, 26 Jun 2016 11:54:40 +0200 Subject: [PATCH] Add tests for liveblog --- djangocms_blog/liveblog/__init__.py | 3 + djangocms_blog/liveblog/models.py | 57 ++++-- ...post_liveblog.py => 0021_post_liveblog.py} | 2 +- ...605_2305.py => 0022_auto_20160605_2305.py} | 2 +- tests/test_liveblog.py | 178 ++++++++++++++++++ tox.ini | 1 + 6 files changed, 222 insertions(+), 21 deletions(-) rename djangocms_blog/migrations/{0018_post_liveblog.py => 0021_post_liveblog.py} (90%) rename djangocms_blog/migrations/{0019_auto_20160605_2305.py => 0022_auto_20160605_2305.py} (90%) create mode 100644 tests/test_liveblog.py diff --git a/djangocms_blog/liveblog/__init__.py b/djangocms_blog/liveblog/__init__.py index 40a96af..f3a5710 100644 --- a/djangocms_blog/liveblog/__init__.py +++ b/djangocms_blog/liveblog/__init__.py @@ -1 +1,4 @@ # -*- coding: utf-8 -*- +from __future__ import absolute_import, print_function, unicode_literals + +default_app_config = 'djangocms_blog.liveblog.apps.LiveBlogAppConfig' diff --git a/djangocms_blog/liveblog/models.py b/djangocms_blog/liveblog/models.py index f6a4396..0f50605 100644 --- a/djangocms_blog/liveblog/models.py +++ b/djangocms_blog/liveblog/models.py @@ -16,32 +16,28 @@ from djangocms_blog.models import Post, thumbnail_model DATE_FORMAT = "%a %d %b %Y %H:%M" -class Liveblog(AbstractText): - title = models.CharField(_('title'), max_length=255) - image = FilerImageField( - verbose_name=_('image'), blank=True, null=True, on_delete=models.SET_NULL, - related_name='djangocms_blog_liveblog_image' - ) - thumbnail = models.ForeignKey( - thumbnail_model, verbose_name=_('thumbnail size'), on_delete=models.SET_NULL, - blank=True, null=True, related_name='djangocms_blog_liveblog_thumbnail' - ) +class LiveblogInterface(models.Model): + """ + Abstract Liveblog plugin model, reusable to customize the liveblogging plugins. + + When implementing this, you **must** call ``self._post_save()`` in the concrete + plugin model ``save`` method. + """ publish = models.BooleanField(_('publish liveblog entry'), default=False) node_order_by = '-changed_date' class Meta: verbose_name = _('liveblog entry') verbose_name_plural = _('liveblog entries') + abstract = True - def save(self, no_signals=False, *args, **kwargs): - saved = super(Liveblog, self).save(*args, **kwargs) + def _post_save(self): if self.publish: self.send() order = CMSPlugin.objects.filter( placeholder=self.placeholder ).order_by('placeholder', 'path').values_list('pk', flat=True) reorder_plugins(self.placeholder, None, self.language, order) - return saved @property def liveblog_group(self): @@ -56,13 +52,36 @@ class Liveblog(AbstractText): """ Render the content and send to the related group """ - notification = { - 'id': self.pk, - 'content': self.render(), - 'creation_date': self.creation_date.strftime(DATE_FORMAT), - 'changed_date': self.changed_date.strftime(DATE_FORMAT), - } if self.liveblog_group: + notification = { + 'id': self.pk, + 'content': self.render(), + 'creation_date': self.creation_date.strftime(DATE_FORMAT), + 'changed_date': self.changed_date.strftime(DATE_FORMAT), + } Group(self.liveblog_group).send({ 'text': json.dumps(notification), }) + + +class Liveblog(LiveblogInterface, AbstractText): + """ + Basic liveblog plugin model + """ + title = models.CharField(_('title'), max_length=255) + image = FilerImageField( + verbose_name=_('image'), blank=True, null=True, on_delete=models.SET_NULL, + related_name='djangocms_blog_liveblog_image' + ) + thumbnail = models.ForeignKey( + thumbnail_model, verbose_name=_('thumbnail size'), on_delete=models.SET_NULL, + blank=True, null=True, related_name='djangocms_blog_liveblog_thumbnail' + ) + + class Meta: + verbose_name = _('liveblog entry') + verbose_name_plural = _('liveblog entries') + + def save(self, *args, **kwargs): + super(Liveblog, self).save(*args, **kwargs) + self._post_save() diff --git a/djangocms_blog/migrations/0018_post_liveblog.py b/djangocms_blog/migrations/0021_post_liveblog.py similarity index 90% rename from djangocms_blog/migrations/0018_post_liveblog.py rename to djangocms_blog/migrations/0021_post_liveblog.py index db8d1aa..28e9aa4 100644 --- a/djangocms_blog/migrations/0018_post_liveblog.py +++ b/djangocms_blog/migrations/0021_post_liveblog.py @@ -9,7 +9,7 @@ class Migration(migrations.Migration): dependencies = [ ('cms', '__first__'), - ('djangocms_blog', '0017_thumbnail_move'), + ('djangocms_blog', '0020_thumbnail_move4'), ] operations = [ diff --git a/djangocms_blog/migrations/0019_auto_20160605_2305.py b/djangocms_blog/migrations/0022_auto_20160605_2305.py similarity index 90% rename from djangocms_blog/migrations/0019_auto_20160605_2305.py rename to djangocms_blog/migrations/0022_auto_20160605_2305.py index f2b0f8d..25e7892 100644 --- a/djangocms_blog/migrations/0019_auto_20160605_2305.py +++ b/djangocms_blog/migrations/0022_auto_20160605_2305.py @@ -9,7 +9,7 @@ import django.db.models.deletion class Migration(migrations.Migration): dependencies = [ - ('djangocms_blog', '0018_post_liveblog'), + ('djangocms_blog', '0021_post_liveblog'), ] operations = [ diff --git a/tests/test_liveblog.py b/tests/test_liveblog.py new file mode 100644 index 0000000..09ab014 --- /dev/null +++ b/tests/test_liveblog.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, print_function, unicode_literals + +import json +from unittest import SkipTest + +try: + from channels import Channel + from channels.tests import ChannelTestCase + from cms.api import add_plugin + + from djangocms_blog.liveblog.consumers import liveblog_connect, liveblog_disconnect + from djangocms_blog.liveblog.models import DATE_FORMAT + from .base import BaseTest + + + class LiveBlogTest(BaseTest, ChannelTestCase): + + @classmethod + def setUpClass(cls): + try: + import knocker + super(LiveBlogTest, cls).setUpClass() + except ImportError: + raise SkipTest('channels not installed, skipping tests') + + def test_add_plugin(self): + posts = self.get_posts() + self.get_pages() + post = posts[0] + post.enable_liveblog = True + post.save() + + Channel('setup').send({'connect': 1, 'reply_channel': 'reply'}) + message = self.get_next_message('setup', require=True) + liveblog_connect(message, self.app_config_1.namespace, 'en', post.slug) + + plugin = add_plugin( + post.liveblog, 'LiveblogPlugin', language='en', body='live text', publish=True + ) + result = self.get_next_message(message.reply_channel.name, require=True) + self.assertTrue(result['text']) + + rendered = json.loads(result['text']) + self.assertEqual(plugin.pk, rendered['id']) + self.assertEqual(plugin.creation_date.strftime(DATE_FORMAT), rendered['creation_date']) + self.assertEqual(plugin.changed_date.strftime(DATE_FORMAT), rendered['changed_date']) + self.assertTrue(rendered['content'].find('data-post-id="{}"'.format(plugin.pk)) > -1) + self.assertTrue(rendered['content'].find('live text') > -1) + + plugin.body = 'modified text' + plugin.save() + + result = self.get_next_message(message.reply_channel.name, require=True) + self.assertTrue(result['text']) + + rendered = json.loads(result['text']) + self.assertEqual(plugin.pk, rendered['id']) + self.assertEqual(plugin.creation_date.strftime(DATE_FORMAT), rendered['creation_date']) + self.assertEqual(plugin.changed_date.strftime(DATE_FORMAT), rendered['changed_date']) + self.assertTrue(rendered['content'].find('data-post-id="{}"'.format(plugin.pk)) > -1) + self.assertTrue(rendered['content'].find('modified text') > -1) + self.assertTrue(rendered['content'].find('live text') == -1) + + def test_add_plugin_no_publish(self): + posts = self.get_posts() + self.get_pages() + post = posts[0] + post.enable_liveblog = True + post.save() + + Channel('setup').send({'connect': 1, 'reply_channel': 'reply'}) + message = self.get_next_message('setup', require=True) + liveblog_connect(message, self.app_config_1.namespace, 'en', post.slug) + + plugin = add_plugin( + post.liveblog, 'LiveblogPlugin', language='en', body='live text', publish=False + ) + result = self.get_next_message(message.reply_channel.name, require=False) + self.assertIsNone(result) + + plugin.publish = True + plugin.save() + + result = self.get_next_message(message.reply_channel.name, require=True) + self.assertTrue(result['text']) + + rendered = json.loads(result['text']) + self.assertEqual(plugin.pk, rendered['id']) + self.assertEqual(plugin.creation_date.strftime(DATE_FORMAT), rendered['creation_date']) + self.assertEqual(plugin.changed_date.strftime(DATE_FORMAT), rendered['changed_date']) + self.assertTrue(rendered['content'].find('data-post-id="{}"'.format(plugin.pk)) > -1) + self.assertTrue(rendered['content'].find('live text') > -1) + + def test_disconnect(self): + posts = self.get_posts() + self.get_pages() + post = posts[0] + post.enable_liveblog = True + post.save() + + Channel('setup').send({'connect': 1, 'reply_channel': 'reply'}) + message = self.get_next_message('setup', require=True) + liveblog_connect(message, self.app_config_1.namespace, 'en', post.slug) + + plugin = add_plugin( + post.liveblog, 'LiveblogPlugin', language='en', body='live text', publish=True + ) + result = self.get_next_message(message.reply_channel.name, require=True) + self.assertTrue(result['text']) + + liveblog_disconnect(message, self.app_config_1.namespace, 'en', post.slug) + + plugin.body = 'modified text' + plugin.save() + + result = self.get_next_message(message.reply_channel.name, require=False) + self.assertIsNone(result) + + def test_nopost(self): + + self.get_pages() + + Channel('setup').send({'connect': 1, 'reply_channel': 'reply'}) + message = self.get_next_message('setup', require=True) + liveblog_connect(message, self.app_config_1.namespace, 'en', 'random-post') + + result = self.get_next_message(message.reply_channel.name, require=True) + self.assertTrue(result['text']) + rendered = json.loads(result['text']) + self.assertTrue(rendered['error'], 'no_post') + + liveblog_disconnect(message, self.app_config_1.namespace, 'en', 'random-post') + result = self.get_next_message(message.reply_channel.name, require=True) + self.assertTrue(result['text']) + rendered = json.loads(result['text']) + self.assertTrue(rendered['error'], 'no_post') + + def test_plugin_without_post(self): + + pages = self.get_pages() + + placeholder = pages[0].get_placeholders().get(slot='content') + + Channel('setup').send({'connect': 1, 'reply_channel': 'reply'}) + message = self.get_next_message('setup', require=True) + liveblog_connect(message, self.app_config_1.namespace, 'en', 'random post') + self.get_next_message(message.reply_channel.name, require=True) + + plugin = add_plugin( + placeholder, 'LiveblogPlugin', language='en', body='live text', publish=True + ) + self.assertIsNone(plugin.liveblog_group) + result = self.get_next_message(message.reply_channel.name, require=False) + self.assertIsNone(result) + + def test_plugin_render(self): + posts = self.get_posts() + pages = self.get_pages() + post = posts[0] + post.enable_liveblog = True + post.save() + plugin = add_plugin( + post.liveblog, 'LiveblogPlugin', language='en', body='live text', publish=False + ) + context = self.get_plugin_context(pages[0], 'en', plugin, edit=False) + rendered = plugin.render_plugin(context, post.liveblog) + self.assertFalse(rendered) + + plugin.publish = True + plugin.save() + context = self.get_plugin_context(pages[0], 'en', plugin, edit=False) + rendered = plugin.render_plugin(context, post.liveblog) + self.assertTrue(rendered.find('data-post-id="{}"'.format(plugin.pk)) > -1) + self.assertTrue(rendered.find('live text') > -1) + +except ImportError: # pragma: no cover + pass diff --git a/tox.ini b/tox.ini index 454f361..e1f679f 100644 --- a/tox.ini +++ b/tox.ini @@ -17,6 +17,7 @@ deps = cms33: https://github.com/divio/django-cms/archive/release/3.3.x.zip cms33: djangocms-text-ckeditor>=3.0 knocker: https://github.com/divio/django-cms/archive/release/3.2.x.zip + knocker: channels>=0.15 knocker: https://github.com/nephila/django-knocker/archive/master.zip?0.1.1 knocker: djangocms-text-ckeditor<3.0 django-meta>=1.2