Add test helpers for Wagtail sites

`wagtail.tests.utils.WagtailPageTests` is a new `TestCase` subclass that
helps developers write tests for their Wagtail sites. It currently
includes three assert methods:

`assertCanCreateAt(parent_model, child_model)`, which asserts that a
child page of a certain type could be created underneath a parent page.
This is useful for making assertions around the business rules of your
site.

`assertCanNotCreateAt(parent_model, child_model)` is the inverse of the
above.

`assertCanCreate(parent, child_model, data)` asserts that a child page
can be added underneath the given parent page, by POSTing `data` at the
correct page in the Wagtail admin. This checks that the developer has
correctly configured their `content_panels` and related options.

These methods are just a start, and could be expanded further. More
methods could be added, asserting that Snippets can be created, for
example. The current methods could be extended further, to validate more
about the Wagtail admin page editor.
pull/1796/merge
Tim Heap 2015-10-06 11:25:16 +11:00 zatwierdzone przez Matt Westcott
rodzic d160ea3ccf
commit 6947eab55b
2 zmienionych plików z 154 dodań i 3 usunięć

Wyświetl plik

@ -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)

Wyświetl plik

@ -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': '<p>Event intro</p>'})
self.assertTrue(EventIndex.objects.exists())
self.assertCanCreate(self.root, StreamPage, {
'title': 'WebDev42',
'body': json.dumps([
{'type': 'text', 'value': 'Some text'},
{'type': 'rich_text', 'value': '<p>Some rich text</p>'},
])})
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, {})