Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make StreamfieldChooser blocks values nullable #396

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## Unreleased

### Changed

- Make value fields nullable on `PageChooserBlock`, `SnippetChooserBlock`, `DocumentChooserBlock` and `ImageChooserBlock` ([#396](https://github.com/torchbox/wagtail-grapple/pull/396))

## [0.25.1] - 2024-04-21

### Changed
Expand Down
8 changes: 4 additions & 4 deletions grapple/types/streamfield.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ def register_streamfield_blocks():
from .snippets import SnippetTypes

class PageChooserBlock(graphene.ObjectType):
page = graphene.Field(get_page_interface(), required=True)
page = graphene.Field(get_page_interface(), required=False)

class Meta:
interfaces = (StreamFieldInterface,)
Expand All @@ -445,7 +445,7 @@ def resolve_page(self, info, **kwargs):
return self.value.specific

class DocumentChooserBlock(graphene.ObjectType):
document = graphene.Field(get_document_type(), required=True)
document = graphene.Field(get_document_type(), required=False)

class Meta:
interfaces = (StreamFieldInterface,)
Expand All @@ -454,7 +454,7 @@ def resolve_document(self, info, **kwargs):
return self.value

class ImageChooserBlock(graphene.ObjectType):
image = graphene.Field(get_image_type(), required=True)
image = graphene.Field(get_image_type(), required=False)

class Meta:
interfaces = (StreamFieldInterface,)
Expand All @@ -474,7 +474,7 @@ def resolve_image(self, info, **kwargs):
if SnippetObjectType is not None:

class SnippetChooserBlock(graphene.ObjectType):
snippet = graphene.Field(SnippetObjectType, required=True)
snippet = graphene.Field(SnippetObjectType, required=False)

class Meta:
interfaces = (StreamFieldInterface,)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def test_schema_for_page_with_graphql_interface(self):
[{"name": "CustomInterface"}, {"name": "PageInterface"}],
)

def test_schem_for_snippet_with_graphql_interface(self):
def test_schema_for_snippet_with_graphql_interface(self):
results = self.introspect_schema_by_type("Advert")
self.assertListEqual(
sorted(results["data"]["__type"]["interfaces"], key=lambda x: x["name"]),
Expand Down
60 changes: 60 additions & 0 deletions tests/test_models_types.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import graphene

from django.test import TestCase
from wagtail.blocks.field_block import PageChooserBlock
from wagtail.documents.blocks import DocumentChooserBlock
from wagtail.images.blocks import ImageChooserBlock
from wagtail.snippets.blocks import SnippetChooserBlock

from grapple import registry
from grapple.actions import get_field_type
from grapple.exceptions import IllegalDeprecation
from grapple.models import (
Expand Down Expand Up @@ -183,3 +188,58 @@ def test_collection_field_required_deprecated(self):
required=True,
deprecation_reason=self.deprecation_reason,
)()


class ChooserBlocksTest(TestCase):
"""
Test that "Chooser" blocks take null values to ensure correct handling
of deleted objects referenced in these blocks.
"""

def test_snippet_chooser_block_value_field_not_required(self):
"""
Test that the SnippetChooserBlock snippet field is nullable in the
GraphQL schema.
"""
block = registry.registry.streamfield_blocks[SnippetChooserBlock]
field = block.snippet

# Check that field is not required by asserting type isn't `NonNull`
self.assertIsInstance(field, graphene.types.field.Field)
self.assertNotIsInstance(field.type, graphene.NonNull)

def test_document_chooser_block_value_field_not_required(self):
"""
Test that the DocumentChooserBlock document field is nullable in the
GraphQL schema.
"""
block = registry.registry.streamfield_blocks[DocumentChooserBlock]
field = block.document

# Check that field is not required by asserting type isn't `NonNull`
self.assertIsInstance(field, graphene.types.field.Field)
self.assertNotIsInstance(field.type, graphene.NonNull)

def test_image_chooser_block_value_field_not_required(self):
"""
Test that the ImageChooserBlock image field is nullable in the GraphQL
schema.
"""
block = registry.registry.streamfield_blocks[ImageChooserBlock]
field = block.image

# Check that field is not required by asserting type isn't `NonNull`
self.assertIsInstance(field, graphene.types.field.Field)
self.assertNotIsInstance(field.type, graphene.NonNull)

def test_page_chooser_block_value_field_not_required(self):
"""
Test that the PageChooserBlock page field is nullable in the GraphQL
schema.
"""
block = registry.registry.streamfield_blocks[PageChooserBlock]
field = block.page

# Check that field is not required by asserting type isn't `NonNull`
self.assertIsInstance(field, graphene.types.field.Field)
self.assertNotIsInstance(field.type, graphene.NonNull)
Loading