I am trying to test pages in wagtail. Creating a page like I did below works for pages without a streamfield.
blogPage = BlogPage(title="Test Blog",path="test-blog", excerpt=rich_text("<p>This is an excerpt </p>"), body=[{"id": "07a1f0b6-0023-45a3-83a0-38cb6a7893f1", "type": "heading", "value": "test heading"}])
root_page = Page.objects.get(id=2)
root_page.add_child(instance=blogPage)
root_page.save()
But when I try to create a page with a streamfield (body) when I run tests assertPageIsPreviewable and assertPageIsEditable I get an error AssertionError: Failed to load preview for BlogPage "Test Blog" with mode="": 'body-count'
.
I could not find any documentation explaining how to programmatically create new pages in wagtail with a streamfield block. I was however able to find some documentation explaining how to use
nested_form_data({'data': streamfield([('heading', 'test heading'),])})
but setting
blogPage = BlogPage(title="Test Blog",path="test-blog", excerpt=rich_text("<p>This is an excerpt </p>"), body=nested_form_data({'body': streamfield([('heading', 'test heading'),])}))
doesn't work and setting it to
blogPage = BlogPage(title="Test Blog",path="test-blog", excerpt=rich_text("<p>This is an excerpt </p>"), body=streamfield([('heading', 'test heading'),]))
doesn't either work. I was finally able to find docs of how to do this in wagtail latest documentation https://docs.wagtail.org/en/latest/advanced_topics/testing.html#working-with-page-content so I tried:
blogPage = BlogPage(title="Test Blog",path="test-blog", excerpt=rich_text("<p>This is an excerpt </p>"))
blogPage.body.extend([('heading', "test heading")])
blogPage.save()
root_page = Page.objects.get(id=2)
root_page.add_child(instance=blogPage)
root_page.save()
and
blogPage = BlogPage(title="Test Blog",path="test-blog", excerpt=rich_text("<p>This is an excerpt </p>"))
root_page = Page.objects.get(id=2)
root_page.add_child(instance=blogPage)
root_page.save()
blogPage.body.extend([('heading', "test heading")])
blogPage.save()
Neither of these worked. What is the correct way to create pages in wagtail with streamfield for testing. I do not want to use fixtures. I found this question on stackoverflow and tried this solution but it doesn't work either.
class BlogTestCase(WagtailPageTestCase):
@classmethod
def setUpTestData(cls):
cls.blogPage = BlogPage(title="Test Blog",path="test-blog", excerpt=rich_text("<p>This is an excerpt </p>"))
cls.blogPage.body.extend([('heading', "test heading")])
cls.blogPage.save()
root_page = Page.objects.get(id=2)
root_page.add_child(instance=cls.blogPage)
root_page.save()
def test_is_previewable(self):
self.assertPageIsPreviewable(self.blogPage)
def test_is_editable(self):
self.assertPageIsEditable(self.blogPage)
assertPageIsPreviewable
and assertPageIsEditable
work by making a POST request to the edit page view, and checking that it returns a non-error response. These methods give you the option of supplying the body of the POST request - if you omit this, it will attempt to obtain a suitable POST body by making a GET request (which returns the edit form) and extracting the form data from the HTML. However, this won't work if the form contains a StreamField, because the editing interface for a StreamField is generated through Javascript, and isn't part of the HTML as rendered by the server. As a result, the shortcut of leaving out the POST data isn't available.
The nested_form_data
, rich_text
, streamfield
and inline_formset
helpers provided in wagtail.test.utils.form_data
are intended specifically for building up a POST body in the format required - you should not use these when working directly with the BlogPage object, which means that
blogPage = BlogPage(body=nested_form_data(...))
is invalid. Passing excerpt=rich_text("...")
is also invalid, although this is probably benign - it'll just mean that your excerpt
will be set to a string of JSON text rather than something HTML-like. excerpt="<p>This is an excerpt</p>"
would be correct here.
The final versions of your code, where you're passing a list of (block type, value) tuples to body.extend
, are the correct way of building up StreamField content on a page object. (Note that you can't call blogPage.save()
until you've added it to the page tree with root_page.add_child(instance=blogPage)
, and in fact add_child
will have the effect of saving blogPage
too, so you don't need to do both.)
However, given the above-mentioned limitations of assertPageIsPreviewable
and assertPageIsEditable
, you'll end up having to supply this data in the format of a POST submission anyhow, and this will overwrite any setup you perform up-front on the blog page object, so it's a bit of a moot point.
Using the POST-data helpers in wagtail.test.utils.form_data
, your final code should come out as (untested):
class BlogTestCase(WagtailPageTestCase):
@classmethod
def setUpTestData(cls):
cls.blogPage = BlogPage(title="Test Blog", slug="test-blog", excerpt="<p>This is an excerpt</p>")
root_page = Page.objects.get(id=2)
root_page.add_child(instance=cls.blogPage)
root_page.save()
cls.post_data = nested_form_data({
"title": "Test blog",
"slug": "test blog",
"excerpt": rich_text("<p>This is an excerpt</p>"),
"body": streamfield([
('heading', "test heading"),
]),
})
def test_is_previewable(self):
self.assertPageIsPreviewable(self.blogPage, post_data=self.post_data)
def test_is_editable(self):
self.assertPageIsEditable(self.blogPage, post_data=self.post_data)