kopia lustrzana https://github.com/wagtail/wagtail
Add form data helpers
rodzic
0a634b0a42
commit
067c26f54d
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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': '',
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Ładowanie…
Reference in New Issue