diff --git a/docs/developers/backend/core/testing-tools.rst b/docs/developers/backend/core/testing-tools.rst
index 58e785f1ca..335187c8d6 100644
--- a/docs/developers/backend/core/testing-tools.rst
+++ b/docs/developers/backend/core/testing-tools.rst
@@ -4,9 +4,32 @@
Test helpers
============
-HTML assertions
+Open Forms tests are built with the core Django testing helpers defined in
+:mod:`django.test`, extended with some third party libraries and project-specific
+helpers.
+
+.. contents:: Helpers
+ :depth: 3
+ :local:
+ :backlinks: entry
+
+Third party packages
+====================
+
+* `django-webtest `_: acts more like a browser
+ without being a full-blown browser. Very useful for admin tests, especially when
+ combined with `pyquery `_.
+* `hypothesis `_: property based testing, very
+ good for generating fuzzy data to catch edge cases you never would think of. See
+ :ref:`developers_backend_core_testing_tools_hypothesis_strategies`.
+
+
+Project helpers
===============
+HTML assertions
+---------------
+
.. automodule:: openforms.utils.tests.html_assert
:members:
@@ -14,26 +37,45 @@ HTML assertions
:members:
Frontend redirects
-==================
+------------------
.. automodule:: openforms.frontend.tests
:members:
Migrations
-==========
+----------
.. automodule:: openforms.utils.tests.test_migrations
:members:
Formio assertions
-=================
+-----------------
.. automodule:: openforms.formio.tests.assertions
:members:
:undoc-members:
Recording HTTP traffic
-======================
+----------------------
.. automodule:: openforms.utils.tests.vcr
:members:
+
+.. _developers_backend_core_testing_tools_hypothesis_strategies:
+
+Custom Hypothesis strategies
+----------------------------
+
+General purpose strategies
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. automodule:: openforms.tests.search_strategies
+ :members:
+ :undoc-members:
+
+Formio component strategies
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. automodule:: openforms.formio.tests.search_strategies
+ :members:
+ :undoc-members:
diff --git a/docs/developers/backend/tests.rst b/docs/developers/backend/tests.rst
index 1d4f341056..5d3696fe92 100644
--- a/docs/developers/backend/tests.rst
+++ b/docs/developers/backend/tests.rst
@@ -7,6 +7,9 @@ Running tests
The Open Forms backend comes with an extensive test suite to prevent regressions and
also describe intended behaviour.
+.. tip:: See the :ref:`developers_backend_core_testing_tools` for a collection of
+ utilities that you can use when writing tests.
+
Running the backend tests
=========================
diff --git a/docs/developers/index.rst b/docs/developers/index.rst
index be52c367e8..c46a93cfd8 100644
--- a/docs/developers/index.rst
+++ b/docs/developers/index.rst
@@ -31,7 +31,6 @@ familiarize yourself with the design principles.
extending
extensions
checklists
- manual_testing
i18n
csp
npm
diff --git a/docs/developers/manual_testing.rst b/docs/developers/manual_testing.rst
deleted file mode 100644
index 12a1651ce7..0000000000
--- a/docs/developers/manual_testing.rst
+++ /dev/null
@@ -1,42 +0,0 @@
-.. _developers_manual_testing:
-
-==============
-Manual testing
-==============
-
-Certain (UI) functionalities are not easily tested automatically. To prevent regressions,
-the following test scenario's should be checked for a new build.
-
-Form builder tests
-==================
-
-The form builder is the core tool used by content editors to design the forms to be
-rendered by the SDK. It uses formio.js under the hood, with custom field types added.
-These custom field types should be verified to be functional.
-
-1. Navigate to the admin. Then go to **Formulieren > Form definitions**. Next, click
- **form definition toevoegen**.
-
-2. Verify that the following components are present under the label **Configuration**,
- and can be added to the form builder by dragging it to the right:
-
- * Section *Formuliervelden*:
-
- * Text Field
- * IBAN Field
- * Text Area
- * Number
- * Checkbox
- * Select boxes
- * Select
- * Currency
- * Radio
-
- * Section *Opmaak*
-
- * Content
- * Field Set
-
- * Section *Basisregistratie Personen*
-
- * Gezinsleden
diff --git a/docs/developers/npm.rst b/docs/developers/npm.rst
index 27619374cc..f7c9cfc4e8 100644
--- a/docs/developers/npm.rst
+++ b/docs/developers/npm.rst
@@ -14,7 +14,8 @@ Note that we have "two frontends":
Common tooling
==============
-The common tooling applies to both Open Forms and the SDK.
+The common tooling applies to Open Forms, the SDK and the supporting libraries like
+the formio-builder and types repository.
**NVM**
@@ -38,6 +39,23 @@ formatting when a ``.prettierrc.json`` config file is available.
Currently, Prettier is configured to format ``.js`` and ``.scss`` files.
+**Storybook**
+
+All projects/libraries have a Storybook for the UI components. When you're working on
+components that aren't in Storybook yet, please add them.
+
+The `SDK Storybook`_ contains more technical documentation for the SDK. You can usually
+run storybook with:
+
+.. code-block:: bash
+
+ npm run storybook [-- --no-open]
+
+Writing `interaction tests `_ is
+recommended, but please limit those to actual interactions. For more low-level tests,
+stick to writing unit tests in Jest, using
+`Testing Library `_.
+
**Managing translations**
Translations are extracted from the code with helper scripts, and after the
@@ -48,9 +66,9 @@ as we're currently re-organizing the tooling here.
Cheat sheet:
-* SDK: ``yarn makemessages`` and ``yarn compilemessages``
+* SDK: ``npm run makemessages`` and ``npm run compilemessages``
* Backend: ``./bin/makemessages_js.sh`` and ``./bin/compilemessages_js.sh``
-* Libraries: ``./bin/makemessages.sh`` and ``(yarn|npm run) compilemessages``
+* Libraries: ``./bin/makemessages.sh`` and ``npm run compilemessages``
There is also a ``bin/find_untranslated_js.py`` script to point out potentially missed
translations, as the JSON file format is not too friendly to keep track of everything.
@@ -61,24 +79,6 @@ Indent sizes and other code formatting rules are specified in the ``.editorconfi
which should be supported by most editors. Possibly you need to install a plugin for it
to be activated though.
-SDK toolchain
-=============
-
-See the `SDK Storybook`_ for more technical documentation.
-
-**Yarn**
-
-In the SDK we use yarn_ rather than NPM. There is no particular version pinned at the
-moment (since the lockfile format did not recently change). The node version is pinned
-in ``.nvmrc`` though.
-
-The Yarn CLI is almost the same as NPM.
-
-**Storybook**
-
-We are shifting isolated/component development and interaction testing towards
-storybook. Make sure to check it out and fill the gaps in documentation!
-
.. _nvm: https://github.com/nvm-sh/nvm
.. _yarn: https://yarnpkg.com/
.. _Prettier: https://prettier.io/
diff --git a/src/openforms/formio/tests/search_strategies.py b/src/openforms/formio/tests/search_strategies.py
index c9f7ea57c0..04f93c91e6 100644
--- a/src/openforms/formio/tests/search_strategies.py
+++ b/src/openforms/formio/tests/search_strategies.py
@@ -1,6 +1,9 @@
"""
Expose hypothesis derived strategies to work with Formio.js data structures.
+.. tip:: Use hypothesis strategies to generate random Formio form configurations to
+ test implementation robustness.
+
All the formio component definitions must be JSON-serializable. JSON in itself can
handle NULL bytes inside strings (they turn into \u0000), but JSONB as used by
postgresql and Django's model.JSONField - where we persist these component definitions -
@@ -373,8 +376,8 @@ def map_component():
return st.fixed_dictionaries(_minimal_component_mapping("map"), optional=optional)
-def nested_components(max_size=10):
- return st.lists(any_component(stop_nesting=True), max_size=max_size)
+def nested_components():
+ return st.lists(any_component, min_size=1, max_size=5)
def edit_grid_component():
@@ -457,8 +460,9 @@ def cosign_v1_component():
)
-def any_component(stop_nesting=False):
- inputs = [
+any_component = st.deferred(
+ lambda: st.one_of(
+ # INPUTS
textfield_component(),
email_component(),
date_component(),
@@ -473,8 +477,7 @@ def any_component(stop_nesting=False):
selectboxes_component(),
currency_component(),
radio_component(),
- ]
- special = [
+ # SPECIAL
iban_component(),
license_plate_component(),
bsn_component(),
@@ -483,22 +486,17 @@ def any_component(stop_nesting=False):
signature_component(),
cosign_v2_component(),
map_component(),
- ]
- # if we keep generating nested structures, we run into Python Recursion limits
- if not stop_nesting:
- special.append(edit_grid_component())
- layout = [
+ edit_grid_component(),
+ # LAYOUT
content_component(),
- ]
- if not stop_nesting:
- layout += [
- columns_component(),
- fieldset_component(),
- ]
- deprecated = [
+ columns_component(),
+ fieldset_component(),
+ # DEPRECATED
postcode_component(),
password_component(),
cosign_v1_component(),
- ]
- all_types = inputs + special + layout + deprecated
- return st.one_of(all_types)
+ )
+)
+"""
+A search strategy returning any possible/supported Formio component dictionary.
+"""
diff --git a/src/openforms/formio/tests/test_search_strategies.py b/src/openforms/formio/tests/test_search_strategies.py
index 7435ab68c3..82ea0138a3 100644
--- a/src/openforms/formio/tests/test_search_strategies.py
+++ b/src/openforms/formio/tests/test_search_strategies.py
@@ -14,6 +14,7 @@
from ..validators import variable_key_validator
from .search_strategies import (
address_nl_component,
+ any_component,
bsn_component,
checkbox_component,
columns_component,
@@ -55,72 +56,67 @@ def test_formio_key_validates(self, key: str):
except ValidationError:
self.fail("Generated formio key did not pass validation")
+ @given(any_component)
+ def test_any_component(self, component: Component):
+ self.assertIn("type", component)
+ self.assertIn("key", component)
+
@given(textfield_component())
def test_textfield_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "textfield")
self.assertIn("key", component)
self.assertIn("label", component)
@given(email_component())
def test_email_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "email")
self.assertIn("key", component)
self.assertIn("label", component)
@given(date_component())
def test_date_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "date")
self.assertIn("key", component)
self.assertIn("label", component)
@given(datetime_component())
def test_datetime_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "datetime")
self.assertIn("key", component)
self.assertIn("label", component)
@given(time_component())
def test_time_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "time")
self.assertIn("key", component)
self.assertIn("label", component)
@given(phone_number_component())
def test_phone_number_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "phoneNumber")
self.assertIn("key", component)
self.assertIn("label", component)
@given(file_component())
def test_file_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "file")
self.assertIn("key", component)
self.assertIn("label", component)
@given(textarea_component())
def test_textarea_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "textarea")
self.assertIn("key", component)
self.assertIn("label", component)
@given(number_component())
def test_number_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "number")
self.assertIn("key", component)
self.assertIn("label", component)
@given(select_component())
def test_select_component(self, component: SelectComponent):
- assert "type" in component
self.assertEqual(component["type"], "select")
self.assertIn("key", component)
self.assertIn("label", component)
@@ -133,14 +129,12 @@ def test_select_component(self, component: SelectComponent):
@given(checkbox_component())
def test_checkbox_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "checkbox")
self.assertIn("key", component)
self.assertIn("label", component)
@given(selectboxes_component())
def test_selectboxes_component(self, component: SelectBoxesComponent):
- assert "type" in component
self.assertEqual(component["type"], "selectboxes")
self.assertIn("key", component)
self.assertIn("label", component)
@@ -152,14 +146,12 @@ def test_selectboxes_component(self, component: SelectBoxesComponent):
@given(currency_component())
def test_currency_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "currency")
self.assertIn("key", component)
self.assertIn("label", component)
@given(radio_component())
def test_radio_component(self, component: RadioComponent):
- assert "type" in component
self.assertEqual(component["type"], "radio")
self.assertIn("key", component)
self.assertIn("label", component)
@@ -171,84 +163,72 @@ def test_radio_component(self, component: RadioComponent):
@given(iban_component())
def test_iban_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "iban")
self.assertIn("key", component)
self.assertIn("label", component)
@given(license_plate_component())
def test_license_plate_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "licenseplate")
self.assertIn("key", component)
self.assertIn("label", component)
@given(bsn_component())
def test_bsn_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "bsn")
self.assertIn("key", component)
self.assertIn("label", component)
@given(address_nl_component())
def test_address_nl_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "addressNL")
self.assertIn("key", component)
self.assertIn("label", component)
@given(np_family_members_component())
def test_np_family_members_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "npFamilyMembers")
self.assertIn("key", component)
self.assertIn("label", component)
@given(signature_component())
def test_signature_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "signature")
self.assertIn("key", component)
self.assertIn("label", component)
@given(cosign_v2_component())
def test_cosign_v2_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "cosign")
self.assertIn("key", component)
self.assertIn("label", component)
@given(map_component())
def test_map_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "map")
self.assertIn("key", component)
self.assertIn("label", component)
@given(postcode_component())
def test_postcode_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "postcode")
self.assertIn("key", component)
self.assertIn("label", component)
@given(password_component())
def test_password_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "password")
self.assertIn("key", component)
self.assertIn("label", component)
@given(cosign_v1_component())
def test_cosign_v1_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "coSign")
self.assertIn("key", component)
self.assertIn("label", component)
@given(content_component())
def test_content_component(self, component: ContentComponent):
- assert "type" in component
self.assertEqual(component["type"], "content")
self.assertIn("key", component)
self.assertIn("label", component)
@@ -256,9 +236,8 @@ def test_content_component(self, component: ContentComponent):
@given(edit_grid_component())
# recursive structure, more expensive to draw examples
- @settings(max_examples=10, deadline=500)
+ @settings(max_examples=10)
def test_edit_grid_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "editgrid")
self.assertIn("key", component)
self.assertIn("label", component)
@@ -269,9 +248,8 @@ def test_edit_grid_component(self, component: Component):
@given(fieldset_component())
# recursive structure, more expensive to draw examples
- @settings(max_examples=10, deadline=500)
+ @settings(max_examples=10)
def test_fieldset_component(self, component: Component):
- assert "type" in component
self.assertEqual(component["type"], "fieldset")
self.assertIn("key", component)
self.assertIn("label", component)
@@ -283,9 +261,8 @@ def test_fieldset_component(self, component: Component):
@given(columns_component())
# recursive structure, more expensive to draw examples
- @settings(max_examples=10, deadline=500)
+ @settings(max_examples=10)
def test_columns_component(self, component: ColumnsComponent):
- assert "type" in component
self.assertEqual(component["type"], "columns")
self.assertIn("key", component)
self.assertNotIn("label", component)
diff --git a/src/openforms/forms/api/serializers/form_definition.py b/src/openforms/forms/api/serializers/form_definition.py
index 967c154483..b05fd896c4 100644
--- a/src/openforms/forms/api/serializers/form_definition.py
+++ b/src/openforms/forms/api/serializers/form_definition.py
@@ -1,5 +1,3 @@
-import warnings
-
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
@@ -14,7 +12,6 @@
ModelTranslationsSerializer,
)
-from ...fd_translations_converter import process_component_tree
from ...models import Form, FormDefinition
from ...validators import (
validate_form_definition_is_reusable,
@@ -145,24 +142,10 @@ def to_representation(self, instance):
def validate(self, attrs):
attrs = super().validate(attrs)
if self.instance:
+ assert isinstance(self.instance, FormDefinition)
validate_form_definition_is_reusable(
self.instance, new_value=attrs.get("is_reusable")
)
-
- # during import, process legacy format component translations
- if self.context.get("is_import", False) and (
- translations_store := attrs.get("component_translations")
- ):
- warnings.warn(
- "Form-definition component translations are deprecated, the "
- "compatibility layer wil be removed in Open Forms 3.0.",
- DeprecationWarning,
- )
- process_component_tree(
- components=attrs["configuration"]["components"],
- translations_store=translations_store,
- )
-
return attrs
diff --git a/src/openforms/forms/fd_translations_converter.py b/src/openforms/forms/fd_translations_converter.py
deleted file mode 100644
index 1f4415430d..0000000000
--- a/src/openforms/forms/fd_translations_converter.py
+++ /dev/null
@@ -1,177 +0,0 @@
-"""
-Implements the translation converter for form definitions.
-
-Github issue: https://github.com/open-formulieren/open-forms/issues/2958
-
-Before, translations for formio components were saved in the JSONField
-``FormDefinition.component_translations``, which is a key-value mapping of language
-code to translations mapping, which itself is a key-value mapping of source string to
-translation string. This had the drawback that if different components happen to use the
-same literal, they also shared the same translation.
-
-The utilities here help in converting these translations to component-local
-translations, where the translations are stored on each component inside the formio
-schema. The exact set of supported fields for translation varies per component, the
-reference for this is the typescript type definitions:
-https://open-formulieren.github.io/types/modules/index.html
-"""
-
-import logging
-from typing import TypedDict
-
-from glom import assign
-
-from openforms.formio.service import iter_components
-from openforms.formio.typing import Component
-
-logger = logging.getLogger(__name__)
-
-
-class Option(TypedDict):
- value: str
- label: str
-
-
-def _set_translations(
- obj: Component | Option,
- translations_from_store: dict[str, str],
- locale: str,
- fields: list[str],
-) -> None:
- translations = {
- key: translation
- for key in fields
- if (literal := obj.get(key))
- and (translation := translations_from_store.get(literal))
- }
- if not translations:
- return
- assign(obj, f"openForms.translations.{locale}", translations, missing=dict)
-
-
-def _move_translations(component: Component, locale: str, translations: dict[str, str]):
- """
- Given a component and translation store, mutate the component to bake in translations.
-
- This mutates the ``component`` parameter!
- """
- assert "type" in component
-
- match component:
- case {"type": "textfield" | "textarea"}:
- _set_translations(
- component,
- translations,
- locale,
- fields=[
- "label",
- "description",
- "tooltip",
- "defaultValue",
- "placeholder",
- ],
- )
- case {
- "type": "email"
- | "date"
- | "datetime"
- | "time"
- | "phoneNumber"
- | "file"
- | "checkbox"
- | "currency"
- | "iban"
- | "licenseplate"
- | "bsn"
- | "addressNL"
- | "npFamilyMembers"
- | "cosign"
- | "map"
- | "postcode"
- | "password"
- }:
- _set_translations(
- component,
- translations,
- locale,
- fields=["label", "description", "tooltip"],
- )
-
- case {"type": "number"}:
- _set_translations(
- component,
- translations,
- locale,
- fields=["label", "description", "tooltip", "suffix"],
- )
-
- case {"type": "select" | "selectboxes" | "radio", **rest}:
- _set_translations(
- component,
- translations,
- locale,
- fields=["label", "description", "tooltip"],
- )
-
- # process options, which have their translations inside of each option
- match rest:
- case {"data": {"values": values}} | {"values": values}:
- values: list[Option]
- for value in values:
- _set_translations(value, translations, locale, fields=["label"])
-
- case {"type": "signature"}:
- _set_translations(
- component,
- translations,
- locale,
- fields=["label", "description", "tooltip", "footer"],
- )
-
- case {"type": "coSign"}:
- _set_translations(
- component, translations, locale, fields=["label", "description"]
- )
-
- case {"type": "editgrid"}:
- _set_translations(
- component,
- translations,
- locale,
- fields=[
- "label",
- "description",
- "tooltip",
- "groupLabel",
- "addAnother",
- "saveRow",
- "removeRow",
- ],
- )
-
- case {"type": "content"}:
- # label is legacy and no longer exposed in the new form builder, but pre-existing
- # form definitions may have it set.
- _set_translations(component, translations, locale, fields=["label", "html"])
-
- case {"type": "columns"}:
- pass
-
- case {"type": "fieldset"}:
- _set_translations(component, translations, locale, fields=["label"])
-
- case _: # pragma: no cover
- # should not happen
- logger.warning(
- "Could not move translations for unknown component type %s",
- component["type"],
- )
-
-
-def process_component_tree(
- components: list[Component], translations_store: dict[str, dict[str, str]]
-):
- tree = {"components": components}
- for component in iter_components(tree, recursive=True): # type: ignore
- for lang_code, translations in translations_store.items():
- _move_translations(component, lang_code, translations)
diff --git a/src/openforms/forms/tests/test_import_export.py b/src/openforms/forms/tests/test_import_export.py
index 0722b2578e..7ab4cd882d 100644
--- a/src/openforms/forms/tests/test_import_export.py
+++ b/src/openforms/forms/tests/test_import_export.py
@@ -1067,76 +1067,6 @@ def test_rountrip_form_with_theme_override(self):
imported_form = Form.objects.exclude(pk=form.pk).get()
self.assertIsNone(imported_form.theme)
- def test_import_form_with_legacy_formio_component_translations_format(self):
- """
- Legacy translations need to be converted to the new format.
- """
- resources = {
- "forms": [
- {
- "active": True,
- "authentication_backends": [],
- "is_deleted": False,
- "login_required": False,
- "maintenance_mode": False,
- "name": "Test Form 1",
- "internal_name": "Test Form Internal 1",
- "product": None,
- "show_progress_indicator": True,
- "slug": "translations",
- "url": "http://testserver/api/v2/forms/324cadce-a627-4e3f-b117-37ca232f16b2",
- "uuid": "324cadce-a627-4e3f-b117-37ca232f16b2",
- }
- ],
- "formSteps": [
- {
- "form": "http://testserver/api/v2/forms/324cadce-a627-4e3f-b117-37ca232f16b2",
- "form_definition": "http://testserver/api/v2/form-definitions/f0dad93b-333b-49af-868b-a6bcb94fa1b8",
- "index": 0,
- "slug": "test-step-1",
- "uuid": "3ca01601-cd20-4746-bce5-baab47636823",
- },
- ],
- "formDefinitions": [
- {
- "configuration": {
- "components": [
- {
- "key": "textfield",
- "type": "textfield",
- "label": "TEXTFIELD_LABEL",
- },
- ]
- },
- "name": "Def 1 - With condition",
- "slug": "test-definition-1",
- "url": "http://testserver/api/v2/form-definitions/f0dad93b-333b-49af-868b-a6bcb94fa1b8",
- "uuid": "f0dad93b-333b-49af-868b-a6bcb94fa1b8",
- "component_translations": {
- "nl": {
- "TEXTFIELD_LABEL": "Tekstveld",
- }
- },
- },
- ],
- }
-
- with zipfile.ZipFile(self.filepath, "w") as zip_file:
- for name, data in resources.items():
- zip_file.writestr(f"{name}.json", json.dumps(data))
-
- call_command("import", import_file=self.filepath)
-
- fd = FormDefinition.objects.get()
- textfield = fd.configuration["components"][0]
-
- self.assertIn("openForms", textfield)
- self.assertIn("translations", textfield["openForms"])
- self.assertIn("nl", textfield["openForms"]["translations"])
- nl_translations = textfield["openForms"]["translations"]["nl"]
- self.assertIn("label", nl_translations)
- self.assertEqual(nl_translations["label"], "Tekstveld")
-
@tag("gh-3975")
def test_import_form_with_old_service_fetch_config(self):
resources = {
diff --git a/src/openforms/forms/tests/test_translations_converter.py b/src/openforms/forms/tests/test_translations_converter.py
deleted file mode 100644
index f83af22ba0..0000000000
--- a/src/openforms/forms/tests/test_translations_converter.py
+++ /dev/null
@@ -1,263 +0,0 @@
-from django.test import SimpleTestCase
-
-from glom import glom
-from hypothesis import given, settings
-
-from openforms.formio.service import iter_components
-from openforms.formio.tests.search_strategies import (
- address_nl_component,
- any_component,
- bsn_component,
- checkbox_component,
- columns_component,
- content_component,
- cosign_v1_component,
- cosign_v2_component,
- currency_component,
- date_component,
- datetime_component,
- edit_grid_component,
- email_component,
- fieldset_component,
- file_component,
- iban_component,
- license_plate_component,
- map_component,
- np_family_members_component,
- number_component,
- password_component,
- phone_number_component,
- postcode_component,
- radio_component,
- select_component,
- selectboxes_component,
- signature_component,
- textarea_component,
- textfield_component,
- time_component,
-)
-from openforms.formio.typing import (
- ColumnsComponent,
- Component,
- ContentComponent,
- RadioComponent,
- SelectBoxesComponent,
- SelectComponent,
-)
-
-from ..fd_translations_converter import process_component_tree
-
-
-def _get_dummy_translations_store(component):
- translations_store = {"nl": {}}
- for comp in iter_components({"components": [component]}, recursive=True):
- if literal := comp.get("label"):
- translations_store["nl"][literal] = "Vertaald label"
- return translations_store
-
-
-def do_processing(component):
- translations_store = _get_dummy_translations_store(component)
- process_component_tree([component], translations_store)
-
-
-class ConverterRobustnessTests(SimpleTestCase):
- """
- Generate fixtures with hypothesis to check that our converter doesn't unexpectedly
- crashes on possibly weird but valid data.
- """
-
- def assertLabelsTranslated(self, component):
- for comp in iter_components({"components": [component]}, recursive=True):
- if not comp.get("label"):
- continue
- translation = glom(comp, "openForms.translations.nl.label", default="")
- self.assertEqual(translation, "Vertaald label")
-
- @given(any_component())
- # recursive structure, more expensive to draw examples
- @settings(max_examples=25, deadline=500)
- def test_any_component_is_properly_processed(self, component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(textfield_component())
- def test_textfield_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(email_component())
- def test_email_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(date_component())
- def test_date_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(datetime_component())
- def test_datetime_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(time_component())
- def test_time_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(phone_number_component())
- def test_phone_number_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(file_component())
- def test_file_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(textarea_component())
- def test_textarea_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(number_component())
- def test_number_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(select_component())
- def test_select_component(self, component: SelectComponent):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(checkbox_component())
- def test_checkbox_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(selectboxes_component())
- def test_selectboxes_component(self, component: SelectBoxesComponent):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(currency_component())
- def test_currency_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(radio_component())
- def test_radio_component(self, component: RadioComponent):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(iban_component())
- def test_iban_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(license_plate_component())
- def test_license_plate_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(bsn_component())
- def test_bsn_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(address_nl_component())
- def test_address_nl_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(np_family_members_component())
- def test_np_family_members_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(signature_component())
- def test_signature_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(cosign_v2_component())
- def test_cosign_v2_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(map_component())
- def test_map_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(postcode_component())
- def test_postcode_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(password_component())
- def test_password_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(cosign_v1_component())
- def test_cosign_v1_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(content_component())
- def test_content_component(self, component: ContentComponent):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(edit_grid_component())
- # recursive structure, more expensive to draw examples
- @settings(max_examples=10, deadline=500)
- def test_edit_grid_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(fieldset_component())
- # recursive structure, more expensive to draw examples
- @settings(max_examples=10, deadline=500)
- def test_fieldset_component(self, component: Component):
- do_processing(component)
-
- self.assertLabelsTranslated(component)
-
- @given(columns_component())
- # recursive structure, more expensive to draw examples
- @settings(max_examples=10, deadline=500)
- def test_columns_component(self, component: ColumnsComponent):
- do_processing(component)
-
- self.assertLabelsTranslated(component)