Add form data helpers

pull/4268/merge
Matt Westcott 2018-02-14 15:51:52 +00:00
rodzic 0a634b0a42
commit 067c26f54d
3 zmienionych plików z 196 dodań i 2 usunięć

Wyświetl plik

@ -44,14 +44,21 @@ WagtailPageTests
.. code-block:: python
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, {
self.assertCanCreate(root_page, ContentPage, nested_form_data({
'title': 'About us',
'body': 'Lorem ipsum dolor sit amet')
'body': streamfield([
('text', 'Lorem ipsum dolor sit amet'),
])
}))
See :ref:`form_data_test_helpers` for a set of functions useful for constructing POST data.
.. automethod:: assertAllowedParentPageTypes
@ -79,3 +86,17 @@ WagtailPageTests
# A HomePage can have ContentPage and EventIndex children
self.assertAllowedParentPageTypes(
HomePage, {ContentPage, EventIndex})
.. _form_data_test_helpers:
Form data helpers
=================
.. automodule:: wagtail.tests.utils.form_data
.. autofunction:: nested_form_data
.. autofunction:: streamfield
.. autofunction:: inline_formset

Wyświetl plik

@ -5,6 +5,7 @@ from wagtail.tests.testapp.models import (
BusinessChild, BusinessIndex, BusinessNowherePage, BusinessSubIndex, EventIndex, EventPage,
SimplePage, StreamPage)
from wagtail.tests.utils import WagtailPageTests, WagtailTestUtils
from wagtail.tests.utils.form_data import inline_formset, nested_form_data, streamfield
class TestAssertTagInHTML(WagtailTestUtils, TestCase):
@ -137,3 +138,60 @@ class TestWagtailPageTests(WagtailPageTests):
self.assertAllowedParentPageTypes(BusinessIndex, all_but_business)
with self.assertRaises(AssertionError):
self.assertAllowedParentPageTypes(BusinessSubIndex, {BusinessSubIndex, BusinessIndex})
class TestFormDataHelpers(TestCase):
def test_nested_form_data(self):
result = nested_form_data({
'foo': 'bar',
'parent': {
'child': 'field',
},
})
self.assertEqual(
result,
{'foo': 'bar', 'parent-child': 'field'}
)
def test_streamfield(self):
result = nested_form_data({'content': streamfield([
('text', 'Hello, world'),
('text', 'Goodbye, world'),
])})
self.assertEqual(
result,
{
'content-count': '2',
'content-0-type': 'text',
'content-0-value': 'Hello, world',
'content-0-order': 0,
'content-0-deleted': '',
'content-1-type': 'text',
'content-1-value': 'Goodbye, world',
'content-1-order': 1,
'content-1-deleted': '',
}
)
def test_inline_formset(self):
result = nested_form_data({'lines': inline_formset([
{'text': 'Hello'},
{'text': 'World'},
])})
self.assertEqual(
result,
{
'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': '',
}
)

Wyświetl plik

@ -0,0 +1,115 @@
"""
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.
"""
def _nested_form_data(data):
if isinstance(data, dict):
items = data.items()
elif isinstance(data, list):
items = enumerate(data)
for key, value in items:
key = str(key)
if isinstance(value, (dict, list)):
for child_keys, child_value in _nested_form_data(value):
yield [key] + child_keys, child_value
else:
yield [key], value
def nested_form_data(data):
"""
Translates a nested dict structure into a flat form data dict
with hyphen-separated keys.
.. code-block:: python
nested_form_data({
'foo': 'bar',
'parent': {
'child': 'field',
},
})
# Returns: {'foo': 'bar', 'parent-child': 'field'}
"""
return {'-'.join(key): value for key, value in _nested_form_data(data)}
def streamfield(items):
"""
Takes a list of (block_type, value) tuples and turns it in to
StreamField form data. Use this within a :func:`nested_form_data`
call, with the field name as the key.
.. code-block:: python
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': '',
# }
"""
def to_block(index, item):
block, value = item
return {'type': block, 'value': value, 'deleted': '', 'order': index}
data_dict = {str(index): to_block(index, item)
for index, item in enumerate(items)}
data_dict['count'] = str(len(data_dict))
return data_dict
def 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 :func:`nested_form_data`
call, with the formset relation name as the key.
.. code-block:: python
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': '',
# }
"""
def to_form(index, item):
defaults = {
'ORDER': str(index),
'DELETE': '',
}
defaults.update(item)
return defaults
data_dict = {str(index): to_form(index, item)
for index, item in enumerate(items)}
data_dict.update({
'TOTAL_FORMS': str(len(data_dict)),
'INITIAL_FORMS': str(initial),
'MIN_NUM_FORMS': str(min),
'MAX_NUM_FORMS': str(max),
})
return data_dict