diff --git a/artel/dynamic_forms/forms.py b/artel/dynamic_forms/forms.py index 56c0903..9e80227 100644 --- a/artel/dynamic_forms/forms.py +++ b/artel/dynamic_forms/forms.py @@ -30,16 +30,26 @@ class DynamicForm(forms.Form): "checkbox": forms.BooleanField(required=False, widget=forms.CheckboxInput(attrs={"class": "form-control"})), "checkboxes": forms.MultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple(attrs={"class": "form-control"})), "dropdown": forms.ChoiceField(widget=forms.Select(attrs={"class": "form-control"})), + "multiselect": forms.MultipleChoiceField(widget=forms.SelectMultiple(attrs={"class": "form-control"})), + "radio": forms.ChoiceField(widget=forms.RadioSelect(attrs={"class": "form-control"})), + "date": forms.DateField(widget=forms.DateInput(attrs={"class": "form-control"})), + "datetime": forms.DateTimeField(widget=forms.DateTimeInput(attrs={"class": "form-control"})), + "hidden": forms.CharField(widget=forms.HiddenInput()), } def __init__(self, *args, **kwargs) -> None: - self.page = kwargs.pop("page") - self.user = kwargs.pop("user") + kwargs.pop("page", "") + kwargs.pop("user", "") field_list = kwargs.pop("field_list") file_uploads = kwargs.pop("file_uploads", False) super().__init__(*args, **kwargs) for field in field_list: - self.fields[field.clean_name] = self.FIELD_TYPE_MAPPING[field.field_type] + f = self.FIELD_TYPE_MAPPING[field.field_type] + f.label = field.label + if hasattr(f, "choices"): + f.choices = [(v, v) for v in field.choices.split(",")] + f.required = field.required + self.fields[field.clean_name] = f if file_uploads: self.fields["attachments"] = MultipleFileField( required=True, widget=MultipleFileInput( diff --git a/artel/dynamic_forms/tests.py b/artel/dynamic_forms/tests.py index c5311d7..63407aa 100644 --- a/artel/dynamic_forms/tests.py +++ b/artel/dynamic_forms/tests.py @@ -1,17 +1,22 @@ -from django.test import TestCase +from wagtail.tests.utils import WagtailPageTests +from django import forms +from django.core.files.uploadedfile import SimpleUploadedFile from dynamic_forms.models import ( CustomEmailForm, EmailFormField ) +from dynamic_forms.forms import DynamicForm -class CustomEmailFormTestCase(TestCase): +class CustomEmailFormTestCase(WagtailPageTests): def setUp(self): self.form = CustomEmailForm.objects.create( + slug="test", title="Test Form", path="test", + depth=0, numchild=0, live=True, has_unpublished_changes=False, from_address="comfy-test@egalitare.pl", to_address="comfy-dest@egalitare.pl", - subject="Test Form", allow_attachments=False + subject="Test Form", allow_attachments=False, ) EmailFormField.objects.create( label="Name", @@ -96,6 +101,177 @@ class CustomEmailFormTestCase(TestCase): form=self.form ) + def test_generate_html_form_from_model(self): + html_form = self.form.get_form() + self.assertIsInstance(html_form, DynamicForm) + self.assertEqual(len(html_form.fields), 13) + self.assertEqual(html_form.fields["name"].label, "Name") + self.assertEqual(html_form.fields["name"].required, True) + self.assertEqual(html_form.fields["name"].widget.attrs["class"], "form-control") + self.assertIsInstance( + html_form.fields["name"], + forms.CharField + ) + self.assertIsInstance( + html_form.fields["message"], + forms.CharField + ) + self.assertIsInstance( + html_form.fields["email"].widget, + forms.EmailInput + ) + self.assertIsInstance( + html_form.fields["number"].widget, + forms.NumberInput + ) - def test_create_form_submission_without_files(self): - ... + def test_create_form_submission_success_without_files(self): + form_data = { + # generate data for this class self.form.get_form() + "name": "Test", + "message": "Test message", + "email": "test@test.com", + "number": 1, + "url": "http://example.com", + "checkbox": True, + "checkboxes": ["a", "b"], + "dropdown": "a", + "multiselect": ["a", "b"], + "radio": "a", + "date": "2020-01-01", + "datetime": "2020-01-01 00:00:00", + "hidden": "hidden", + } + form = self.form.get_form(form_data) + self.assertTrue(form.is_valid()) + # change field not to be required + field = EmailFormField.objects.get( + label="Name", form=self.form + ) + field.required = False + field.save() + form = self.form.get_form(form_data) + self.assertTrue(form.is_valid()) + # it should also work without this field + form_data.pop("name") + form = self.form.get_form(form_data) + self.assertTrue(form.is_valid()) + + def test_create_form_submission_success_with_files(self): + self.form.allow_attachments = True + self.form.save() + form_data = { + # generate data for this class self.form.get_form() + "name": "Test", + "message": "Test message", + "email": "test@test.com", + "number": 1, + "url": "http://example.com", + "checkbox": True, + "checkboxes": ["a", "b"], + "dropdown": "a", + "multiselect": ["a", "b"], + "radio": "a", + "date": "2020-01-01", + "datetime": "2020-01-01 00:00:00", + "hidden": "hidden" + } + files = { + "attachments": [SimpleUploadedFile("test.txt", b"test")], + } + form = self.form.get_form(form_data, files=files) + self.assertTrue(form.is_valid()) + + def test_create_form_submission_failure_without_files_missing_data(self): + form_data = { + # generate data for this class self.form.get_form() + "message": "Test message", + "email": "test@test.com", + "number": 1, + "url": "http://example.com", + "checkbox": True, + "checkboxes": ["a", "b"], + "dropdown": "a", + "multiselect": ["a", "b"], + "radio": "a", + "date": "2020-01-01", + "datetime": "2020-01-01 00:00:00", + "hidden": "hidden", + } + form = self.form.get_form(form_data) + self.assertFalse(form.is_valid()) + self.assertEqual(len(form.errors), 1) + self.assertFormError(form, "name", 'This field is required.') + + form_data.pop("url") + form = self.form.get_form(form_data) + self.assertFalse(form.is_valid()) + self.assertEqual(len(form.errors), 2) + self.assertFormError(form, "name", 'This field is required.') + self.assertFormError(form, "url", 'This field is required.') + # make Field not required + field = EmailFormField.objects.get( + label="Hidden", form=self.form + ) + field.required = False + field.save() + # it should also work without this field + form_data.pop("hidden") + form = self.form.get_form(form_data) + self.assertFalse(form.is_valid()) + self.assertEqual(len(form.errors), 2) + self.assertFormError(form, "name", 'This field is required.') + self.assertFormError(form, "url", 'This field is required.') + + def test_create_form_submission_failure_with_files_missing_data(self): + self.form.allow_attachments = True + self.form.save() + form_data = { + # generate data for this class self.form.get_form() + "message": "Test message", + "email": "test@test.com", + "number": 1, + "url": "http://example.com", + "checkbox": True, + "checkboxes": ["a", "b"], + "dropdown": "a", + "multiselect": ["a", "b"], + "radio": "a", + "date": "2020-01-01", + "datetime": "2020-01-01 00:00:00", + "hidden": "hidden", + } + files = { + "attachments": [SimpleUploadedFile("test.txt", b"test")], + } + form = self.form.get_form(form_data, files=files) + self.assertFalse(form.is_valid()) + self.assertEqual(len(form.errors), 1) + self.assertFormError(form, "name", 'This field is required.') + + form_data.pop("url") + form = self.form.get_form(form_data, files=files) + self.assertFalse(form.is_valid()) + self.assertEqual(len(form.errors), 2) + self.assertFormError(form, "name", 'This field is required.') + self.assertFormError(form, "url", 'This field is required.') + # make Field not required + field = EmailFormField.objects.get( + label="Hidden", form=self.form + ) + field.required = False + field.save() + # it should also work without this field + form_data.pop("hidden") + form = self.form.get_form(form_data, files=files) + self.assertFalse(form.is_valid()) + self.assertEqual(len(form.errors), 2) + self.assertFormError(form, "name", 'This field is required.') + self.assertFormError(form, "url", 'This field is required.') + # Now try without files + form = self.form.get_form(form_data, files={}) + self.assertFalse(form.is_valid()) + self.assertEqual(len(form.errors), 3) + self.assertFormError(form, "name", 'This field is required.') + self.assertFormError(form, "url", 'This field is required.') + self.assertFormError(form, "attachments", 'This field is required.')