Testing your Wagtail site¶
Wagtail comes with some utilities that simplify writing tests for your site.
WagtailPageTests¶
-
class
wagtail.tests.utils.
WagtailPageTests
¶ WagtailPageTests
extendsdjango.test.TestCase
, adding a few newassert
methods. You should extend this class to make use of its methods:from wagtail.tests.utils import WagtailPageTests from myapp.models import MyPage class MyPageTests(WagtailPageTests): def test_can_create_a_page(self): ...
-
assertCanCreateAt
(parent_model, child_model, msg=None)¶ Assert a particular child Page type can be created under a parent Page type.
parent_model
andchild_model
should be the Page classes being tested.def test_can_create_under_home_page(self): # You can create a ContentPage under a HomePage self.assertCanCreateAt(HomePage, ContentPage)
-
assertCanNotCreateAt
(parent_model, child_model, msg=None)¶ Assert a particular child Page type can not be created under a parent Page type.
parent_model
andchild_model
should be the Page classes being tested.def test_cant_create_under_event_page(self): # You can not create a ContentPage under an EventPage self.assertCanNotCreateAt(EventPage, ContentPage)
-
assertCanCreate
(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.
parent
should be a Page instance, andchild_model
should be a Page subclass.data
should be a dict that will be POSTed at the Wagtail admin Page creation method.from wagtail.tests.utils.form_data import nested_form_data, streamfield def test_can_create_content_page(self): # Get the HomePage root_page = HomePage.objects.get(pk=2) # Assert that a ContentPage can be made here, with this POST data self.assertCanCreate(root_page, ContentPage, nested_form_data({ 'title': 'About us', 'body': streamfield([ ('text', 'Lorem ipsum dolor sit amet'), ]) }))
See Form data helpers for a set of functions useful for constructing POST data.
-
assertAllowedParentPageTypes
(child_model, parent_models, msg=None)¶ Test that the only page types that
child_model
can be created under areparent_models
.The list of allowed parent models may differ from those set in
Page.parent_page_types
, if the parent models have setPage.subpage_types
.def test_content_page_parent_pages(self): # A ContentPage can only be created under a HomePage # or another ContentPage self.assertAllowedParentPageTypes( ContentPage, {HomePage, ContentPage}) # An EventPage can only be created under an EventIndex self.assertAllowedParentPageTypes( EventPage, {EventIndex})
-
assertAllowedSubpageTypes
(parent_model, child_models, msg=None)¶ Test that the only page types that can be created under
parent_model
arechild_models
.The list of allowed child models may differ from those set in
Page.subpage_types
, if the child models have setPage.parent_page_types
.def test_content_page_subpages(self): # A ContentPage can only have other ContentPage children self.assertAllowedSubpageTypes( ContentPage, {ContentPage}) # A HomePage can have ContentPage and EventIndex children self.assertAllowedParentPageTypes( HomePage, {ContentPage, EventIndex})
-
Form data helpers¶
The assertCanCreate
method requires page data to be passed in
the same format that the page edit form would submit. For complex
page types, it can be difficult to construct this data structure by hand;
the wagtail.tests.utils.form_data
module provides a set of helper
functions to assist with this.
-
wagtail.tests.utils.form_data.
nested_form_data
(data)¶ Translates a nested dict structure into a flat form data dict with hyphen-separated keys.
nested_form_data({ 'foo': 'bar', 'parent': { 'child': 'field', }, }) # Returns: {'foo': 'bar', 'parent-child': 'field'}
-
wagtail.tests.utils.form_data.
rich_text
(value, editor='default', features=None)¶ Converts an HTML-like rich text string to the data format required by the currently active rich text editor.
Parameters: - editor – An alternative editor name as defined in
WAGTAILADMIN_RICH_TEXT_EDITORS
- features – A list of features allowed in the rich text content (see Limiting features in a rich text field)
self.assertCanCreate(root_page, ContentPage, nested_form_data({ 'title': 'About us', 'body': rich_text('<p>Lorem ipsum dolor sit amet</p>'), }))
- editor – An alternative editor name as defined in
-
wagtail.tests.utils.form_data.
streamfield
(items)¶ Takes a list of (block_type, value) tuples and turns it in to StreamField form data. Use this within a
nested_form_data()
call, with the field name as the key.nested_form_data({'content': streamfield([ ('text', 'Hello, world'), ])}) # Returns: # { # 'content-count': '1', # 'content-0-type': 'text', # 'content-0-value': 'Hello, world', # 'content-0-order': '0', # 'content-0-deleted': '', # }
-
wagtail.tests.utils.form_data.
inline_formset
(items, initial=0, min=0, max=1000)¶ Takes a list of form data for an InlineFormset and translates it in to valid POST data. Use this within a
nested_form_data()
call, with the formset relation name as the key.nested_form_data({'lines': inline_formset([ {'text': 'Hello'}, {'text': 'World'}, ])}) # Returns: # { # 'lines-TOTAL_FORMS': '2', # 'lines-INITIAL_FORMS': '0', # 'lines-MIN_NUM_FORMS': '0', # 'lines-MAX_NUM_FORMS': '1000', # 'lines-0-text': 'Hello', # 'lines-0-ORDER': '0', # 'lines-0-DELETE': '', # 'lines-1-text': 'World', # 'lines-1-ORDER': '1', # 'lines-1-DELETE': '', # }
Fixtures¶
Using dumpdata
¶
Creating fixtures for tests is best done by creating content in a development environment, and using Django’s dumpdata command.
Note that by default dumpdata
will represent content_type
by the primary key; this may cause consistency issues when adding / removing models, as content types are populated separately from fixtures. To prevent this, use the --natural-foreign
switch, which represents content types by ["app", "model"]
instead.
Manual modification¶
You could modify the dumped fixtures manually, or even write them all by hand. Here are a few things to be wary of.
Custom Page models¶
When creating customised Page models in fixtures, you will need to add both a
wagtailcore.page
entry, and one for your custom Page model.
Let’s say you have a website
module which defines a Homepage(Page)
class.
You could create such a homepage in a fixture with:
[
{
"model": "wagtailcore.page",
"pk": 3,
"fields": {
"title": "My Customer's Homepage",
"content_type": ["website", "homepage"],
"depth": 2
}
},
{
"model": "website.homepage",
"pk": 3,
"fields": {}
}
]
Treebeard fields¶
Filling in the path
/ numchild
/ depth
fields is necessary in order for tree operations like get_parent()
to work correctly.
url_path
is another field that can cause errors in some uncommon cases if it isn’t filled in.
The Treebeard docs might help in understanding how this works.