Skip to content

Commit

Permalink
Backport of fix for #721
Browse files Browse the repository at this point in the history
  • Loading branch information
Jacob Holm committed Dec 21, 2006
1 parent 44dc622 commit 43d0929
Show file tree
Hide file tree
Showing 6 changed files with 302 additions and 2 deletions.
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def _renderedValueSet(self):
return self._data is not self._data_marker

def setPrefix(self, prefix):
if not prefix.endswith("."):
if prefix and not prefix.endswith("."):
prefix += '.'
self._prefix = prefix
self.name = prefix + self.context.__name__
Expand Down
211 changes: 211 additions & 0 deletions browser/tests/test_editview.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
##############################################################################
#
# 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.
#
##############################################################################
"""Edit View Tests
$Id$
"""
import unittest

from zope.interface import Interface, implements
from zope.publisher.browser import TestRequest
from zope.schema import TextLine, accessors
from zope.schema.interfaces import ITextLine
from zope.component.exceptions import ComponentLookupError

from zope.app.testing import ztapi
from zope.app.testing.placelesssetup import PlacelessSetup
from zope.app.event.tests.placelesssetup import getEvents

from zope.app.form.browser import TextWidget
from zope.app.form.browser.editview import EditView
from zope.app.form.browser.submit import Update
from zope.component.exceptions import ComponentLookupError
from zope.app.form.interfaces import IInputWidget
from zope.app.form.tests import utils
from zope.app.location.interfaces import ILocation

class I(Interface):
foo = TextLine(title=u"Foo")
bar = TextLine(title=u"Bar")
a = TextLine(title=u"A")
b = TextLine(title=u"B", min_length=0, required=False)
getbaz, setbaz = accessors(TextLine(title=u"Baz"))

class EV(EditView):
schema = I
object_factories = []

class C(object):
implements(I)
foo = u"c foo"
bar = u"c bar"
a = u"c a"
b = u"c b"
__Security_checker__ = utils.SchemaChecker(I)

_baz = u"c baz"
def getbaz(self): return self._baz
def setbaz(self, v): self._baz = v


class IFoo(Interface):
foo = TextLine(title=u"Foo")

class IBar(Interface):
bar = TextLine(title=u"Bar")

class Foo(object):
implements(IFoo)
__Security_checker__ = utils.SchemaChecker(IFoo)

foo = u'Foo foo'

class ConformFoo(object):
implements(IFoo)

foo = u'Foo foo'

def __conform__(self, interface):
if interface is IBar:
return OtherFooBarAdapter(self)


class FooBarAdapter(object):
implements(IBar, ILocation)
__used_for__ = IFoo

def __init__(self, context):
self.context = context

def getbar(self): return self.context.foo
def setbar(self, v): self.context.foo = v

bar = property(getbar, setbar)

__Security_checker__ = utils.SchemaChecker(IBar)

class OtherFooBarAdapter(FooBarAdapter):
pass

class BarV(EditView):
schema = IBar
object_factories = []

class Test(PlacelessSetup, unittest.TestCase):

def setUp(self):
super(Test, self).setUp()
ztapi.browserViewProviding(ITextLine, TextWidget, IInputWidget)
ztapi.provideAdapter(IFoo, IBar, FooBarAdapter)

def test_setPrefix_and_widgets(self):
v = EV(C(), TestRequest())
v.setPrefix("test")
self.assertEqual(
[w.name for w in v.widgets()],
['test.foo', 'test.bar', 'test.a', 'test.b', 'test.getbaz']
)

def test_empty_prefix(self):
v = EV(C(), TestRequest())
v.setPrefix("")
self.assertEqual(
[w.name for w in v.widgets()],
['foo', 'bar', 'a', 'b', 'getbaz']
)

def test_fail_wo_adapter(self):
c = Foo()
request = TestRequest()
self.assertRaises(TypeError, EV, c, request)

def test_update_no_update(self):
c = C()
request = TestRequest()
v = EV(c, request)
self.assertEqual(v.update(), '')
self.assertEqual(c.foo, u'c foo')
self.assertEqual(c.bar, u'c bar')
self.assertEqual(c.a , u'c a')
self.assertEqual(c.b , u'c b')
self.assertEqual(c.getbaz(), u'c baz')
request.form['field.foo'] = u'r foo'
request.form['field.bar'] = u'r bar'
request.form['field.a'] = u'r a'
request.form['field.b'] = u'r b'
request.form['field.getbaz'] = u'r baz'
self.assertEqual(v.update(), '')
self.assertEqual(c.foo, u'c foo')
self.assertEqual(c.bar, u'c bar')
self.assertEqual(c.a , u'c a')
self.assertEqual(c.b , u'c b')
self.assertEqual(c.getbaz(), u'c baz')
self.failIf(getEvents())

def test_update(self):
c = C()
request = TestRequest()
v = EV(c, request)
request.form[Update] = ''
request.form['field.foo'] = u'r foo'
request.form['field.bar'] = u'r bar'
request.form['field.getbaz'] = u'r baz'
request.form['field.a'] = u'c a'

message = v.update()
self.failUnless(message.startswith('Updated '), message)
self.assertEqual(c.foo, u'r foo')
self.assertEqual(c.bar, u'r bar')
self.assertEqual(c.a , u'c a')
self.assertEqual(c.b , u'c b') # missing from form - unchanged
self.assertEqual(c.getbaz(), u'r baz')

# Verify that calling update multiple times has no effect

c.__dict__.clear()
self.assertEqual(v.update(), message)
self.assertEqual(c.foo, u'c foo')
self.assertEqual(c.bar, u'c bar')
self.assertEqual(c.a , u'c a')
self.assertEqual(c.b , u'c b')
self.assertEqual(c.getbaz(), u'c baz')

def test_update_via_adapter(self):
f = Foo()
request = TestRequest()
v = BarV(f, request)
# check adapter
self.assertEqual(f.foo, u'Foo foo')
a = IBar(f)
self.assertEqual(a.bar, u'Foo foo')
# update
request.form[Update] = ''
request.form['field.bar'] = u'r bar'
message = v.update()
self.failUnless(message.startswith('Updated '), message)
self.assertEqual(a.bar, u'r bar')
# wrong update
self.failIf(getEvents())

def test_setUpWidget_via_conform_adapter(self):

f = ConformFoo()
request = TestRequest()
v = BarV(f, request)

def test_suite():
return unittest.makeSuite(Test)

if __name__=='__main__':
unittest.main(defaultTest='test_suite')
6 changes: 6 additions & 0 deletions browser/tests/test_itemswidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ def test_setPrefix(self):
self.assertEqual(widget.name, 'foo.%s' %name)
self.assertEqual(widget.empty_marker_name,
'foo.%s-empty-marker' %name)
# Declaring empty prefix
widget.setPrefix('')
self.assertEqual(widget._prefix, '')
self.assertEqual(widget.name, name)
self.assertEqual(widget.empty_marker_name,
'%s-empty-marker' %name)

def test_convertTokensToValues(self):
widget = self._makeWidget()
Expand Down
73 changes: 73 additions & 0 deletions browser/tests/test_setprefix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
##############################################################################
#
# 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.
#
##############################################################################
"""Widget name prefix tests
$Id$
"""
import unittest

from zope.app.form.browser import TextWidget
from zope.app.form.browser.tests import support
from zope.publisher.browser import TestRequest
from zope.schema import Text

class Test(support.VerifyResults, unittest.TestCase):

def setUp(self):
field = Text(__name__ = 'foo')
request = TestRequest()
request.form['spam.foo'] = u'Foo Value'
self._widget = TextWidget(field, request)
self._widget.setPrefix('spam')

def testGetData(self):
self.assertEqual(self._widget.getInputValue(), u'Foo Value')

def testRender(self):
value = 'Foo Value 2'
check_list = ('type="text"', 'id="spam.foo"', 'name="spam.foo"',
'value="Foo Value 2"', 'size="20"')
self._widget.setRenderedValue(value)
self.verifyResult(self._widget(), check_list)
check_list = ('type="hidden"',) + check_list[1:-1]
self.verifyResult(self._widget.hidden(), check_list)
check_list = ('style="color: red"',) + check_list
self._widget.extra = 'style="color: red"'
self.verifyResult(self._widget.hidden(), check_list)

class TestEmpty(support.VerifyResults, unittest.TestCase):

def setUp(self):
field = Text(__name__ = 'foo')
request = TestRequest()
request.form['foo'] = u'Foo Value'
self._widget = TextWidget(field, request)
self._widget.setPrefix('')

def testGetData(self):
self.assertEqual(self._widget.getInputValue(), u'Foo Value')

def testRender(self):
check_list = ('id="foo"', 'name="foo"')
self.verifyResult(self._widget(), check_list)
self.verifyResult(self._widget.hidden(), check_list)

def test_suite():
return unittest.TestSuite((
unittest.makeSuite(Test),
unittest.makeSuite(TestEmpty),
))

if __name__=='__main__':
unittest.main(defaultTest='test_suite')
6 changes: 5 additions & 1 deletion browser/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,12 @@ class SimpleInputWidget(BrowserWidget, InputWidget):
>>> widget.error()
''
You can modify the prefix used to create the widget name as follows:
You can use 'setPrefix' to remove or modify the prefix used to create the
widget name as follows:
>>> widget.setPrefix('')
>>> widget.name
'foo'
>>> widget.setPrefix('baz')
>>> widget.name
'baz.foo'
Expand Down
6 changes: 6 additions & 0 deletions tests/test_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ class TestWidget(object):
>>> widget.name
'newprefix.Test'
Using the empty string as prefix leaves the prefix off entirely:
>>> widget.setPrefix('')
>>> widget.name
'Test'
To configure a widget, call setRenderedValue with a value that the
widget should display:
Expand Down

0 comments on commit 43d0929

Please sign in to comment.