Skip to main content

Factory boy classes for wagtail

Project description

wagtail-factories

Factory boy classes for Wagtail CMS

Installation

pip install wagtail-factories

Usage

Documentation is still in progress, but see the tests for more examples.

import wagtail_factories
from wagtail import models as wt_models

from . import models


class MyCarouselItemFactory(wagtail_factories.StructBlockFactory):
    label = 'my-label'
    image = factory.SubFactory(
        wagtail_factories.ImageChooserBlockFactory)

    class Meta:
        model = models.MyBlockItem


class MyCarouselFactory(wagtail_factories.StructBlockFactory):
    title = "Carousel title"
    items = wagtail_factories.ListBlockFactory(
        MyCarouselItemFactory)

    class Meta:
        model = models.MyCarousel


class MyNewsPageFactory(wagtail_factories.PageFactory):
    class Meta:
        model = models.MyNewsPage


class MyNewsPageChooserBlockFactory(wagtail_factories.PageChooserBlockFactory):
    page = factory.SubFactory(MyNewsPageFactory)


class MyTestPageFactory(wagtail_factories.PageFactory):
    body = wagtail_factories.StreamFieldFactory({
        'carousel': factory.SubFactory(MyCarouselFactory),
        'news_page': factory.SubFactory(MyNewsPageChooserBlockFactory),
    })

    class Meta:
        model = models.MyTestPage


def test_my_page():
    root_page = wt_models.Page.get_first_root_node()
    assert root_page is not None

    my_page = MyTestPageFactory(
        parent=root_page,
        title="My great page",
        body__0__carousel__items__0__label='Slide 1',
        body__0__carousel__items__0__image__image__title='Image Slide 1',
        body__0__carousel__items__1__label='Slide 2',
        body__0__carousel__items__1__image__image__title='Image Slide 2',
        body__0__carousel__items__2__label='Slide 3',
        body__0__carousel__items__2__image__image__title='Image Slide 3',
        body__1__news_page__page__title="News",
    )

    # Defaults defined on factory classes are propagated.
    assert my_page.body[0].value["title"] == "Carousel title"

    # Parameters are propagated.
    assert my_page.title == "My great page"
    assert my_page.body[0].value["items"][0].value["label"] == "Slide 1"

Using StreamBlockFactory

StreamBlockFactory can be used in conjunction with the other block factory types to create complex, nested StreamValues, much like how StreamBlock can be used to declare the blocks for a complex StreamField.

First, define your StreamBlockFactory subclass, using factory.SubFactory to wrap child block declarations. Be sure to include your StreamBlock subclass as the model attribute on the inner Meta class.

class MyStreamBlockFactory(wagtail_factories.StreamBlockFactory):
    my_struct_block = factory.SubFactory(MyStructBlockFactory)

    class Meta:
        model = MyStreamBlock

Then include your StreamBlockFactory subclass on a model factory as the argument to a StreamFieldFactory.

class MyPageFactory(wagtail_factories.PageFactory):
    body = wagtail_factories.StreamFieldFactory(MyStreamBlockFactory)

    class Meta:
        model = MyPage

You can then use a modified version of factory_boy's deep object declaration syntax to build up StreamValues on the fly.

MyPageFactory(
    body__0__my_struct_block__some_field="some value",
    body__0__my_struct_block__some_other_field="some other value",
)

To generate the default value for a block factory, terminate your declaration at the index and provide the block name as the value.

MyPageFactory(body__0="my_struct_block")

Alternative StreamFieldFactory declaration syntax

Prior to version 3.0, StreamFieldFactory could only be used by providing a dict mapping block names to block factory classes as the single argument, for example:

class MyTestPageWithStreamFieldFactory(wagtail_factories.PageFactory):
    body = wagtail_factories.StreamFieldFactory(
        {
            "char_array": wagtail_factories.ListBlockFactory(
                wagtail_factories.CharBlockFactory
            ),
            "int_array": wagtail_factories.ListBlockFactory(
                wagtail_factories.IntegerBlockFactory
            ),
            "struct": MyBlockFactory,
            "image": wagtail_factories.ImageChooserBlockFactory,
        }
    )

    class Meta:
        model = models.MyTestPage

This style of declaration is still supported, with the caveat that nested stream blocks are not supported for this approach. From version 3.0, all BlockFactory values in a StreamFieldFactory definition of this style must be wrapped in factory_boy SubFactories. For example, the above example must be updated to the following for 3.0 compatibility.

class MyTestPageWithStreamFieldFactory(wagtail_factories.PageFactory):
    body = wagtail_factories.StreamFieldFactory(
        {
            "char_array": wagtail_factories.ListBlockFactory(
                wagtail_factories.CharBlockFactory
            ),
            "int_array": wagtail_factories.ListBlockFactory(
                wagtail_factories.IntegerBlockFactory
            ),
            "struct": factory.SubFactory(MyBlockFactory),
            "image": factory.SubFactory(wagtail_factories.ImageChooserBlockFactory),
        }
    )

    class Meta:
        model = models.MyTestPage

This requirement does not apply to ListBlockFactory, which is a subclass of SubFactory.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wagtail_factories-4.4.0.tar.gz (9.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wagtail_factories-4.4.0-py2.py3-none-any.whl (10.8 kB view details)

Uploaded Python 2Python 3

File details

Details for the file wagtail_factories-4.4.0.tar.gz.

File metadata

  • Download URL: wagtail_factories-4.4.0.tar.gz
  • Upload date:
  • Size: 9.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wagtail_factories-4.4.0.tar.gz
Algorithm Hash digest
SHA256 c77c13d438a2e999a9220ff1829f060116013aa519a81944577353f460ba8cba
MD5 667e0b994eda1f42a9f999d0f711582b
BLAKE2b-256 428c2ece22c2757bb3f6ef34f36cf185246b136134cf594b7b1dde92cb0a331f

See more details on using hashes here.

File details

Details for the file wagtail_factories-4.4.0-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for wagtail_factories-4.4.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 be0abb96d36bf0e3c733d7520fc1944441a379ab06d93af447fc4e71b67e2a01
MD5 6d482f96d5a8534d0129e400454abfb2
BLAKE2b-256 4c85bd5aeaa54a10b6defca927f75bc3890acb7c3a9a23df8e10f3aa42e75807

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page