From 6e1322376dfa632dd5618962b9534fe376ac256c Mon Sep 17 00:00:00 2001 From: Fred van Dijk Date: Thu, 6 Jun 2019 15:29:46 +0200 Subject: [PATCH 1/3] Fix validation and inline validation for fields in fieldsets. Refs #172 Forward port from branch 1.x. --- CHANGES.rst | 2 ++ src/collective/easyform/fields.py | 12 +++++++++++- src/collective/easyform/fields.zcml | 3 +++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 709b84fd..12e6eba6 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,8 @@ Changelog 2.1.1 (unreleased) ------------------ +- Fix validation and inline validation for fields in fieldsets. Refs #172. [frevd] + - Moved from dotted to named behaviors. [iham] diff --git a/src/collective/easyform/fields.py b/src/collective/easyform/fields.py index 0d5822cb..b35452fe 100644 --- a/src/collective/easyform/fields.py +++ b/src/collective/easyform/fields.py @@ -11,6 +11,7 @@ from plone.schemaeditor.fields import FieldFactory from plone.supermodel.exportimport import BaseHandler from z3c.form import validator as z3c_validator +from z3c.form.interfaces import IGroup from z3c.form.interfaces import IValidator from z3c.form.interfaces import IValue from zope.component import adapter @@ -28,7 +29,7 @@ @adapter(IEasyForm, Interface, IEasyFormForm, IField, Interface) class FieldExtenderValidator(z3c_validator.SimpleFieldValidator): - """ z3c.form validator class for easyform fields """ + """ z3c.form validator class for easyform fields in the default fieldset""" def validate(self, value): """ Validate field by TValidator """ @@ -53,6 +54,15 @@ def validate(self, value): raise Invalid(cerr) +@implementer(IValidator) +@adapter(IEasyForm, Interface, IGroup, IField, Interface) +class GroupFieldExtenderValidator(FieldExtenderValidator): + + """ z3c.form validator class for easyform fields in fieldset groups """ + + pass + + @implementer(IValue) @adapter(IEasyForm, Interface, IEasyFormForm, IField, Interface) class FieldExtenderDefault(object): diff --git a/src/collective/easyform/fields.zcml b/src/collective/easyform/fields.zcml index df7feec6..92583af3 100644 --- a/src/collective/easyform/fields.zcml +++ b/src/collective/easyform/fields.zcml @@ -5,6 +5,9 @@ + Date: Mon, 5 Aug 2019 18:17:51 +0200 Subject: [PATCH 2/3] Fixed default value for fields in fieldsets. Fixes https://github.com/collective/collective.easyform/issues/157. --- CHANGES.rst | 4 +++- src/collective/easyform/fields.py | 11 ++++++++++- src/collective/easyform/fields.zcml | 4 ++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 12e6eba6..1fd32ce4 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,9 @@ Changelog 2.1.1 (unreleased) ------------------ -- Fix validation and inline validation for fields in fieldsets. Refs #172. [frevd] +- Fixed validation, inline validation, and defaults for fields in fieldsets. + Refs issues `#172 `_ + and ` #157 `_. [frevd, maurits] - Moved from dotted to named behaviors. [iham] diff --git a/src/collective/easyform/fields.py b/src/collective/easyform/fields.py index b35452fe..998c7bc6 100644 --- a/src/collective/easyform/fields.py +++ b/src/collective/easyform/fields.py @@ -67,7 +67,7 @@ class GroupFieldExtenderValidator(FieldExtenderValidator): @adapter(IEasyForm, Interface, IEasyFormForm, IField, Interface) class FieldExtenderDefault(object): - """ z3c.form default class for easyform fields """ + """ z3c.form default class for easyform fields in the default fieldset """ def __init__(self, context, request, view, field, widget): self.context = context @@ -84,6 +84,15 @@ def get(self): return get_expression(self.context, TDefault) if TDefault else fdefault +@implementer(IValue) +@adapter(IEasyForm, Interface, IGroup, IField, Interface) +class GroupFieldExtenderDefault(FieldExtenderDefault): + + """ z3c.form default class for easyform fields in fieldset groups """ + + pass + + @implementer(IFromUnicode, ILabel) class Label(Field): diff --git a/src/collective/easyform/fields.zcml b/src/collective/easyform/fields.zcml index 92583af3..942d5d28 100644 --- a/src/collective/easyform/fields.zcml +++ b/src/collective/easyform/fields.zcml @@ -12,6 +12,10 @@ factory=".fields.FieldExtenderDefault" name="default" /> + Date: Mon, 5 Aug 2019 21:29:59 +0200 Subject: [PATCH 3/3] Added tests for validators and defaults both in and out of a fieldset. --- .../fixtures/fieldset_with_single_field.xml | 10 +++ .../easyform/tests/fixtures/single_field.xml | 8 +++ .../easyform/tests/testValidators.py | 72 +++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 src/collective/easyform/tests/fixtures/fieldset_with_single_field.xml create mode 100644 src/collective/easyform/tests/fixtures/single_field.xml diff --git a/src/collective/easyform/tests/fixtures/fieldset_with_single_field.xml b/src/collective/easyform/tests/fixtures/fieldset_with_single_field.xml new file mode 100644 index 00000000..706d34c8 --- /dev/null +++ b/src/collective/easyform/tests/fixtures/fieldset_with_single_field.xml @@ -0,0 +1,10 @@ + + +
+ + + Your E-Mail Address + +
+
+
diff --git a/src/collective/easyform/tests/fixtures/single_field.xml b/src/collective/easyform/tests/fixtures/single_field.xml new file mode 100644 index 00000000..a88a40e6 --- /dev/null +++ b/src/collective/easyform/tests/fixtures/single_field.xml @@ -0,0 +1,8 @@ + + + + + Your E-Mail Address + + + diff --git a/src/collective/easyform/tests/testValidators.py b/src/collective/easyform/tests/testValidators.py index 2d3e44d6..dbda6162 100644 --- a/src/collective/easyform/tests/testValidators.py +++ b/src/collective/easyform/tests/testValidators.py @@ -2,9 +2,14 @@ from collective.easyform import validators from collective.easyform.api import get_schema from collective.easyform.api import set_fields +from collective.easyform.browser.view import EasyFormForm from collective.easyform.browser.view import ValidateFile from collective.easyform.interfaces import IFieldExtender from collective.easyform.tests import base +from os.path import dirname +from os.path import join +from plone import api +from plone.namedfile.file import NamedFile from plone.namedfile.interfaces import INamed from Products.CMFPlone.RegistrationTool import EmailAddressInvalid from Products.validation import validation @@ -96,6 +101,73 @@ def test_talvalidator2(self): self.assertEqual(len(errors), 1) +class TestSingleFieldValidator(base.EasyFormTestCase): + + """ test validator in form outside of fieldset + + The test methods are reused in TestFieldsetValidator. + They use the same field, except that one has it in a fieldset. + """ + schema_fixture = "single_field.xml" + + def afterSetUp(self): + self.folder.invokeFactory("EasyForm", "ff1") + self.ff1 = getattr(self.folder, "ff1") + self.ff1.CSRFProtection = False # no csrf protection + self.ff1.showAll = True + field_template = api.content.create( + self.layer["portal"], "File", id="easyform_default_fields.xml" + ) + with open(join(dirname(__file__), "fixtures", self.schema_fixture)) as f: + filecontent = NamedFile(f.read(), contentType="application/xml") + field_template.file = filecontent + classImplements(BaseRequest, IFormLayer) + validators.update_validators() + + def LoadRequestForm(self, **kwargs): + request = self.layer["request"] + request.form.clear() + prefix = "form.widgets." + for key in kwargs.keys(): + request.form[prefix + key] = kwargs[key] + return request + + def test_get_default(self): + # With a GET, we should see the default value in the form. + request = self.LoadRequestForm() + request.method = "GET" + form = EasyFormForm(self.ff1, request)() + self.assertNotIn('Required input is missing.', form) + self.assertIn('value="foo@example.org"', form) + + def test_required(self): + data = {"replyto": ""} + request = self.LoadRequestForm(**data) + request.method = "POST" + form = EasyFormForm(self.ff1, request)() + self.assertIn('Required input is missing.', form) + self.assertNotIn('Invalid email address.', form) + + def test_validator_in_fieldset(self): + data = { + "replyto": "bad email address", + } + request = self.LoadRequestForm(**data) + request.method = "POST" + form = EasyFormForm(self.ff1, request)() + self.assertNotIn('Required input is missing.', form) + self.assertIn('Invalid email address.', form) + + +class TestFieldsetValidator(TestSingleFieldValidator): + + """ test validator in fieldset + + This reuses the test methods from TestSingleFieldValidator. + """ + schema_fixture = "fieldset_with_single_field.xml" + + class TestCustomValidators(base.EasyFormTestCase): """ test our validators """