[Zope3-checkins] CVS: Zope3/src/zope/app/browser/form/ftests - __init__.py:1.1.2.1 support.py:1.1.2.1 test_checkboxwidget.py:1.1.2.1 test_datetimewidget.py:1.1.2.1 test_filewidget.py:1.1.2.1 test_floatwidget.py:1.1.2.1 test_intwidget.py:1.1.2.1 test_textareawidget.py:1.1.2.1 test_textwidget.py:1.1.2.1

Garrett Smith garrett@mojave-corp.com
Mon, 21 Jul 2003 20:09:04 -0400


Update of /cvs-repository/Zope3/src/zope/app/browser/form/ftests
In directory cvs.zope.org:/tmp/cvs-serv25939

Added Files:
      Tag: garrett-widgets-branch
	__init__.py support.py test_checkboxwidget.py 
	test_datetimewidget.py test_filewidget.py test_floatwidget.py 
	test_intwidget.py test_textareawidget.py test_textwidget.py 
Log Message:
Addition of functional tests.


=== Added File Zope3/src/zope/app/browser/form/ftests/__init__.py ===
#
# This file is necessary to make this directory a package.


=== Added File Zope3/src/zope/app/browser/form/ftests/support.py ===
##############################################################################
#
# 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.0 (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.
#
##############################################################################
"""

$Id: support.py,v 1.1.2.1 2003/07/22 00:08:52 garrett Exp $ # XXX-GDS
"""

import re
from StringIO import StringIO

from zope.configuration.xmlconfig import xmlconfig


def registerEditForm(schema):
    config = StringIO("""
        <zopeConfigure xmlns="http://namespaces.zope.org/browser">
          <editform
            name="edit.html"
            schema="%s"
            permission="zope.View" />
        </zopeConfigure>
        """ % schema.__identifier__)
    xmlconfig(config)


def defineSecurity(class_, schema):
    class_ = '%s.%s' % (class_.__module__, class_.__name__)
    schema = schema.__identifier__
    config = StringIO("""
        <zopeConfigure xmlns="http://namespaces.zope.org/zope">
          <class class="%s">
            <require 
              permission="zope.Public" 
              interface="%s"
              set_schema="%s" />
          </class>
        </zopeConfigure>
        """ % (class_, schema, schema))
    xmlconfig(config)


def defineWidgetView(name, field_interface, widget_class):

    field_interface = field_interface.__identifier__
    widget_class = '%s.%s' % (widget_class.__module__, widget_class.__name__)
    config = StringIO("""
        <zopeConfigure xmlns="http://namespaces.zope.org/browser">
          <page
            name="%s"
            permission="zope.Public"
            allowed_interface="zope.app.interfaces.browser.form.IBrowserWidget"
            for="%s"
            class="%s" />
        </zopeConfigure>
        """ % (name, field_interface, widget_class))
    xmlconfig(config)


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)


def missingInputErrorExists(field, source):

    return validationErrorExists(field, 'Input is required', 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)


=== Added File Zope3/src/zope/app/browser/form/ftests/test_checkboxwidget.py ===
##############################################################################
#
# 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.0 (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.
#
##############################################################################
"""

$Id: test_checkboxwidget.py,v 1.1.2.1 2003/07/22 00:08:52 garrett Exp $ # XXX-GDS
"""

import unittest
from persistence import Persistent
from transaction import get_transaction

from zope.interface import Interface
from zope.interface import implements

from zope.schema import Bool
from zope.app.browser.form.widget import CheckBoxWidget

from support import *
from zope.app.traversing import traverse

from zope.testing.functional import BrowserTestCase


class IBoolTest(Interface):

    b1 = Bool(
        required=True)

    b2 = Bool(
        required=False)


registerEditForm(IBoolTest)


class BoolTest(Persistent):

    implements(IBoolTest)

    def __init__(self):
        self.b1 = True
        self.b2 = False

defineSecurity(BoolTest, IBoolTest)


class Test(BrowserTestCase):


    def test_display_edit_form(self):
        self.getRootFolder().setObject('test', BoolTest())
        get_transaction().commit()

        # display edit view
        response = self.publish('/test/edit.html')
        self.assertEqual(response.getStatus(), 200)

        # b1 and b2 should be displayed in checkbox input fields
        self.assert_(patternExists(
            '<input .* checked="checked".* name="field.b1".* ' \
            'type="checkbox".* />',
            response.getBody()))
        self.assert_(patternExists(
            '<input .* name="field.b2".* type="checkbox".* />',
            response.getBody()))
        # confirm that b2 is *not* checked
        self.assert_(not patternExists(
            '<input .* checked="checked".* name="field.b2".* ' \
            'type="checkbox".* />',
            response.getBody()))


    def test_submit_edit_form(self):
        self.getRootFolder().setObject('test', BoolTest())
        get_transaction().commit()

        # submit edit view
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.b1' : '',
            'field.b2' : 'on' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new values in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.b1, False) 
        self.assertEqual(object.b2, True)


    def test_unexpected_value(self):
        object = BoolTest()
        object.b1 = True
        object.b2 = True
        self.getRootFolder().setObject('test', object)
        get_transaction().commit()

        # submit invalud type for text line
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.b1' : 'true',
            'field.b2' : 'foo' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))

        # values other than 'on' should be treated as False
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.b1, False) 
        self.assertEqual(object.b2, False)


    def test_missing_value(self):
        # Note: checkbox widget doesn't support a missing value. This
        # test confirms that one cannot set a Bool field to None.

        self.getRootFolder().setObject('test', BoolTest())
        get_transaction().commit()

        # confirm default value of b1 is True
        object = traverse(self.getRootFolder(), 'test')
        self.assertEqual(object.b1, True)

        # submit missing for b1
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.b1' : CheckBoxWidget._missing })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # confirm b1 is not missing
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assert_(object.b1 != Bool.missing_value)


def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(Test))
    return suite

if __name__=='__main__':
    unittest.main(defaultTest='test_suite')




=== Added File Zope3/src/zope/app/browser/form/ftests/test_datetimewidget.py ===
##############################################################################
#
# 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.0 (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.
#
##############################################################################
"""

$Id: test_datetimewidget.py,v 1.1.2.1 2003/07/22 00:08:52 garrett Exp $ # XXX-GDS
"""

import unittest
import re
from persistence import Persistent
from transaction import get_transaction
from datetime import datetime
from zope.app.datetimeutils import parseDatetimetz, tzinfo

from zope.interface import Interface
from zope.interface import implements

from zope.schema import Datetime
from zope.schema import EnumeratedDatetime

from support import *
from zope.app.traversing import traverse

from zope.testing.functional import BrowserTestCase


class IDatetimeTest(Interface):

    d1 = Datetime(
        required=True,
        min=datetime(2003, 1, 1, tzinfo=tzinfo(0)),
        max=datetime(2020, 12, 31, tzinfo=tzinfo(0)))

    d2 = Datetime(
        required=False)

    d3 = EnumeratedDatetime(
        required=False,
        allowed_values=(
            datetime(2003, 9, 15, tzinfo=tzinfo(0)), 
            datetime(2003, 10, 15, tzinfo=tzinfo(0))),
        missing_value=datetime(2000, 1, 1, tzinfo=tzinfo(0)))

registerEditForm(IDatetimeTest)


class DatetimeTest(Persistent):

    implements(IDatetimeTest)

    def __init__(self):
        self.d1 = datetime(2003, 4, 6, tzinfo=tzinfo(0))
        self.d2 = datetime(2003, 8, 6, tzinfo=tzinfo(0))
        self.d3 = None

defineSecurity(DatetimeTest, IDatetimeTest)


def getDateForField(field, source):
    """Returns a datetime object for the specified field in source.
    
    Returns None if the field value cannot be converted to date.
    """

    # look in input element first
    pattern = '<input .* name="field.%s".* value="(.*)".*>' % field
    m = re.search(pattern, source)
    if m is None:
        # look in a select element
        pattern = '<select .* name="field.%s".*>.*' \
            '<option value="(.*)" selected>*.</select>' % field
        m = re.search(pattern, source, re.DOTALL)
        if m is None:
            return None

    try:
        return parseDatetimetz(m.group(1))
    except:
        # ignore specifics
        return None


class Test(BrowserTestCase):


    def test_display_edit_form(self):
        self.getRootFolder().setObject('test', DatetimeTest())
        get_transaction().commit()
        object = traverse(self.getRootFolder(), 'test')

        # display edit view
        response = self.publish('/test/edit.html')
        self.assertEqual(response.getStatus(), 200)

        # confirm date values in form with actual values
        self.assertEqual(getDateForField('d1', response.getBody()), object.d1)
        self.assertEqual(getDateForField('d2', response.getBody()), object.d2)
        self.assert_(getDateForField('d3', response.getBody()) is None)


    def test_submit_edit_form(self):
        self.getRootFolder().setObject('test', DatetimeTest())
        get_transaction().commit()

        d1 = datetime(2003, 2, 1, tzinfo=tzinfo(0))
        d2 = datetime(2003, 2, 2, tzinfo=tzinfo(0))
        d3 = datetime(2003, 10, 15, tzinfo=tzinfo(0))

        # submit edit view
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.d1' : str(d1),
            'field.d2' : str(d2),
            'field.d3' : str(d3) })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new values in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()

        self.assertEqual(object.d1, d1) 
        self.assertEqual(object.d2, d2)
        self.assertEqual(object.d3, d3)


    def test_missing_value(self):
        self.getRootFolder().setObject('test', DatetimeTest())
        get_transaction().commit()

        # submit missing values for d2 and d3
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.d2' : '',
            'field.d3' : '' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new values in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assert_(object.d2 is None) # default missing_value for dates
        # 2000-1-1 is missing_value for d3
        self.assertEqual(object.d3, datetime(2000, 1, 1, tzinfo=tzinfo(0)))


    def test_required_validation(self):
        self.getRootFolder().setObject('test', DatetimeTest())
        get_transaction().commit()

        # submit missing values for required field d1
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.d1' : '',
            'field.d2' : '',
            'field.d3' : '' })
        self.assertEqual(response.getStatus(), 200)

        # confirm error msgs
        self.assert_(missingInputErrorExists('d1', response.getBody()))
        self.assert_(not missingInputErrorExists('d2', response.getBody()))
        self.assert_(not missingInputErrorExists('d3', response.getBody()))


    def test_inalid_value(self):
        self.getRootFolder().setObject('test', DatetimeTest())
        get_transaction().commit()

        # submit a value for d3 that isn't allowed
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.d3' : str(datetime(2003, 2, 1, tzinfo=tzinfo(0))) })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(invalidValueErrorExists('d3', response.getBody()))


    def test_min_max_validation(self):
        self.getRootFolder().setObject('test', DatetimeTest())
        get_transaction().commit()

        # submit value for d1 that is too low
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.d1' : str(datetime(2002, 12, 31, tzinfo=tzinfo(0))) })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(validationErrorExists('d1', 'Too small', 
            response.getBody()))

        # submit value for i1 that is too high
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.d1' : str(datetime(2021, 1, 1, tzinfo=tzinfo(0))) })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(validationErrorExists('d1', 'Too big', 
            response.getBody()))


    def test_omitted_value(self):
        self.getRootFolder().setObject('test', DatetimeTest())
        get_transaction().commit()

        # remember default values
        object = traverse(self.getRootFolder(), 'test')
        d1 = object.d1
        d2 = object.d2
        self.assert_(d2 is not None)
        d3 = object.d3

        # submit change with only d2 present -- note that required
        # field d1 is omitted, which should not cause a validation error
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.d2' : '' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new value in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.d1, d1)
        self.assert_(object.d2 is None)
        self.assertEqual(object.d3, d3)


def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(Test))
    return suite

if __name__=='__main__':
    unittest.main(defaultTest='test_suite')




=== Added File Zope3/src/zope/app/browser/form/ftests/test_filewidget.py ===
##############################################################################
#
# 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.0 (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.
#
##############################################################################
"""

$Id: test_filewidget.py,v 1.1.2.1 2003/07/22 00:08:52 garrett Exp $ # XXX-GDS
"""

import unittest
from StringIO import StringIO
from persistence import Persistent
from transaction import get_transaction

from zope.interface import Interface
from zope.interface import implements

from zope.schema.interfaces import IField, IEnumerated
from zope.schema import Field, Enumerated

from zope.app.browser.form.widget import FileWidget

from support import *
from zope.app.traversing import traverse

from zope.testing.functional import BrowserTestCase

class IFileField(IEnumerated, IField):
    """Field for representing a file that can be edited by FileWidget."""


class FileField(Enumerated, Field):

    implements(IFileField)


defineWidgetView('edit', IFileField, FileWidget)


class IFileTest(Interface):

    f1 = FileField()
    f2 = FileField(required=False)

registerEditForm(IFileTest)


class FileTest(Persistent):

    implements(IFileTest)

    def __init__(self):
        self.f1 = None
        self.f2 = 'foo'

defineSecurity(FileTest, IFileTest)


class SampleTextFile(StringIO):

    def __init__(self, buf, filename=''):
        StringIO.__init__(self, buf)
        self.filename = filename


class Test(BrowserTestCase):

    sampleText = "The quick brown fox\njumped over the lazy dog."
    sampleTextFile = SampleTextFile(sampleText)

    emptyFileName = 'empty.txt'
    emptyFile = SampleTextFile('', emptyFileName)


    def test_display_edit_form(self):
        self.getRootFolder().setObject('test', FileTest())
        get_transaction().commit()

        # display edit view
        response = self.publish('/test/edit.html')
        self.assertEqual(response.getStatus(), 200)

        # field should be displayed in a file input element
        self.assert_(patternExists(
            '<input .* name="field.f1".* type="file".*>', response.getBody()))
        self.assert_(patternExists(
            '<input .* name="field.f2".* type="file".*>', response.getBody()))


    def test_submit_text(self):
        self.getRootFolder().setObject('test', FileTest())
        get_transaction().commit()
        object = traverse(self.getRootFolder(), 'test')
        self.assert_(object.f1 is None)
        self.assertEqual(object.f2, 'foo')

        # submit a sample text file
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.f1' : self.sampleTextFile,
            'field.f2' : self.sampleTextFile })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new values in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.f1, self.sampleText)
        self.assertEqual(object.f2, self.sampleText)


    def XXX_test_invalid_value(self):
        self.getRootFolder().setObject('test', FileTest())
        get_transaction().commit()

        # submit an invalid file value
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.f1' : 'not a file' })
        self.assertEqual(response.getStatus(), 200)

        print response.getBody()

        self.assert_(validationErrorExists('f1', 
            'Value is not a file object', response.getBody()))


    def XXX_test_required_validation(self):
        self.getRootFolder().setObject('test', TextLineTest())
        get_transaction().commit()

        # submit missing values for required field s1
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.f1' : sampleTextFile,
            'field.f2' : '' })
        self.assertEqual(response.getStatus(), 200)

        # confirm error msgs
        self.assert_(missingInputErrorExists('s1', response.getBody()))
        self.assert_(not missingInputErrorExists('s2', response.getBody()))



    def test_empty_file(self):
        self.getRootFolder().setObject('test', FileTest())
        get_transaction().commit()

        # submit an empty text file
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.f2' : self.emptyFile })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # new value for f1 should be field.missing_value (i.e, None)
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assert_(object.f1 is None)


def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(Test))
    return suite

if __name__=='__main__':
    unittest.main(defaultTest='test_suite')




=== Added File Zope3/src/zope/app/browser/form/ftests/test_floatwidget.py ===
##############################################################################
#
# 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.0 (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.
#
##############################################################################
"""

$Id: test_floatwidget.py,v 1.1.2.1 2003/07/22 00:08:52 garrett Exp $ # XXX-GDS
"""

import unittest
from persistence import Persistent
from transaction import get_transaction

from support import *

from zope.interface import Interface
from zope.interface import implements

from zope.schema import Float
from zope.schema import EnumeratedFloat

from zope.app.traversing import traverse

from zope.testing.functional import BrowserTestCase


class IFloatTest(Interface):

    f1 = Float(
        required=True,
        min=1.1,
        max=10.1)

    f2 = Float(
        required=False)

    f3 = EnumeratedFloat(
        required=False,
        allowed_values=(0.0, 1.1, 2.1, 3.1, 5.1, 7.1, 11.1),
        missing_value=0)

registerEditForm(IFloatTest)


class FloatTest(Persistent):

    implements(IFloatTest)

    def __init__(self):
        self.f1 = None
        self.f2 = 1.1
        self.f3 = 2.1

defineSecurity(FloatTest, IFloatTest)


class Test(BrowserTestCase):


    def test_display_edit_form(self):
        self.getRootFolder().setObject('test', FloatTest())
        get_transaction().commit()

        # display edit view
        response = self.publish('/test/edit.html')
        self.assertEqual(response.getStatus(), 200)

        # f1 and f2 should be displayed in text fields
        self.assert_(patternExists(
            '<input .* name="field.f1".* value="".*>', response.getBody()))
        self.assert_(patternExists(
            '<input .* name="field.f2".* value="1.1".*>', response.getBody()))

        # f3 should be in a dropdown
        self.assert_(patternExists(
            '<select .* name="field.f3".*>', response.getBody()))
        self.assert_(patternExists(
            '<option value="2.1" selected>2.1</option>', response.getBody()))


    def test_submit_edit_form(self):
        self.getRootFolder().setObject('test', FloatTest())
        get_transaction().commit()

        # submit edit view
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.f1' : '1.123',
            'field.f2' : '2.23456789012345',
            'field.f3' : '11.1' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new values in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.f1, 1.123) 
        self.assertEqual(object.f2, 2.23456789012345)
        self.assertEqual(object.f3, 11.1)


    def test_missing_value(self):
        self.getRootFolder().setObject('test', FloatTest())
        get_transaction().commit()

        # submit missing values for f2 and f3
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.f1' : '1.1',
            'field.f2' : '',
            'field.f3' : '' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new values in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.f1, 1.1) 
        self.assertEqual(object.f2, None) # None is default missing_value
        self.assertEqual(object.f3, 0)  # 0 is from f3.missing_value=0


    def test_required_validation(self):
        self.getRootFolder().setObject('test', FloatTest())
        get_transaction().commit()

        # submit missing values for required field f1
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.f1' : '',
            'field.f2' : '',
            'field.f3' : '' })
        self.assertEqual(response.getStatus(), 200)

        # confirm error msgs
        self.assert_(missingInputErrorExists('f1', response.getBody()))
        self.assert_(not missingInputErrorExists('f2', response.getBody()))
        self.assert_(not missingInputErrorExists('f3', response.getBody()))


    def test_invalid_allowed_value(self):
        self.getRootFolder().setObject('test', FloatTest())
        get_transaction().commit()

        # submit a value for f3 that isn't allowed
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.f3' : '10000' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(invalidValueErrorExists('f3', response.getBody()))


    def test_min_max_validation(self):
        self.getRootFolder().setObject('test', FloatTest())
        get_transaction().commit()

        # submit value for f1 that is too low
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.f1' : '-1' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(validationErrorExists('f1', 'Too small', 
            response.getBody()))

        # submit value for f1 that is too high
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.f1' : '1000.2' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(validationErrorExists('f1', 'Too big', 
            response.getBody()))


    def test_omitted_value(self):
        self.getRootFolder().setObject('test', FloatTest())
        get_transaction().commit()

        # confirm default values
        object = traverse(self.getRootFolder(), 'test')
        self.assert_(object.f1 is None)
        self.assertEqual(object.f2, 1.1)
        self.assertEqual(object.f3, 2.1)

        # submit change with only f2 present -- note that required
        # field f1 is omitted, which should not cause a validation error
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.f2' : '' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new value in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assert_(object.f1 is None) 
        self.assert_(object.f2 is None)
        self.assertEqual(object.f3, 2.1)


    def test_conversion(self):
        self.getRootFolder().setObject('test', FloatTest())
        get_transaction().commit()

        # submit value for f1 that cannot be convert to an float
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.f1' : 'foo' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(validationErrorExists('f1', 
            'Invalid floating point data', response.getBody()))


def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(Test))
    return suite

if __name__=='__main__':
    unittest.main(defaultTest='test_suite')



=== Added File Zope3/src/zope/app/browser/form/ftests/test_intwidget.py ===
##############################################################################
#
# 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.0 (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.
#
##############################################################################
"""

$Id: test_intwidget.py,v 1.1.2.1 2003/07/22 00:08:52 garrett Exp $ # XXX-GDS
"""

import unittest
from persistence import Persistent
from transaction import get_transaction

from support import *

from zope.interface import Interface
from zope.interface import implements

from zope.schema import Int
from zope.schema import EnumeratedInt

from zope.app.traversing import traverse

from zope.testing.functional import BrowserTestCase


class IIntTest(Interface):

    i1 = Int(
        required=True,
        min=1,
        max=10)

    i2 = Int(
        required=False)

    i3 = EnumeratedInt(
        required=False,
        allowed_values=(0, 1, 2, 3, 5, 7, 11),
        missing_value=0)

registerEditForm(IIntTest)


class IIntTest2(Interface):
    """Used to test an unusual care where missing_value is -1 and
    not in allowed_values."""

    i1 = EnumeratedInt(
        required=False,
        missing_value=-1,
        allowed_values=(10, 20, 30))

registerEditForm(IIntTest2)


class IntTest(Persistent):

    implements(IIntTest)

    def __init__(self):
        self.i1 = None
        self.i2 = 1
        self.i3 = 2

defineSecurity(IntTest, IIntTest)


class IntTest2(Persistent):

    implements(IIntTest2)

    def __init__(self):
        self.i1 = 10

defineSecurity(IntTest2, IIntTest2)


class Test(BrowserTestCase):


    def test_display_edit_form(self):
        self.getRootFolder().setObject('test', IntTest())
        get_transaction().commit()

        # display edit view
        response = self.publish('/test/edit.html')
        self.assertEqual(response.getStatus(), 200)

        # i1 and i2 should be displayed in text fields
        self.assert_(patternExists(
            '<input .* name="field.i1".* value="".*>', response.getBody()))
        self.assert_(patternExists(
            '<input .* name="field.i2".* value="1".*>', response.getBody()))

        # i3 should be in a dropdown
        self.assert_(patternExists(
            '<select .* name="field.i3".*>', response.getBody()))
        self.assert_(patternExists(
            '<option value="2" selected>2</option>', response.getBody()))


    def test_submit_edit_form(self):
        self.getRootFolder().setObject('test', IntTest())
        get_transaction().commit()

        # submit edit view
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.i1' : '1',
            'field.i2' : '2',
            'field.i3' : '3' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new values in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.i1, 1) 
        self.assertEqual(object.i2, 2)
        self.assertEqual(object.i3, 3)


    def test_missing_value(self):
        self.getRootFolder().setObject('test', IntTest())
        get_transaction().commit()

        # submit missing values for i2 and i3
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.i1' : '1',
            'field.i2' : '',
            'field.i3' : '' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new values in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.i1, 1) 
        self.assertEqual(object.i2, None) # None is default missing_value
        self.assertEqual(object.i3, 0)  # 0 is from i3.missing_value=0


    def test_alternative_missing_value(self):
        """Tests the addition of an empty value at the top of the dropdown
        that, when selected, updates the field with field.missing_value.
        """
    
        self.getRootFolder().setObject('test', IntTest2()) # note alt. class
        get_transaction().commit()

        # display edit form
        response = self.publish('/test/edit.html')
        self.assertEqual(response.getStatus(), 200)

        # confirm that i1 is has a blank item at top with value=""
        self.assert_(patternExists(
            '<select .* name="field.i1".*>', response.getBody()))
        self.assert_(patternExists(
            '<option value=""></option>', response.getBody()))
        self.assert_(patternExists(
            '<option value="10" selected>10</option>', response.getBody()))

        # submit form as if top item is selected
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.i1' : '' })

        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # confirm new value is -1 -- i1.missing_value
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.i1, -1) 


    def test_required_validation(self):
        self.getRootFolder().setObject('test', IntTest())
        get_transaction().commit()

        # submit missing values for required field i1
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.i1' : '',
            'field.i2' : '',
            'field.i3' : '' })
        self.assertEqual(response.getStatus(), 200)

        # confirm error msgs
        self.assert_(missingInputErrorExists('i1', response.getBody()))
        self.assert_(not missingInputErrorExists('i2', response.getBody()))
        self.assert_(not missingInputErrorExists('i3', response.getBody()))


    def test_invalid_allowed_value(self):
        self.getRootFolder().setObject('test', IntTest())
        get_transaction().commit()

        # submit a value for i3 that isn't allowed
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.i3' : '12' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(invalidValueErrorExists('i3', response.getBody()))


    def test_min_max_validation(self):
        self.getRootFolder().setObject('test', IntTest())
        get_transaction().commit()

        # submit value for i1 that is too low
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.i1' : '-1' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(validationErrorExists('i1', 'Too small', 
            response.getBody()))

        # submit value for i1 that is too high
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.i1' : '11' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(validationErrorExists('i1', 'Too big', 
            response.getBody()))


    def test_omitted_value(self):
        self.getRootFolder().setObject('test', IntTest())
        get_transaction().commit()

        # confirm default values
        object = traverse(self.getRootFolder(), 'test')
        self.assert_(object.i1 is None)
        self.assertEqual(object.i2, 1)
        self.assertEqual(object.i3, 2)

        # submit change with only i2 present -- note that required
        # field i1 is omitted, which should not cause a validation error
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.i2' : '' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new value in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assert_(object.i1 is None) 
        self.assert_(object.i2 is None)
        self.assertEqual(object.i3, 2)


    def test_conversion(self):
        self.getRootFolder().setObject('test', IntTest())
        get_transaction().commit()

        # submit value for i1 that cannot be convert to an int
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.i1' : 'foo' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(validationErrorExists('i1', 'Invalid integer data', 
            response.getBody()))


def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(Test))
    return suite

if __name__=='__main__':
    unittest.main(defaultTest='test_suite')


=== Added File Zope3/src/zope/app/browser/form/ftests/test_textareawidget.py ===
##############################################################################
#
# 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.0 (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.
#
##############################################################################
"""

$Id: test_textareawidget.py,v 1.1.2.1 2003/07/22 00:08:52 garrett Exp $ # XXX-GDS
"""

import unittest
from persistence import Persistent
from transaction import get_transaction

from zope.interface import Interface
from zope.interface import implements

from zope.schema import Text

from support import *
from zope.app.traversing import traverse

from zope.testing.functional import BrowserTestCase


class ITextTest(Interface):

    s1 = Text(
        required=True,
        min_length=2,
        max_length=10)

    s2 = Text(
        required=False)

    s3 = Text(
        required=False,
        missing_value=None)

registerEditForm(ITextTest)


class TextTest(Persistent):

    implements(ITextTest)

    def __init__(self):
        self.s1 = ''
        self.s2 = u'foo'
        self.s3 = None

defineSecurity(TextTest, ITextTest)


class Test(BrowserTestCase):


    def test_display_edit_form(self):
        self.getRootFolder().setObject('test', TextTest())
        get_transaction().commit()

        # display edit view
        response = self.publish('/test/edit.html')
        self.assertEqual(response.getStatus(), 200)

        # all fields should be displayed in text fields
        self.assert_(patternExists(
            '<textarea .* name="field.s1".*></textarea>', 
            response.getBody()))
        self.assert_(patternExists(
            '<textarea .* name="field.s2".*>foo</textarea>', 
            response.getBody()))
        self.assert_(patternExists(
            '<textarea .* name="field.s3".*></textarea>', 
            response.getBody()))


    def test_submit_edit_form(self):
        self.getRootFolder().setObject('test', TextTest())
        get_transaction().commit()

        # submit edit view
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s1' : u'foo',
            'field.s2' : u'bar',
            'field.s3' : u'baz' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new values in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.s1, u'foo') 
        self.assertEqual(object.s2, u'bar')
        self.assertEqual(object.s3, u'baz')


    def test_inalid_type(self):
        self.getRootFolder().setObject('test', TextTest())
        get_transaction().commit()

        # submit invalid type for text
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s1' : 'foo' }) # not unicode

        self.assertEqual(response.getStatus(), 200)
        self.assert_(patternExists(
            'name="field.s1".*Wrong type', response.getBody()))


    def test_missing_value(self):
        self.getRootFolder().setObject('test', TextTest())
        get_transaction().commit()

        # submit missing values for s2 and s3
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s1' : u'foo',
            'field.s2' : '',
            'field.s3' : '' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new value in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.s1, u'foo') 
        self.assertEqual(object.s2, u'')   # default missing_value
        self.assertEqual(object.s3, None)  # None is s3's missing_value


    def test_required_validation(self):
        self.getRootFolder().setObject('test', TextTest())
        get_transaction().commit()

        # submit missing values for required field s1
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s1' : '',
            'field.s2' : '',
            'field.s3' : '' })
        self.assertEqual(response.getStatus(), 200)

        # confirm error msgs
        self.assert_(missingInputErrorExists('s1', response.getBody()))
        self.assert_(not missingInputErrorExists('s2', response.getBody()))
        self.assert_(not missingInputErrorExists('s3', response.getBody()))


    def test_length_validation(self):
        self.getRootFolder().setObject('test', TextTest())
        get_transaction().commit()

        # submit value for s1 that is too short
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s1' : u'a' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(patternExists(
            'name="field.s1".*Too short', response.getBody()))

        # submit value for s1 that is too long
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s1' : u'12345678901' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(validationErrorExists('s1', 'Too long', 
            response.getBody()))


    def test_omitted_value(self):
        self.getRootFolder().setObject('test', TextTest())
        get_transaction().commit()

        # confirm default values
        object = traverse(self.getRootFolder(), 'test')
        self.assertEqual(object.s1, '')
        self.assertEqual(object.s2, u'foo')
        self.assert_(object.s3 is None)

        # submit change with only s2 present -- note that required
        # field s1 is omitted, which should not cause a validation error
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s2' : u'bar' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new values in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.s1, '')
        self.assertEqual(object.s2, u'bar')
        self.assert_(object.s3 is None)


    def test_conversion(self):
        self.getRootFolder().setObject('test', TextTest())
        get_transaction().commit()

        # confirm that line terminators are converted correctly on post
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s2' : u'line1\r\nline2' }) # CRLF per RFC 822
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.s2, u'line1\nline2')

        # confirm conversion to HTML
        response = self.publish('/test/edit.html')
        self.assertEqual(response.getStatus(), 200)
        self.assert_(patternExists('line1\r\nline2', response.getBody()))



def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(Test))
    return suite

if __name__=='__main__':
    unittest.main(defaultTest='test_suite')



=== Added File Zope3/src/zope/app/browser/form/ftests/test_textwidget.py ===
##############################################################################
#
# 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.0 (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.
#
##############################################################################
"""

$Id: test_textwidget.py,v 1.1.2.1 2003/07/22 00:08:52 garrett Exp $ # XXX-GDS
"""

import unittest
from persistence import Persistent
from transaction import get_transaction

from zope.interface import Interface
from zope.interface import implements

from zope.schema import TextLine
from zope.schema import EnumeratedTextLine

from support import *
from zope.app.traversing import traverse

from zope.testing.functional import BrowserTestCase


class ITextLineTest(Interface):

    s1 = TextLine(
        required=True,
        min_length=2,
        max_length=10)

    s2 = TextLine(
        required=False)

    s3 = EnumeratedTextLine(
        required=False,
        allowed_values=(u'Bob', u'is', u'*Your*', u'Uncle'),
        missing_value=None)

registerEditForm(ITextLineTest)


class TextLineTest(Persistent):

    implements(ITextLineTest)

    def __init__(self):
        self.s1 = ''
        self.s2 = u'foo'
        self.s3 = None

defineSecurity(TextLineTest, ITextLineTest)


class Test(BrowserTestCase):


    def test_display_edit_form(self):
        self.getRootFolder().setObject('test', TextLineTest())
        get_transaction().commit()

        # display edit view
        response = self.publish('/test/edit.html')
        self.assertEqual(response.getStatus(), 200)

        # s1 and s2 should be displayed in text fields
        self.assert_(patternExists(
            '<input .* name="field.s1".* value="".*>', response.getBody()))
        self.assert_(patternExists(
            '<input .* name="field.s2".* value="foo".*>', response.getBody()))

        # s3 should be in a dropdown
        self.assert_(patternExists(
            '<select .* name="field.s3".*>', response.getBody()))
        self.assert_(patternExists(
            '<option value="" selected></option>', response.getBody()))


    def test_submit_edit_form(self):
        self.getRootFolder().setObject('test', TextLineTest())
        get_transaction().commit()

        # submit edit view
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s1' : u'foo',
            'field.s2' : u'bar',
            'field.s3' : u'Uncle' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new values in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.s1, u'foo') 
        self.assertEqual(object.s2, u'bar')
        self.assertEqual(object.s3, u'Uncle')


    def test_inalid_type(self):
        self.getRootFolder().setObject('test', TextLineTest())
        get_transaction().commit()

        # submit invalud type for text line
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s1' : 'foo' }) # not unicode

        self.assertEqual(response.getStatus(), 200)
        self.assert_(patternExists(
            'name="field.s1".*Wrong type', response.getBody()))


    def test_missing_value(self):
        self.getRootFolder().setObject('test', TextLineTest())
        get_transaction().commit()

        # submit missing values for s2 and s3
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s1' : u'foo',
            'field.s2' : '',
            'field.s3' : '' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new values in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.s1, u'foo') 
        self.assertEqual(object.s2, u'')   # default missing_value
        self.assertEqual(object.s3, None)  # None is s3's missing_value


    def test_required_validation(self):
        self.getRootFolder().setObject('test', TextLineTest())
        get_transaction().commit()

        # submit missing values for required field s1
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s1' : '',
            'field.s2' : '',
            'field.s3' : '' })
        self.assertEqual(response.getStatus(), 200)

        # confirm error msgs
        self.assert_(missingInputErrorExists('s1', response.getBody()))
        self.assert_(not missingInputErrorExists('s2', response.getBody()))
        self.assert_(not missingInputErrorExists('s3', response.getBody()))


    def test_inalid_value(self):
        self.getRootFolder().setObject('test', TextLineTest())
        get_transaction().commit()

        # submit a value for s3 that isn't allowed
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s3' : u'Bob is *Not* My Uncle' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(invalidValueErrorExists('s3', response.getBody()))


    def test_length_validation(self):
        self.getRootFolder().setObject('test', TextLineTest())
        get_transaction().commit()

        # submit value for s1 that is too short
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s1' : u'a' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(patternExists(
            'name="field.s1".*Too short', response.getBody()))

        # submit value for s1 that is too long
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s1' : u'12345678901' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(validationErrorExists('s1', 'Too long', 
            response.getBody()))


    def test_omitted_value(self):
        self.getRootFolder().setObject('test', TextLineTest())
        get_transaction().commit()

        # confirm default values
        object = traverse(self.getRootFolder(), 'test')
        self.assertEqual(object.s1, '')
        self.assertEqual(object.s2, u'foo')
        self.assert_(object.s3 is None)

        # submit change with only s2 present -- note that required
        # field s1 is omitted, which should not cause a validation error
        response = self.publish('/test/edit.html', form={
            'UPDATE_SUBMIT' : '',
            'field.s2' : u'bar' })
        self.assertEqual(response.getStatus(), 200)
        self.assert_(updatedMsgExists(response.getBody()))
        
        # check new value in object
        object = traverse(self.getRootFolder(), 'test')
        object._p_jar.sync()
        self.assertEqual(object.s1, '')
        self.assertEqual(object.s2, u'bar')
        self.assert_(object.s3 is None)


def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(Test))
    return suite

if __name__=='__main__':
    unittest.main(defaultTest='test_suite')