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.5.0.tar.gz (10.1 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.5.0-py3-none-any.whl (10.8 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for wagtail_factories-4.5.0.tar.gz
Algorithm Hash digest
SHA256 d981ceaaf7715b2325f9debb1be1ffc07e338ae8957e9527f4f9175fcdff2c56
MD5 7433942a7e6c1cc84a31d9f120c3239b
BLAKE2b-256 0cb80a6e91ea32467acd96c5769face88c6ac79f2f0990f822d7396d054bbc15

See more details on using hashes here.

File details

Details for the file wagtail_factories-4.5.0-py3-none-any.whl.

File metadata

File hashes

Hashes for wagtail_factories-4.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4ad0e9f396fca7f7d349a8752c49f68e18deeffee9c857897b849ff08c6c33a6
MD5 6fa92d2ed8fd817cc23a1250487aec5f
BLAKE2b-256 8f1836e0be763870e22b1f0f87361cc768a7bfcc842f6504a6bafdddf932fd7d

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