Skip to content
Merged
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
80 changes: 79 additions & 1 deletion demo/tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
from freezegun import freeze_time

from formidable.constants import REQUIRED, EDITABLE, READONLY, HIDDEN
from formidable.models import Formidable
from formidable.models import Formidable, PresetArg
from formidable.forms import FormidableForm, widgets, fields
from formidable.forms.validations.presets import ConfirmationPresets


class TestDynamicForm(TestCase):
Expand Down Expand Up @@ -776,3 +777,80 @@ def test_from_json_raised_error(self):
self.assertEqual(len(context.exception.messages), 3)
for message in context.exception.messages:
self.assertEqual(message, 'This field is required.')


class TestInnerPresets(TestCase):

def test_confirmation_not_required_field(self):
class TestPresets(FormidableForm):
number = fields.IntegerField(accesses={
'jedi': EDITABLE,
})
text = fields.CharField(accesses={
'jedi': EDITABLE,
})

class Meta:
presets = [
ConfirmationPresets(
[PresetArg(slug='left', field_id='number'),
PresetArg(slug='right', value='42')],
),
ConfirmationPresets(
[PresetArg(slug='left', field_id='text'),
PresetArg(slug='right', value='toto')],
),
]

formidable = TestPresets.to_formidable(label='presets')
form_class = formidable.get_django_form_class(role='jedi')
form = form_class(data={'number': '', 'text': ''})
self.assertEqual(len(form.rules), 2)
self.assertTrue(form.is_valid(), form.errors)

def test_confirmation_not_required_fields(self):
class TestPresets(FormidableForm):
left = fields.IntegerField(accesses={
'jedi': REQUIRED,
})
right = fields.IntegerField(accesses={
'jedi': REQUIRED,
})

class Meta:
presets = [
ConfirmationPresets(
[PresetArg(slug='left', field_id='left'),
PresetArg(slug='right', field_id='right')],
),
]

formidable = TestPresets.to_formidable(label='presets')
form_class = formidable.get_django_form_class(role='padawan')
form = form_class(data={'left': '', 'right': ''})
self.assertTrue(form.is_valid(), form.errors)

def test_confirmation_required_fields(self):
class TestPresets(FormidableForm):
left = fields.IntegerField(accesses={
'jedi': REQUIRED,
})
right = fields.IntegerField(accesses={
'jedi': REQUIRED,
})

class Meta:
presets = [
ConfirmationPresets(
[PresetArg(slug='left', field_id='left'),
PresetArg(slug='right', field_id='right')],
),
]

formidable = TestPresets.to_formidable(label='presets')
form_class = formidable.get_django_form_class(role='jedi')
form = form_class(data={'left': '', 'right': ''})
self.assertFalse(form.is_valid(), form.errors)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the test ... The field are required so the form validation will be false.

I would like to see a test like that

=> Define a Validation Between two fields required for the Jedi
=> Get the dynamic_form_class for a padawan
=> Fill the form with empty value
=> validate the form (it has to be okay).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some assertions in this test and a new test that matches your description

self.assertEqual(len(form.errors), 2)
self.assertIn('left', form.errors)
self.assertIn('right', form.errors)
18 changes: 18 additions & 0 deletions formidable/forms/validations/presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,25 @@ def __init__(self, arguments, message=None):
self.arguments = arguments
self.message = message or self.default_message

def has_empty_fields(self, cleaned_data):
def is_empty_value(data):
return (data is None or
(isinstance(data, six.string_types) and not data))

used_fields = {a.field_id for a in self.arguments if a.field_id}
# we do not filter out required fields because they can't be empty
return any(
is_empty_value(cleaned_data.get(name, None))
for name in used_fields
)

def __call__(self, cleaned_data):
if self.has_empty_fields(cleaned_data):
# We skip rules using empty fields
# If the fields were required then it is already reported in
# form.errors. If the fields were not required, then it is not
# useful to report an error
return True
kwargs = self.collect_kwargs(cleaned_data)
if not self.run(**kwargs):
raise ValidationError(self.get_message(kwargs))
Expand Down