Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merged r26931 and r26932 from trunk.
- Loading branch information
Showing
8 changed files
with
469 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
############################################################################## | ||
# | ||
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. | ||
# All Rights Reserved. | ||
# | ||
# This software is subject to the provisions of the Zope Public License, | ||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. | ||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | ||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | ||
# FOR A PARTICULAR PURPOSE. | ||
# | ||
############################################################################## | ||
"""Support Functions for Widget Functional Tests | ||
$Id$ | ||
""" | ||
import re | ||
from zope.configuration import xmlconfig | ||
|
||
def registerEditForm(schema, widgets={}): | ||
"""Registers an edit form for the specified schema. | ||
widgets is a mapping of field name to dict. The dict for each field must | ||
contain a 'class' item, which is the widget class, and any additional | ||
widget attributes (e.g. text field size, rows, cols, etc.) | ||
""" | ||
widgetsXml = [] | ||
for field in widgets: | ||
widgetsXml.append('<widget field="%s"' % field) | ||
for attr in widgets[field]: | ||
widgetsXml.append(' %s="%s"' % (attr, widgets[field][attr])) | ||
widgetsXml.append(' />') | ||
xmlconfig.string(""" | ||
<configure xmlns="http://namespaces.zope.org/browser"> | ||
<include package="zope.app.form.browser" file="meta.zcml" /> | ||
<editform | ||
name="edit.html" | ||
schema="%s" | ||
permission="zope.View"> | ||
%s | ||
</editform> | ||
</configure> | ||
""" % (schema.__identifier__, ''.join(widgetsXml))) | ||
|
||
|
||
def defineSecurity(class_, schema): | ||
class_ = '%s.%s' % (class_.__module__, class_.__name__) | ||
schema = schema.__identifier__ | ||
xmlconfig.string(""" | ||
<configure xmlns="http://namespaces.zope.org/zope"> | ||
<include package="zope.app.component" file="meta.zcml" /> | ||
<class class="%s"> | ||
<require | ||
permission="zope.Public" | ||
interface="%s" | ||
set_schema="%s" /> | ||
</class> | ||
</configure> | ||
""" % (class_, schema, schema)) | ||
|
||
|
||
def defineWidgetView(field_interface, widget_class, view_type): | ||
field_interface = field_interface.__identifier__ | ||
widget_class = '%s.%s' % (widget_class.__module__, widget_class.__name__) | ||
view_type = '%s.%s' % (view_type.__module__, view_type.__name__) | ||
xmlconfig.string(""" | ||
<configure xmlns="http://namespaces.zope.org/zope"> | ||
<include package="zope.app.component" file="meta.zcml" /> | ||
<view | ||
for="%s" | ||
type="zope.publisher.interfaces.browser.IBrowserRequest" | ||
factory="%s" | ||
provides="%s" | ||
permission="zope.Public" | ||
/> | ||
</configure> | ||
""" % (field_interface, widget_class, view_type)) | ||
|
||
|
||
def patternExists(pattern, source, flags=0): | ||
return re.search(pattern, source, flags) is not None | ||
|
||
|
||
def validationErrorExists(field, error_msg, source): | ||
return patternExists( | ||
'name="field.%s".*%s' % (field, error_msg), source, re.DOTALL) | ||
|
||
|
||
def missingInputErrorExists(field, source): | ||
return validationErrorExists(field, 'Required input is missing.', source) | ||
|
||
|
||
def invalidValueErrorExists(field, source): | ||
# assumes this error is displayed for select elements | ||
return patternExists( | ||
'name="field.%s".*</select>.*Invalid value' % field, | ||
source, re.DOTALL) | ||
|
||
|
||
def updatedMsgExists(source): | ||
return patternExists('<p>Updated .*</p>', source) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
############################################################################## | ||
# | ||
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. | ||
# All Rights Reserved. | ||
# | ||
# This software is subject to the provisions of the Zope Public License, | ||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. | ||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | ||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | ||
# FOR A PARTICULAR PURPOSE. | ||
# | ||
############################################################################## | ||
"""Radio Widget Functional Tests | ||
$Id: $ | ||
""" | ||
import unittest | ||
from persistent import Persistent | ||
from transaction import get_transaction | ||
|
||
from support import * | ||
|
||
from zope.interface import Interface | ||
from zope.interface import implements | ||
|
||
from zope.schema import Bool | ||
|
||
from zope.app.traversing.api import traverse | ||
|
||
from zope.app.tests.functional import BrowserTestCase | ||
|
||
|
||
class IFoo(Interface): | ||
|
||
bar = Bool(title=u'Bar') | ||
|
||
registerEditForm(IFoo, widgets={ | ||
'bar': { 'class': 'zope.app.form.browser.BooleanRadioWidget' }}) | ||
|
||
|
||
class Foo(Persistent): | ||
|
||
implements(IFoo) | ||
|
||
def __init__(self): | ||
self.bar = True | ||
|
||
defineSecurity(Foo, IFoo) | ||
|
||
|
||
class Test(BrowserTestCase): | ||
|
||
|
||
def test_display_editform(self): | ||
self.getRootFolder()['foo'] = Foo() | ||
get_transaction().commit() | ||
|
||
# display edit view | ||
response = self.publish('/foo/edit.html') | ||
self.assertEqual(response.getStatus(), 200) | ||
|
||
# bar field should be displayed as two radio buttons | ||
self.assert_(patternExists( | ||
'<input .*checked="checked".*name="field.bar".*type="radio".*' | ||
'value="on".* />', | ||
response.getBody())) | ||
self.assert_(patternExists( | ||
'<input .*name="field.bar".*type="radio".*value="off".* />', | ||
response.getBody())) | ||
|
||
# a hidden element is used to note that the field is present | ||
self.assert_(patternExists( | ||
'<input name="field.bar-empty-marker" type="hidden" value="1".* />', | ||
response.getBody())) | ||
|
||
|
||
def test_submit_editform(self): | ||
self.getRootFolder()['foo'] = Foo() | ||
get_transaction().commit() | ||
|
||
# submit edit view | ||
response = self.publish('/foo/edit.html', form={ | ||
'UPDATE_SUBMIT' : '', | ||
'field.bar' : 'off'}) | ||
self.assertEqual(response.getStatus(), 200) | ||
self.assert_(updatedMsgExists(response.getBody())) | ||
|
||
# check new values in object | ||
object = traverse(self.getRootFolder(), 'foo') | ||
self.assertEqual(object.bar, False) | ||
|
||
|
||
def test_missing_value(self): | ||
self.getRootFolder()['foo'] = Foo() | ||
get_transaction().commit() | ||
|
||
# temporarily make bar field not required | ||
IFoo['bar'].required = False | ||
|
||
# submit missing value for bar | ||
response = self.publish('/foo/edit.html', form={ | ||
'UPDATE_SUBMIT' : '', | ||
'field.bar-empty-marker' : '' }) | ||
self.assertEqual(response.getStatus(), 200) | ||
self.assert_(updatedMsgExists(response.getBody())) | ||
|
||
# confirm use of missing_value as new object value | ||
self.assert_(IFoo['bar'].missing_value is None) | ||
object = traverse(self.getRootFolder(), 'foo') | ||
self.assert_(object.bar is None) | ||
|
||
# restore bar required state | ||
IFoo['bar'].required = True | ||
|
||
|
||
def test_required_validation(self): | ||
self.getRootFolder()['foo'] = Foo() | ||
get_transaction().commit() | ||
|
||
self.assert_(IFoo['bar'].required) | ||
|
||
# submit missing value for required field bar | ||
response = self.publish('/foo/edit.html', form={ | ||
'UPDATE_SUBMIT' : '', | ||
'field.bar-empty-marker' : '1'}) | ||
self.assertEqual(response.getStatus(), 200) | ||
|
||
# confirm error msgs | ||
self.assert_(missingInputErrorExists('bar', response.getBody())) | ||
|
||
|
||
def test_invalid_allowed_value(self): | ||
self.getRootFolder()['foo'] = Foo() | ||
get_transaction().commit() | ||
|
||
# submit a value for bar isn't allowed | ||
response = self.publish('/foo/edit.html', form={ | ||
'UPDATE_SUBMIT' : '', | ||
'field.bar' : 'bogus' }) | ||
self.assertEqual(response.getStatus(), 200) | ||
|
||
self.assert_(validationErrorExists('bar', 'Invalid value', | ||
response.getBody())) | ||
|
||
|
||
def test_suite(): | ||
suite = unittest.TestSuite() | ||
suite.addTest(unittest.makeSuite(Test)) | ||
return suite | ||
|
||
if __name__=='__main__': | ||
unittest.main(defaultTest='test_suite') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.