[Checkins] SVN: z3c.form/trunk/src/z3c/form/ improve group testing,
Roger Ineichen
roger at projekt01.ch
Fri Apr 3 00:08:51 EDT 2009
Log message for revision 98805:
improve group testing,
now we have 100% coverage in every test except the object.py implementation
Note:
the z3c.pt implementation is buggy and doesn't work right.
I left a test in group.txt which shows that a div tag get skipped with z3c.pt.
We need to fix this in z3c.pt or chameleon and the test should be fine without
any changes.
Changed:
U z3c.form/trunk/src/z3c/form/group.txt
A z3c.form/trunk/src/z3c/form/tests/simple_nested_groupedit.pt
-=-
Modified: z3c.form/trunk/src/z3c/form/group.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/group.txt 2009-04-03 04:06:20 UTC (rev 98804)
+++ z3c.form/trunk/src/z3c/form/group.txt 2009-04-03 04:08:51 UTC (rev 98805)
@@ -456,9 +456,94 @@
>>> attrs.attributes
('license', 'address', 'model', 'make', 'year')
-And that's it!
+Group form as instance
+----------------------
+It is also possible to use group instances in forms. Let's setup our previous
+form and assing a group instance:
+
+ >>> class RegistrationEditForm(group.GroupForm, form.EditForm):
+ ... fields = field.Fields(IVehicleRegistration).select(
+ ... 'firstName', 'lastName')
+ ...
+ ... template = viewpagetemplatefile.ViewPageTemplateFile(
+ ... 'simple_groupedit.pt', os.path.dirname(tests.__file__))
+
+ >>> request = testing.TestRequest()
+
+ >>> edit = RegistrationEditForm(reg, request)
+
+Instanciate the form and use a group class and a group instance:
+
+ >>> carGroupInstance = CarGroup(edit.context, request, edit)
+ >>> edit.groups = (LicenseGroup, carGroupInstance)
+ >>> edit.update()
+ >>> print edit.render()
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <body>
+ <form action=".">
+ <div class="row">
+ <label for="form-widgets-firstName">First Name</label>
+ <input id="form-widgets-firstName"
+ name="form.widgets.firstName"
+ class="text-widget required textline-field"
+ value="Stephan" type="text" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-lastName">Last Name</label>
+ <input id="form-widgets-lastName"
+ name="form.widgets.lastName"
+ class="text-widget required textline-field"
+ value="Richter" type="text" />
+ </div>
+ <fieldset>
+ <legend>License</legend>
+ <div class="row">
+ <label for="form-widgets-license">License</label>
+ <input id="form-widgets-license"
+ name="form.widgets.license"
+ class="text-widget required textline-field"
+ value="MA 4038765" type="text" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-address">Address</label>
+ <input id="form-widgets-address"
+ name="form.widgets.address"
+ class="text-widget required textline-field"
+ value="11 Main St, Maynard, MA" type="text" />
+ </div>
+ </fieldset>
+ <fieldset>
+ <legend>Car</legend>
+ <div class="row">
+ <label for="form-widgets-model">Model</label>
+ <input id="form-widgets-model" name="form.widgets.model"
+ class="text-widget required textline-field"
+ value="Ford" type="text" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-make">Make</label>
+ <input id="form-widgets-make" name="form.widgets.make"
+ class="text-widget required textline-field"
+ value="F150" type="text" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-year">Year</label>
+ <input id="form-widgets-year" name="form.widgets.year"
+ class="text-widget required textline-field"
+ value="2006" type="text" />
+ </div>
+ </fieldset>
+ <div class="action">
+ <input id="form-buttons-apply" name="form.buttons.apply"
+ class="submit-widget button-field" value="Apply"
+ type="submit" />
+ </div>
+ </form>
+ </body>
+ </html>
+
Groups with Different Content
-----------------------------
@@ -524,7 +609,6 @@
... template = viewpagetemplatefile.ViewPageTemplateFile(
... 'simple_groupedit.pt', os.path.dirname(tests.__file__))
-
>>> reg = VehicleRegistration(
... license=u'MA 40387',
... address=u'10 Main St, Maynard, MA',
@@ -645,10 +729,9 @@
Nested Groups
------------------
+-------------
-The group can contains groups.
-Let's adapt the previous RegistrationEditForm
+The group can contains groups. Let's adapt the previous RegistrationEditForm:
>>> class OwnerGroup(group.Group):
... label = u'Owner'
@@ -662,14 +745,16 @@
... fields = field.Fields(IVehicleRegistration).omit(
... 'owner')
... groups = (OwnerGroup,)
+ ...
+ ... template = viewpagetemplatefile.ViewPageTemplateFile(
+ ... 'simple_groupedit.pt', os.path.dirname(tests.__file__))
>>> class RegistrationEditForm(group.GroupForm, form.EditForm):
... groups = (VehicleRegistrationGroup,)
...
... template = viewpagetemplatefile.ViewPageTemplateFile(
- ... 'simple_groupedit.pt', os.path.dirname(tests.__file__))
+ ... 'simple_nested_groupedit.pt', os.path.dirname(tests.__file__))
-
>>> reg = VehicleRegistration(
... license=u'MA 40387',
... address=u'10 Main St, Maynard, MA',
@@ -721,11 +806,168 @@
>>> reg.year
u'2005'
-So what happens, if errors happen inside a nested group?
+So what happens, if errors happen inside a nested group? Let's use an empty
+invllaid object for the test missing input errors:
+ >>> reg = VehicleRegistration(owner=VehicleOwner())
+
>>> request = testing.TestRequest(form={
+ ... 'form.widgets.owner.firstName': u'',
+ ... 'form.widgets.owner.lastName': u'',
+ ... 'form.widgets.license': u'',
+ ... 'form.widgets.address': u'',
+ ... 'form.widgets.model': u'',
+ ... 'form.widgets.make': u'',
+ ... 'form.widgets.year': u'',
+ ... 'form.buttons.apply': u'Apply'
+ ... })
+
+ >>> edit = RegistrationEditForm(reg, request)
+ >>> edit.update()
+ >>> data, errors = edit.extractData()
+ >>> print testing.render(edit, './/xmlns:i')
+ <i >There were some errors.</i>
+
+ >>> print testing.render(edit, './/xmlns:fieldset[1]/xmlns:ul')
+ <ul>
+ <li>
+ License:
+ <div class="error">Required input is missing.</div>
+ </li>
+ <li>
+ Address:
+ <div class="error">Required input is missing.</div>
+ </li>
+ <li>
+ Model:
+ <div class="error">Required input is missing.</div>
+ </li>
+ <li>
+ Make:
+ <div class="error">Required input is missing.</div>
+ </li>
+ <li>
+ Year:
+ <div class="error">Required input is missing.</div>
+ </li>
+ </ul>
+ <ul>
+ <li>
+ First Name:
+ <div class="error">Required input is missing.</div>
+ </li>
+ <li>
+ Last Name:
+ <div class="error">Required input is missing.</div>
+ </li>
+ </ul>
+
+
+Group instance in nested group
+------------------------------
+
+Let's also test if the Group class can handle group objects as instances:
+
+ >>> reg = VehicleRegistration(
+ ... license=u'MA 40387',
+ ... address=u'10 Main St, Maynard, MA',
+ ... model=u'BMW',
+ ... make=u'325',
+ ... year=u'2005',
+ ... owner=VehicleOwner(firstName=u'Stephan',
+ ... lastName=u'Richter'))
+ >>> request = testing.TestRequest()
+
+ >>> edit = RegistrationEditForm(reg, request)
+ >>> vrg = VehicleRegistrationGroup(edit.context, request, edit)
+ >>> ownerGroup = OwnerGroup(edit.context, request, edit)
+
+Now build the group instance object chain:
+
+ >>> vrg.groups = (ownerGroup,)
+ >>> edit.groups = (vrg,)
+
+Also use refreshActions whihc is not needed but will make coverage this
+additional line of code in the update method:
+
+ >>> edit.refreshActions = True
+
+Update and render:
+
+ >>> edit.update()
+ >>> print edit.render()
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <body>
+ <form action=".">
+ <fieldset>
+ <legend>Registration</legend>
+ <div class="row">
+ <label for="form-widgets-license">License</label>
+ <input id="form-widgets-license"
+ name="form.widgets.license"
+ class="text-widget required textline-field"
+ value="MA 40387" type="text" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-address">Address</label>
+ <input id="form-widgets-address"
+ name="form.widgets.address"
+ class="text-widget required textline-field"
+ value="10 Main St, Maynard, MA" type="text" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-model">Model</label>
+ <input id="form-widgets-model" name="form.widgets.model"
+ class="text-widget required textline-field"
+ value="BMW" type="text" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-make">Make</label>
+ <input id="form-widgets-make" name="form.widgets.make"
+ class="text-widget required textline-field"
+ value="325" type="text" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-year">Year</label>
+ <input id="form-widgets-year" name="form.widgets.year"
+ class="text-widget required textline-field"
+ value="2005" type="text" />
+ </div>
+ <fieldset>
+ <legend>Owner</legend>
+ <div class="row">
+ <label for="form-widgets-owner-firstName">First Name</label>
+ <input id="form-widgets-owner-firstName"
+ name="form.widgets.owner.firstName"
+ class="text-widget required textline-field"
+ value="Stephan" type="text" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-owner-lastName">Last Name</label>
+ <input id="form-widgets-owner-lastName"
+ name="form.widgets.owner.lastName"
+ class="text-widget required textline-field"
+ value="Richter" type="text" />
+ </div>
+ </fieldset>
+ </fieldset>
+ <div class="action">
+ <input id="form-buttons-apply" name="form.buttons.apply"
+ class="submit-widget button-field" value="Apply"
+ type="submit" />
+ </div>
+ </form>
+ </body>
+ </html>
+
+
+Now test the error handling if just one missing value is given in a group:
+
+ >>> request = testing.TestRequest(form={
... 'form.widgets.owner.firstName': u'Paul',
+ ... 'form.widgets.owner.lastName': u'',
... 'form.widgets.license': u'MA 4038765',
+ ... 'form.widgets.address': u'Berkeley',
... 'form.widgets.model': u'BMW',
... 'form.widgets.make': u'325',
... 'form.widgets.year': u'2005',
@@ -733,25 +975,24 @@
... })
>>> edit = RegistrationEditForm(reg, request)
+ >>> vrg = VehicleRegistrationGroup(edit.context, request, edit)
+ >>> ownerGroup = OwnerGroup(edit.context, request, edit)
+ >>> vrg.groups = (ownerGroup,)
+ >>> edit.groups = (vrg,)
+
>>> edit.update()
>>> data, errors = edit.extractData()
- >>> " ".join(["%s %s"%(error.widget.label, error.render()) for error in errors])
- u'Address \n <div class="error">Required input is missing.</div>\n\n Last Name \n <div class="error">Required input is missing.</div>\n\n'
-
>>> print testing.render(edit, './/xmlns:i')
<i >There were some errors.</i>
>>> print testing.render(edit, './/xmlns:fieldset[1]/xmlns:ul')
- <ul >
- <li>
- Address:
- <div class="error">Required input is missing.</div>
- </li>
+ <ul>
+ <li>
+ Last Name:
+ <div class="error">Required input is missing.</div>
+ </li>
</ul>
-
-And that's it!
-
Just check whether we fully support the interface:
>>> from z3c.form import interfaces
Added: z3c.form/trunk/src/z3c/form/tests/simple_nested_groupedit.pt
===================================================================
--- z3c.form/trunk/src/z3c/form/tests/simple_nested_groupedit.pt (rev 0)
+++ z3c.form/trunk/src/z3c/form/tests/simple_nested_groupedit.pt 2009-04-03 04:08:51 UTC (rev 98805)
@@ -0,0 +1,49 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:metal="http://xml.zope.org/namespaces/metal"
+ xmlns:tal="http://xml.zope.org/namespaces/tal">
+ <body>
+ <i tal:condition="view/status" tal:content="view/status"/>
+ <ul tal:condition="view/widgets/errors"
+ metal:define-macro="errors">
+ <li tal:repeat="error view/widgets/errors">
+ <tal:block condition="error/widget">
+ <tal:block replace="error/widget/label" />:
+ </tal:block>
+ <tal:block replace="structure error/render" />
+ </li>
+ </ul>
+ <form action=".">
+ <metal:block metal:define-macro="rows">
+ <div class="row"
+ tal:repeat="widget view/widgets/values">
+ <b tal:condition="widget/error"
+ tal:content="structure widget/error/render" />
+ <label for=""
+ tal:attributes="for widget/id"
+ tal:content="widget/label" />
+ <input type="text" tal:replace="structure widget/render" />
+ </div>
+ </metal:block>
+ <fieldset tal:condition="view/groups|nothing"
+ tal:repeat="view view/groups">
+ <legend tal:condition="view/label"
+ tal:content="view/label">Label</legend>
+ <div metal:use-macro="template/macros/errors" />
+ <div metal:use-macro="template/macros/rows" />
+ <fieldset tal:condition="view/groups|nothing"
+ tal:repeat="view view/groups">
+ <legend tal:condition="view/label"
+ tal:content="view/label">Label</legend>
+ <div metal:use-macro="template/macros/errors" />
+ <div metal:use-macro="template/macros/rows" />
+ </fieldset>
+ </fieldset>
+ <div class="action"
+ tal:condition="view/actions|nothing"
+ tal:repeat="action view/actions/values">
+ <input type="submit" tal:replace="structure action/render"
+ /></div>
+ </form>
+ </body>
+</html>
More information about the Checkins
mailing list