diff --git a/wagtail/tests/utils.py b/wagtail/tests/utils.py index 3cfca1f098..939ba0496a 100644 --- a/wagtail/tests/utils.py +++ b/wagtail/tests/utils.py @@ -1,9 +1,18 @@ -from contextlib import contextmanager -import warnings -import sys +from __future__ import absolute_import, unicode_literals +import sys +import warnings +from contextlib import contextmanager + +import django from django.contrib.auth import get_user_model +from django.contrib.contenttypes.models import ContentType +from django.core.urlresolvers import reverse +from django.test import TestCase from django.utils import six +from django.utils.text import slugify + +from wagtail.wagtailcore.models import Page class WagtailTestUtils(object): @@ -51,3 +60,88 @@ class WagtailTestUtils(object): for mod in list(sys.modules.values()): if hasattr(mod, key): getattr(mod, key).clear() + + +class WagtailPageTests(WagtailTestUtils, TestCase): + """ + A set of asserts to help write tests for your own Wagtail site. + """ + def setUp(self): + super(WagtailPageTests, self).setUp() + self.login() + + def _testCanCreateAt(self, parent_model, child_model): + child_ct = ContentType.objects.get_for_model(child_model) + parent_ct = ContentType.objects.get_for_model(parent_model) + + return all([ + child_ct in parent_model.allowed_subpage_types(), + # Anything can be created under a Page + parent_model is Page or parent_ct in child_model.allowed_parent_page_types()]) + + def assertCanCreateAt(self, parent_model, child_model, msg=None): + """ + Assert a particular child Page type can be created under a parent + Page type. + """ + if not self._testCanCreateAt(parent_model, child_model): + msg = self._formatMessage(msg, "Can not create a %s.%s under a %s.%s" % ( + child_model._meta.app_label, child_model._meta.model_name, + parent_model._meta.app_label, parent_model._meta.model_name)) + raise self.failureException(msg) + + def assertCanNotCreateAt(self, parent_model, child_model, msg=None): + """ + Assert a particular child Page type can not be created under a parent + Page type. + """ + if self._testCanCreateAt(parent_model, child_model): + msg = self._formatMessage(msg, "Can create a %s.%s under a %s.%s" % ( + child_model._meta.app_label, child_model._meta.model_name, + parent_model._meta.app_label, parent_model._meta.model_name)) + raise self.failureException(msg) + + def assertCanCreate(self, parent, child_model, data, msg=None): + """ + Assert that a child of the given Page type can be created under the + parent, using the supplied POST data + """ + self.assertCanCreateAt(parent.specific_class, child_model) + + if 'slug' not in data and 'title' in data: + data['slug'] = slugify(data['title']) + data['action-publish'] = 'action-publish' + + add_url = reverse('wagtailadmin_pages:add', args=[ + child_model._meta.app_label, child_model._meta.model_name, parent.pk]) + response = self.client.post(add_url, data, follow=True) + + if response.status_code != 200: + msg = self._formatMessage(msg, 'Creating a %s.%s returned a %d' % ( + child_model._meta.app_label, child_model._meta.model_name, response.status_code)) + raise self.failureException(msg) + + if response.redirect_chain == []: + if 'form' not in response.context: + msg = self._formatMessage(msg, 'Creating a page failed unusually') + raise self.failureException(msg) + form = response.context['form'] + if not form.errors: + msg = self._formatMessage(msg, 'Creating a page failed for an unknown reason') + raise self.failureException(msg) + + errors = '\n'.join(' %s:\n %s' % (field, '\n '.join(errors)) + for field, errors in sorted(form.errors.items())) + msg = self._formatMessage(msg, 'Validation errors found when creating a %s.%s:\n%s' % ( + child_model._meta.app_label, child_model._meta.model_name, errors)) + raise self.failureException(msg) + + if django.VERSION >= (1, 9): + explore_url = reverse('wagtailadmin_explore', args=[parent.pk]) + else: + explore_url = 'http://testserver' + reverse('wagtailadmin_explore', args=[parent.pk]) + if response.redirect_chain != [(explore_url, 302)]: + msg = self._formatMessage(msg, 'Creating a page %s.%s didnt redirect the user to the explorer, but to %s' % ( + child_model._meta.app_label, child_model._meta.model_name, + response.redirect_chain)) + raise self.failureException(msg) diff --git a/wagtail/wagtailcore/tests/test_tests.py b/wagtail/wagtailcore/tests/test_tests.py new file mode 100644 index 0000000000..41ddeb8c8a --- /dev/null +++ b/wagtail/wagtailcore/tests/test_tests.py @@ -0,0 +1,57 @@ +from __future__ import absolute_import, unicode_literals + +import json + +from wagtail.tests.testapp.models import ( + BusinessChild, EventIndex, EventPage, SimplePage, StreamPage) +from wagtail.tests.utils import WagtailPageTests +from wagtail.wagtailcore.models import Page, Site + + +class TestWagtailPageTests(WagtailPageTests): + def setUp(self): + super(TestWagtailPageTests, self).setUp() + site = Site.objects.get(is_default_site=True) + self.root = site.root_page.specific + + def test_assert_can_create_at(self): + # It should be possible to create an EventPage under an EventIndex, + self.assertCanCreateAt(EventIndex, EventPage) + self.assertCanCreateAt(Page, EventIndex) + # It should not be possible to create a SimplePage under a BusinessChild + self.assertCanNotCreateAt(SimplePage, BusinessChild) + + # This should raise, as it *is not* possible + with self.assertRaises(AssertionError): + self.assertCanCreateAt(SimplePage, BusinessChild) + # This should raise, as it *is* possible + with self.assertRaises(AssertionError): + self.assertCanNotCreateAt(EventIndex, EventPage) + + def test_assert_can_create(self): + + self.assertFalse(EventIndex.objects.exists()) + self.assertCanCreate(self.root, EventIndex, { + 'title': 'Event Index', + 'intro': '

Event intro

'}) + self.assertTrue(EventIndex.objects.exists()) + + self.assertCanCreate(self.root, StreamPage, { + 'title': 'WebDev42', + 'body': json.dumps([ + {'type': 'text', 'value': 'Some text'}, + {'type': 'rich_text', 'value': '

Some rich text

'}, + ])}) + + def test_assert_can_create_subpage_rules(self): + simple_page = SimplePage(title='Simple Page', slug='simple') + self.root.add_child(instance=simple_page) + # This should raise an error, as a BusinessChild can not be created under a SimplePage + with self.assertRaisesRegexp(AssertionError, r'Can not create a tests.businesschild under a tests.simplepage'): + self.assertCanCreate(simple_page, BusinessChild, {}) + + def test_assert_can_create_validation_error(self): + # This should raise some validation errors, complaining about missing + # title and slug fields + with self.assertRaisesRegexp(AssertionError, r'\bslug:\n[\s\S]*\btitle:\n'): + self.assertCanCreate(self.root, SimplePage, {})