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

Feature/4717 accessibility improvements aria #4747

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
32 changes: 32 additions & 0 deletions src/openforms/formio/rendering/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ def is_visible(self) -> bool:
return True


@register("textfield")
class TextNode(ComponentNode):
@property
def value_list(self):
return super().value


@register("selectboxes")
@register("radio")
class ChoicesNode(ComponentNode):
Expand All @@ -69,6 +76,23 @@ def apply_to_labels(self, f: Callable[[str], str]) -> None:
for choice in self.component["values"]:
choice["label"] = f(choice["label"])

@property
def value_list(self):
if not self.component["type"] == "selectboxes":
return super().display_value

values = []
for value, isSelected in super().value.items():
if isSelected:
value_to_add = value
# Search the label for the value
for choice in self.component["values"]:
if choice["value"] == value:
value_to_add = choice["label"]

values.append(value_to_add)
return values


@register("select")
class SelectNode(ComponentNode):
Expand All @@ -77,6 +101,14 @@ def apply_to_labels(self, f: Callable[[str], str]) -> None:
for choice in self.component["data"]["values"]:
choice["label"] = f(choice["label"])

@property
def value_list(self) -> list:
values = []
for choice in self.component["data"]["values"]:
if choice["value"] in super().value:
values.append(choice["label"])
return values


@register("fieldset")
class FieldSetNode(ContainerMixin, ComponentNode):
Expand Down
219 changes: 219 additions & 0 deletions src/openforms/formio/rendering/tests/test_list_components.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
from unittest.mock import patch

from django.test import TestCase

from openforms.submissions.rendering import Renderer, RenderModes
from openforms.submissions.tests.factories import SubmissionFactory

from ..default import ChoicesNode, SelectNode, TextNode
from ..nodes import ComponentNode
from ..registry import Registry


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

config = {
"components": [
{
"type": "selectboxes",
"key": "selectboxes",
"label": "Selectboxes",
"values": [
{
"value": "option1",
"label": "Option 1",
},
{
"value": "option2",
"label": "Option 2",
},
{
"value": "option3",
"label": "Option 3",
},
],
},
{
"type": "radio",
"key": "radio",
"label": "Radio",
"values": [
{
"value": "option1",
"label": "Option 1",
},
{
"value": "option2",
"label": "Option 2",
},
],
},
{
"type": "select",
"key": "select-single",
"label": "Select single",
"multiple": False,
"openForms": {
"dataSrc": "manual",
},
"data": {
"values": [
{"label": "Option 1", "value": "option1"},
{"label": "Option 2", "value": "option2"},
]
},
},
{
"type": "select",
"key": "select-multiple",
"label": "Select multiple",
"multiple": True,
"openForms": {
"dataSrc": "manual",
},
"data": {
"values": [
{
"label": "Option 1",
"value": "option1",
},
{
"label": "Option 2",
"value": "option2",
},
{
"label": "Option 3",
"value": "option3",
},
]
},
},
{
"type": "textfield",
"key": "textfield",
"label": "Textfield",
"multiple": True,
},
]
}
data = {
"selectboxes": {"option1": True, "option2": True},
"radio": "option1",
"select-single": "option1",
"select-multiple": ["option2", "option3"],
"textfield": ["Foo", "Bar"],
}

submission = SubmissionFactory.from_components(
components_list=config["components"], submitted_data=data
)

# expose test data to test methods
cls.submission = submission
cls.step = submission.steps[0]

def test_render_mode_pdf(self):
renderer = Renderer(self.submission, mode=RenderModes.pdf, as_html=True)
# set up mock registry without special fieldset/editgrid behaviour
register = Registry()

nodelist = []
with patch("openforms.formio.rendering.registry.register", new=register):
for component in self.step.form_step.form_definition.configuration[
"components"
]:
if component["type"] == "selectboxes" or component["type"] == "radio":
component_node = ChoicesNode(
step_data=self.step.data, component=component, renderer=renderer
)
elif component["type"] == "select":
component_node = SelectNode(
step_data=self.step.data, component=component, renderer=renderer
)
elif component["type"] == "textfield":
component_node = TextNode(
step_data=self.step.data, component=component, renderer=renderer
)
nodelist += list(component_node)

self.assertEqual(len(nodelist), 5)
labels = [node.label for node in nodelist]
expected_labels = [
"Selectboxes",
"Radio",
"Select single",
"Select multiple",
"Textfield",
]
self.assertEqual(labels, expected_labels)

values = [node.value_list for node in nodelist]
expected_values = [
["Option 1", "Option 2"],
"Option 1",
["Option 1"],
["Option 2", "Option 3"],
["Foo", "Bar"],
]
self.assertEqual(values, expected_values)

def test_render_mode_summary(self):
# NOTE the summary renders as text but some like the 'content' component render html
renderer = Renderer(self.submission, mode=RenderModes.summary, as_html=False)
# set up mock registry without special fieldset/editgrid behaviour
register = Registry()

nodelist = []
with patch("openforms.formio.rendering.registry.register", new=register):
for component in self.step.form_step.form_definition.configuration[
"components"
]:
component_node = ComponentNode.build_node(
step_data=self.step.data, component=component, renderer=renderer
)
nodelist += list(component_node)

# self.assertEqual(len(nodelist), 11)
labels = [node.label for node in nodelist]
expected_labels = [
"Input 1",
"Input 3",
"Input 5",
"Input 5.1",
"A container without visible children",
"A container with visible children",
"Input 9",
"Visible editgrid with visible children",
"Input 11",
"Visible editgrid with hidden children",
"Input 14",
]
self.assertEqual(labels, expected_labels)

def test_render_mode_confirmation_email(self):
renderer = Renderer(
self.submission, mode=RenderModes.confirmation_email, as_html=True
)
# set up mock registry without special fieldset behaviour
register = Registry()

nodelist = []
with patch("openforms.formio.rendering.registry.register", new=register):
for component in self.step.form_step.form_definition.configuration[
"components"
]:
component_node = ComponentNode.build_node(
step_data=self.step.data, component=component, renderer=renderer
)
nodelist += list(component_node)

self.assertEqual(len(nodelist), 2)
labels = [node.label for node in nodelist]
expected_labels = [
"Input 3",
"Input 6",
]
self.assertEqual(labels, expected_labels)
2 changes: 1 addition & 1 deletion src/openforms/js/components/errors/ErrorMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {ErrorIcon} from 'components/admin/icons';
const ErrorMessage = ({children}) => {
if (!children) return null;
return (
<div className="error-message">
<div className="error-message" role="alert">
<span className="error-message__icon icon icon--danger icon--as-lead">
<ErrorIcon text="error" />
</span>
Expand Down
1 change: 1 addition & 0 deletions src/openforms/scss/pdfs/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// specific content styling
@import 'header';
@import 'metadata';
@import 'sr-only';
@import 'submission-step';
@import 'submission-step-row';
@import 'payment-info';
Expand Down
11 changes: 11 additions & 0 deletions src/openforms/scss/pdfs/_sr-only.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.sr-only {
position: absolute !important;
width: 1px !important;
height: 1px !important;
padding: 0 !important;
margin: -1px !important;
overflow: hidden !important;
clip: rect(0, 0, 0, 0) !important;
white-space: nowrap !important;
border: 0 !important;
}
15 changes: 13 additions & 2 deletions src/openforms/submissions/templates/report/submission_report.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@
<span
class="header__logo"
{% if theme.logo %}role="img"{% endif %}
></span>
>
<span class="sr-only">{% blocktrans with organization_name=config.organization_name trimmed %}
Logo {{ organization_name }}
{% endblocktrans %}</span>
</span>
</header>

<h1 class="title">{{ report.form.name }}</h1>
Expand Down Expand Up @@ -63,7 +67,14 @@ <h2 class="subtitle">{{ submission_step_node.render }}</h2>
</div>

<div class="submission-step-row__value{% if not component_node.display_value %} submission-step-row__value--empty{% endif %}">
{{ component_node.display_value|default:"" }}
{% if not component_node.display_value %}
{% elif component_node.component.type == "textfield" and component_node.component.multiple %}
{% include 'report/submission_report_node_list.html' with values=component_node.value_list %}
{% elif component_node.component.type == "selectboxes" or component_node.component.type == "select" %}
{% include 'report/submission_report_node_list.html' with values=component_node.value_list %}
{% else %}
{{ component_node.display_value|default:"" }}
{% endif %}
</div>
{% endif %}
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<ul>
{% for value in values %}
<li>{{ value }}</li>
{% endfor %}
</ul>
8 changes: 7 additions & 1 deletion src/openforms/submissions/tests/test_submission_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,13 @@ def test_report_is_generated_in_same_language_as_submission(self):

for component_type, localised_input in fields:
with self.subTest(f"FormIO label for {component_type}"):
self.assertIn(localised_input, html_report)
if component_type == "selectboxes":
values = localised_input.split("; ")
for value in values:
self.assertIn(value, html_report)
else:
self.assertIn(localised_input, html_report)

self.assertNotIn(
f"Untranslated {component_type.title()} label", html_report
)
Expand Down
Loading
Loading