Skip to content

Commit

Permalink
✅ [#1451] -- add tests for ComponentNode generic behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
sergei-maertens committed Apr 29, 2022
1 parent c56d06a commit 1c275dd
Show file tree
Hide file tree
Showing 2 changed files with 280 additions and 7 deletions.
21 changes: 14 additions & 7 deletions src/openforms/formio/rendering/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,25 @@ def is_visible(self) -> bool:
"""
from .conf import RENDER_CONFIGURATION # circular import

# everything is emitted in export mode to get consistent columns
if self.mode == RenderModes.export:
return True

# explicitly hidden components never show up. Note that this property can be set
# by form logic!
if self.component.get("hidden") is True:
return False

render_configuration = RENDER_CONFIGURATION[self.renderer.mode]
render_configuration = RENDER_CONFIGURATION[self.mode]
# it's possible the end-user cannot explicitly configure the visibility, in
# which case the system default is used.
if render_configuration.attribute is None:
if render_configuration.key is None:
return render_configuration.default

# if there is an attribute, try to read it but fall back to the system default
# if there is a property key, try to read it but fall back to the system default
# if it's absent.
should_render = self.component.get(
render_configuration.attribute, render_configuration.default
render_configuration.key, render_configuration.default
)
return should_render

Expand Down Expand Up @@ -130,7 +134,10 @@ def __iter__(self) -> Iterator["ComponentNode"]:
if not self.is_visible:
return

yield self
# in export mode, only emit if there's a 'key' property
if self.mode != RenderModes.export or "key" in self.component:
yield self

for child in self.get_children():
if not child.is_visible:
continue
Expand All @@ -148,7 +155,7 @@ def label(self) -> str:
"""
Obtain the (human-readable) label for the Formio component.
"""
if self.renderer.mode == RenderModes.export:
if self.mode == RenderModes.export:
return self.component.get("key") or "KEY_MISSING"
return self.component.get("label") or self.component.get("key", "")

Expand All @@ -161,7 +168,7 @@ def display_value(self) -> Union[str, Any]:
component type, using :func:`openforms.formio.formatter.service.format_value`.
"""
# in export mode, expose the raw datatype
if self.renderer.mode == RenderModes.export:
if self.mode == RenderModes.export:
return self.value
return format_value(self.component, self.value, as_html=self.renderer.as_html)

Expand Down
266 changes: 266 additions & 0 deletions src/openforms/formio/rendering/tests/test_component_node.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
from unittest.mock import patch

from django.test import TestCase

from openforms.forms.tests.factories import FormFactory
from openforms.submissions.rendering import Renderer, RenderModes
from openforms.submissions.tests.factories import (
SubmissionFactory,
SubmissionStepFactory,
)

from ..constants import RenderConfigurationOptions
from ..nodes import ComponentNode
from ..registry import Registry

# from rest_framework.reverse import reverse


class FormNodeTests(TestCase):
@classmethod
def setUpTestData(cls):
super().setUpTestData()

form = FormFactory.create(
name="public name",
internal_name="internal name",
generate_minimal_setup=True,
formstep__form_definition__configuration={
"components": [
# visible component, leaf node
{
"type": "textfield",
"key": "input1",
"label": "Input 1",
"hidden": False,
},
# hidden component, leaf node
{
"type": "textfield",
"key": "input2",
"label": "Input 2",
"hidden": True,
},
# visible in PDF and confirmation email component, leaf node
{
"type": "textfield",
"key": "input3",
"label": "Input 3",
"hidden": False,
RenderConfigurationOptions.show_in_pdf: True,
RenderConfigurationOptions.show_in_confirmation_email: True,
},
# hidden in PDF and confirmation email component, leaf node
{
"type": "textfield",
"key": "input4",
"label": "Input 4",
"hidden": False,
RenderConfigurationOptions.show_in_pdf: False,
RenderConfigurationOptions.show_in_confirmation_email: False,
},
# visible in PDF and hidden in confirmation email component, leaf node
{
"type": "textfield",
"key": "input5",
"label": "Input 5",
"hidden": False,
RenderConfigurationOptions.show_in_pdf: True,
RenderConfigurationOptions.show_in_confirmation_email: False,
},
# hidden in PDF and visible in confirmation email component, leaf node
{
"type": "textfield",
"key": "input6",
"label": "Input 6",
"hidden": False,
RenderConfigurationOptions.show_in_pdf: False,
RenderConfigurationOptions.show_in_confirmation_email: True,
},
# container: visible fieldset without visible children
{
"type": "fieldset",
"label": "A container without visible children",
"hidden": False,
"components": [
{
"type": "textfield",
"key": "input7",
"label": "Input 7",
"hidden": True,
}
],
},
# container: visible fieldset with visible children
{
"type": "fieldset",
"label": "A container with visible children",
"hidden": False,
"components": [
{
"type": "textfield",
"key": "input8",
"label": "Input 8",
"hidden": True,
},
{
"type": "textfield",
"key": "input9",
"label": "Input 9",
"hidden": False,
},
],
},
# container: hidden fieldset with 'visible' children
{
"type": "fieldset",
"label": "A hidden container with visible children",
"hidden": True,
"components": [
{
"type": "textfield",
"key": "input10",
"label": "Input 10",
"hidden": False,
}
],
},
# TODO container: columns
]
},
)

submission = SubmissionFactory.create(form=form)
step = SubmissionStepFactory.create(
submission=submission,
form_step=form.formstep_set.get(),
data={
"input1": "aaaaa",
"input2": "bbbbb",
"input3": "ccccc",
"input4": "ddddd",
"input5": "eeeee",
"input6": "fffff",
"input7": "ggggg",
"input8": "hhhhh",
"input9": "iiiii",
},
)

# expose test data to test methods
cls.submission = submission
cls.step = step

def test_generic_node_builder(self):
"""
Assert that ComponentNode.build_node produces node instances.
"""
# we always need a renderer instance
renderer = Renderer(self.submission, mode=RenderModes.pdf, as_html=False)
# take a simple component
component = self.step.form_step.form_definition.configuration["components"][0]
assert component["key"] == "input1"

component_node = ComponentNode.build_node(
step=self.step, component=component, renderer=renderer
)

self.assertIsInstance(component_node, ComponentNode)
self.assertEqual(component_node.depth, 0)
self.assertTrue(component_node.is_visible)
self.assertEqual(component_node.value, "aaaaa")
self.assertEqual(component_node.display_value, "aaaaa")
self.assertEqual(component_node.label, "Input 1")
self.assertEqual(list(component_node.get_children()), [])
nodelist = list(component_node)
self.assertEqual(nodelist, [component_node])
self.assertEqual(component_node.render(), "Input 1: aaaaa")

def test_generic_node_builder_specific_subclasses(self):
# set up mock registry and component class for test
register = Registry()

@register("textfield")
class TextFieldNode(ComponentNode):
pass

# we always need a renderer instance
renderer = Renderer(self.submission, mode=RenderModes.pdf, as_html=False)
# take a simple component
component = self.step.form_step.form_definition.configuration["components"][0]
assert component["key"] == "input1"

with patch("openforms.formio.rendering.registry.register", new=register):
component_node = ComponentNode.build_node(
step=self.step, component=component, renderer=renderer
)

self.assertIsInstance(component_node, TextFieldNode)

def test_explicitly_hidden_component_skipped(self):
# we always need a renderer instance
renderer = Renderer(self.submission, mode=RenderModes.pdf, as_html=False)

with self.subTest("Simple hidden leaf component"):
component = self.step.form_step.form_definition.configuration["components"][
1
]
assert component["key"] == "input2"
assert component["hidden"]

component_node = ComponentNode.build_node(
step=self.step, component=component, renderer=renderer
)

nodelist = list(component_node)

self.assertEqual(nodelist, [])

with self.subTest("Nested hidden component"):
fieldset = self.step.form_step.form_definition.configuration["components"][
6
]
assert not fieldset["hidden"]

# set up mock registry and component class for test
register = Registry()

with patch("openforms.formio.rendering.registry.register", new=register):
component_node = ComponentNode.build_node(
step=self.step, component=fieldset, renderer=renderer
)

nodelist = list(component_node)

self.assertEqual(len(nodelist), 1)
self.assertEqual(nodelist[0].label, "A container without visible children")

def test_export_always_emits_all_nodes(self):
renderer = Renderer(self.submission, mode=RenderModes.export, as_html=False)

nodelist = []
for component in self.step.form_step.form_definition.configuration[
"components"
]:
component_node = ComponentNode.build_node(
step=self.step, component=component, renderer=renderer
)
nodelist += list(component_node)

self.assertEqual(len(nodelist), 10)
labels = [node.label for node in nodelist]
self.assertEqual(
labels,
[
"input1",
"input2",
"input3",
"input4",
"input5",
"input6",
"input7",
"input8",
"input9",
"input10",
],
)

0 comments on commit 1c275dd

Please sign in to comment.