Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/nhsuk/wagtail-factories i…
Browse files Browse the repository at this point in the history
…nto dev
  • Loading branch information
Brad Morton committed Jun 19, 2023
2 parents 2e7b6ff + 1cc3381 commit 4f6dc17
Show file tree
Hide file tree
Showing 13 changed files with 245 additions and 64 deletions.
24 changes: 24 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,27 @@ Documentation is still in progress, but see the `tests`_ for more examples.
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')
Contributing
============

1. Clone the repo `git clone https://github.com/nhsuk/wagtail-streamfield-index.git`
2. Install dependencies `pip install .[testing,linting]`

If you are having issues in installing, it may be of use to use an environment tool
like [virtualenv](https://docs.python.org/3/library/venv.html)

Formatting
============

`black .`

Linting
============

`flake8 .`

Tests
============

`pytest`
14 changes: 8 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@

install_requires = [
'factory-boy>=2.8.0',
'wagtail>=2.0',
'wagtail>=5.0',
'flatdict>=3.0.1',
"Django==3.2.19",
]

docs_require = [
'sphinx>=1.4.0',
]

tests_require = [
'pytest==5.0.1',
'pytest-django==3.5.1',
'pytest-cov==2.7.1',
'pytest-pythonpath==0.7.3',
'pytest==6.2.2',
'pytest-django==4.1.0',
'pytest-cov==2.4.0',
'pytest-pythonpath==0.7.1',
'psycopg2>=2.3.1',
'coverage==4.5.3',

Expand All @@ -31,7 +33,7 @@

setup(
name='wagtail_factories',
version='2.0.0',
version='3.0.0',
description='Factory boy classes for wagtail',
long_description=long_description,
author="Michael van Tellingen",
Expand Down
3 changes: 2 additions & 1 deletion src/wagtail_factories/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .blocks import * # noqa
from .factories import * # noqa
from .wrapper import * # noqa

__version__ = "2.0.0"
__version__ = "3.0.0"
59 changes: 58 additions & 1 deletion src/wagtail_factories/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

import factory
from factory.declarations import ParameteredAttribute
from wagtail.core import blocks

from wagtail import blocks
from wagtail.images.blocks import ImageChooserBlock

from wagtail_factories.factories import ImageFactory
Expand All @@ -24,6 +25,8 @@ class StreamFieldFactory(ParameteredAttribute):
"""
Syntax:
<streamfield>__<index>__<block_name>__<key>='foo',
or
<streamfield>__<index>__<block_name>='foo',
Syntax to generate blocks with default factory values:
<streamfield>__<index>=<block_name>
Expand Down Expand Up @@ -89,9 +92,63 @@ def generate(self, step, params):
for index, index_params in sorted(result.items()):
item = subfactory(**index_params)
retval.append(item)

return retval


class StreamBlockSubFactory(factory.SubFactory):

def __call__(self, **kwargs):
return self.generate(None, kwargs)

def generate(self, step, params):
result = defaultdict(lambda: defaultdict(lambda: defaultdict()))
subfactory = self.get_factory()

for key, value in params.items():
parts = key.split('__', 2)
index = parts[0]
if index.isdigit():
index = int(index)
else:
continue

block_name = parts[1]

if len(parts) == 2:
result[index][block_name][block_name] = value
if len(parts) == 3:
param = parts[2]
result[index][block_name][block_name + "__" + param] = value

retval = []
for index, block_items in sorted(result.items()):
for block_name, block_params in block_items.items():
block_params['_block_name'] = block_name
step_builder = factory.builder.StepBuilder(
subfactory._meta,
block_params,
"build"
)
built = step_builder.build()
retval.append((block_name, built))

return blocks.StreamValue(subfactory._meta.model(), retval)


class StreamBlockFactory(factory.Factory):

@classmethod
def _build(cls, model_class, *args, **kwargs):
block = model_class()
block_name = kwargs['_block_name']
block_params = kwargs.get(block_name, None)
return block.to_python([{"type": block_name, "value": block_params}])[0].value

@classmethod
def _create(cls, model_class, *args, **kwargs):
return cls._build(model_class, *args, **kwargs)

class BlockFactory(factory.Factory):
class Meta:
abstract = True
Expand Down
22 changes: 2 additions & 20 deletions src/wagtail_factories/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,9 @@

import factory
from django.utils.text import slugify
from factory import errors, utils
from factory.declarations import ParameteredAttribute
from wagtail import VERSION as WAGTAIL_VERSION
from wagtail.core.models import Collection, Page, Site
from wagtail.images import get_image_model

try:
from factory.django import DjangoModelFactory
except ImportError:
from factory import DjangoModelFactory

if WAGTAIL_VERSION >= (2, 8):
from wagtail.documents import get_document_model
else:
from wagtail.documents.models import get_document_model

__all__ = ["CollectionFactory", "ImageFactory", "PageFactory", "SiteFactory", "DocumentFactory"]
logger = logging.getLogger(__file__)


class ParentNodeFactory(ParameteredAttribute):
from wagtail.models import Collection, Page, Site
from wagtail.images import get_image_model

EXTEND_CONTAINERS = True
FORCE_SEQUENCE = False
Expand Down
8 changes: 8 additions & 0 deletions src/wagtail_factories/wrapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from flatdict import FlatterDict


class DictToParameteredAttribute:

def __new__(self, factory, params):
flat_params = dict(FlatterDict(params, delimiter='__'))
return factory(**flat_params)
41 changes: 21 additions & 20 deletions tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
}
}

ROOT_URLCONF = "tests.urls"
ROOT_URLCONF = 'wagtail.test.urls'

SECRET_KEY = "Gx8sMKAtnA69TR9lyAlLuSnozUv3kxdscHkpwEjatZRVQQ0laMY69KL4XPxvr3KY"

Expand Down Expand Up @@ -64,25 +64,26 @@
] + INSTALLED_APPS
else:
INSTALLED_APPS = [
"wagtail.contrib.styleguide",
"wagtail.contrib.sitemaps",
"wagtail.contrib.routable_page",
"wagtail.contrib.frontend_cache",
"wagtail.contrib.search_promotions",
"wagtail.contrib.settings",
"wagtail.contrib.modeladmin",
"wagtail.contrib.table_block",
"wagtail.contrib.forms",
"wagtail.search",
"wagtail.embeds",
"wagtail.images",
"wagtail.sites",
"wagtail.users",
"wagtail.snippets",
"wagtail.documents",
"wagtail.admin",
"wagtail.api.v2",
"wagtail.core",
'wagtail.contrib.styleguide',
'wagtail.contrib.sitemaps',
'wagtail.contrib.routable_page',
'wagtail.contrib.frontend_cache',
'wagtail.contrib.search_promotions',
'wagtail.contrib.settings',
'wagtail.contrib.modeladmin',
'wagtail.contrib.table_block',
'wagtail.contrib.forms',

'wagtail.search',
'wagtail.embeds',
'wagtail.images',
'wagtail.sites',
'wagtail.users',
'wagtail.snippets',
'wagtail.documents',
'wagtail.admin',
'wagtail.api.v2',
'wagtail',
] + INSTALLED_APPS


Expand Down
85 changes: 83 additions & 2 deletions tests/test_blocks.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from collections import OrderedDict

import pytest
from wagtail.core.blocks import StructValue
from wagtail.core.rich_text import RichText

from wagtail_factories.wrapper import DictToParameteredAttribute


from wagtail.blocks import StructValue, StreamValue
from wagtail.images.models import Image

import wagtail_factories
Expand Down Expand Up @@ -97,6 +100,84 @@ def test_custom_page_streamfield_data_complex():
body__3__image__image__title="Blub",
body__4__richtext__value="This is some <strong>richtext</strong>",
)

assert Image.objects.count() == 1
image = Image.objects.first()

assert page.body.stream_data == [
('char_array', ['foo', 'bar']),
('struct', StructValue(None, [
('title', 'My Title'),
('item', StructValue(None, [
('label', 'my-label'),
('value', 100),
])),
('items', []),
('image', None),
])),
('int_array', [100]),
('image', image),
('stream', StreamValue(None, [
('title', 'Stream title'),
('subtitle', 'Stream subtitle'),
])),
('char', 'A char'),
('stream', StreamValue(None, [
('item', StructValue(None, [
('label', 'A deeply nested item'),
('value', 100),
]))
])),
]
content = str(page.body)
assert 'block-image' in content


@pytest.mark.django_db
def test_custom_page_streamfield_data_dict():
assert Image.objects.count() == 0

root_page = wagtail_factories.PageFactory(parent=None)
params = OrderedDict({
'parent': root_page,
'body': [
{
'char_array': [
'foo',
'bar',
],
},
{
'struct': {
'title': 'My Title',
'item': {
'value': 100,
},
'image': {
'image': None,
},
},
},
{
'int_array': [
100,
],
},
{
'image': {
'image': {
'title': 'Blub',
},
},
},
],
})

page = DictToParameteredAttribute(
MyTestPageWithStreamFieldFactory,
params=params
)

assert Image.objects.count() == 1
image = Image.objects.first()

Expand Down
3 changes: 2 additions & 1 deletion tests/test_factories.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest
from wagtail.core.models import Page, Site

from wagtail.models import Page, Site

import wagtail_factories
from tests.testapp.factories import MyTestPageFactory, MyTestPageGetOrCreateFactory
Expand Down
16 changes: 16 additions & 0 deletions tests/testapp/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ class Meta:
django_get_or_create = ["slug", "parent"]


class MyStreamBlockFactory(wagtail_factories.StreamBlockFactory):

title = "Char block"
subtitle = "Another char block"
item = factory.SubFactory(MyBlockItemFactory)

class Meta:
model = models.MyStreamBlock


class MyCharBlockFactory(wagtail_factories.CharBlockFactory):

class Meta:
model = models.MyCharBlock


class MyTestPageWithStreamFieldFactory(wagtail_factories.PageFactory):

body = wagtail_factories.StreamFieldFactory(
Expand Down
6 changes: 2 additions & 4 deletions tests/testapp/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@
import django.db.models.deletion
from django.db import migrations, models

try:
from wagtail.wagtailcore import blocks, fields
except ImportError:
from wagtail.core import blocks, fields

from wagtail import blocks, fields


class Migration(migrations.Migration):
Expand Down
Loading

0 comments on commit 4f6dc17

Please sign in to comment.