diff --git a/src/openforms/forms/tests/test_api_formsteps.py b/src/openforms/forms/tests/test_api_formsteps.py index c67a08bbc6..7c24c762b0 100644 --- a/src/openforms/forms/tests/test_api_formsteps.py +++ b/src/openforms/forms/tests/test_api_formsteps.py @@ -856,6 +856,133 @@ def test_with_non_unique_fd_slugs(self): slugs = {form_step.slug for form_step in form_steps} self.assertEqual(len(slugs), 2) # we expect two unique slugs + @patch("openforms.forms.tasks.create_form_variables_for_components.si") + @patch( + "openforms.forms.tasks.repopulate_reusable_definition_variables_to_form_variables.si" + ) + @patch("openforms.forms.tasks.recouple_submission_variables_to_form_variables.si") + @patch("openforms.forms.tasks.chain") + @tag("gh-4824") + def test_create_form_step_schedules_task_chain_to_fix_form_variables( + self, mock_chain, mock_recouple, mock_repopulate, mock_create_variables + ): + """ + Regression test for https://github.com/open-formulieren/open-forms/issues/4824 + """ + mock_chain_instance = mock_chain.return_value + mock_chain_instance.delay.return_value = None + + assign_change_form_permissions(self.user) + form = FormFactory.create() + url = reverse("api:form-steps-list", kwargs={"form_uuid_or_slug": form.uuid}) + form_definition = FormDefinitionFactory.create( + configuration={ + "display": "form", + "components": [ + { + "key": "lastName", + "type": "textfield", + "label": "Last Name", + }, + ], + } + ) + formdefinition_detail_url = reverse( + "api:formdefinition-detail", + kwargs={"uuid": form_definition.uuid}, + ) + data = { + "formDefinition": f"http://testserver{formdefinition_detail_url}", + "index": 0, + } + self.client.force_login(user=self.user) + + with self.captureOnCommitCallbacks(execute=True): + response = self.client.post(url, data=data) + + mock_create_variables.assert_called_once_with(form.id) + mock_repopulate.assert_called_once_with(form.id) + mock_recouple.assert_called_once_with(form.id) + + mock_chain.assert_called_once_with( + mock_create_variables.return_value, + mock_repopulate.return_value, + mock_recouple.return_value, + ) + + mock_chain_instance.apply_async.assert_called_once_with(countdown=60) + + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual( + FormStep.objects.filter(form_definition=form_definition).count(), + 1, + ) + + @patch("openforms.forms.tasks.create_form_variables_for_components.si") + @patch( + "openforms.forms.tasks.repopulate_reusable_definition_variables_to_form_variables.si" + ) + @patch("openforms.forms.tasks.recouple_submission_variables_to_form_variables.si") + @patch("openforms.forms.tasks.chain") + @tag("gh-4824") + def test_update_form_step_schedules_task_chain_to_fix_form_variables( + self, mock_chain, mock_recouple, mock_repopulate, mock_create_variables + ): + """ + Regression test for https://github.com/open-formulieren/open-forms/issues/4824 + """ + mock_chain_instance = mock_chain.return_value + mock_chain_instance.delay.return_value = None + + assign_change_form_permissions(self.user) + form_step = FormStepFactory.create() + form_definition = FormDefinitionFactory.create( + configuration={ + "display": "form", + "components": [ + { + "key": "lastName", + "type": "textfield", + "label": "Last Name", + }, + ], + } + ) + url = reverse( + "api:form-steps-detail", + kwargs={"form_uuid_or_slug": form_step.form.uuid, "uuid": form_step.uuid}, + ) + formdefinition_detail_url = reverse( + "api:formdefinition-detail", + kwargs={"uuid": form_definition.uuid}, + ) + data = { + "formDefinition": f"http://testserver{formdefinition_detail_url}", + "index": 0, + } + self.client.force_login(user=self.user) + + with self.captureOnCommitCallbacks(execute=True): + response = self.client.put(url, data=data) + + mock_create_variables.assert_called_once_with(form_step.form.id) + mock_repopulate.assert_called_once_with(form_step.form.id) + mock_recouple.assert_called_once_with(form_step.form.id) + + mock_chain.assert_called_once_with( + mock_create_variables.return_value, + mock_repopulate.return_value, + mock_recouple.return_value, + ) + + mock_chain_instance.apply_async.assert_called_once_with(countdown=60) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual( + FormStep.objects.filter(form_definition=form_definition).count(), + 1, + ) + class FormStepsAPITranslationTests(APITestCase): maxDiff = None diff --git a/src/openforms/forms/tests/test_tasks.py b/src/openforms/forms/tests/test_tasks.py index 761e18c179..129180e45d 100644 --- a/src/openforms/forms/tests/test_tasks.py +++ b/src/openforms/forms/tests/test_tasks.py @@ -2,14 +2,19 @@ from unittest.mock import patch from django.db import DatabaseError -from django.test import TestCase, override_settings +from django.test import TestCase, override_settings, tag from freezegun import freeze_time +from openforms.forms.models import FormVariable from openforms.logging.models import TimelineLogProxy -from ..tasks import activate_forms, deactivate_forms -from .factories import FormFactory +from ..tasks import ( + activate_forms, + create_form_variables_for_components, + deactivate_forms, +) +from .factories import FormDefinitionFactory, FormFactory, FormStepFactory logger = logging.getLogger(__name__) @@ -216,3 +221,45 @@ def test_database_error(self, mocked_deactivation): mocked_deactivation.assert_called() self.assertEqual(message, f"Form deactivation of form {form.admin_name} failed") + + +@tag("gh-4824") +class CreateFormVariablesForComponentsTests(TestCase): + def test_create_form_variables_for_components(self): + form = FormFactory.create() + form_definition = FormDefinitionFactory.create( + configuration={ + "display": "form", + "components": [ + { + "key": "lastName", + "type": "textfield", + "label": "Last Name", + }, + ], + } + ) + FormStepFactory.create(form=form, form_definition=form_definition) + + # Form is in a broken state, because no FormVariable exists for `lastName` + FormVariable.objects.filter(form=form).delete() + + with self.subTest("create variables for components"): + create_form_variables_for_components(form.id) + + variables = FormVariable.objects.filter(form=form) + + self.assertEqual(variables.count(), 1) + + [variable] = variables + + self.assertEqual(variable.form_definition, form_definition) + self.assertEqual(variable.source, "component") + self.assertEqual(variable.key, "lastName") + + with self.subTest("task is idempotent"): + create_form_variables_for_components(form.id) + + variables = FormVariable.objects.filter(form=form) + + self.assertEqual(variables.count(), 1)