[Zope3-checkins]
SVN: Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/
Tested all possible control scenarios. Fixed behavior of
unvalued single
Stephan Richter
srichter at cosmos.phy.tufts.edu
Wed Jul 27 17:27:31 EDT 2005
Log message for revision 37500:
Tested all possible control scenarios. Fixed behavior of unvalued single
checkboxes along the way.
Changed:
U Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/README.txt
U Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/browser.py
A Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/ftests/controls.html
U Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/interfaces.py
-=-
Modified: Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/README.txt
===================================================================
--- Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/README.txt 2005-07-27 20:40:46 UTC (rev 37499)
+++ Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/README.txt 2005-07-27 21:27:30 UTC (rev 37500)
@@ -250,9 +250,281 @@
--------
One of the most important features of the browser is the ability to inspect
-and fill in values for the controls of input forms.
+and fill in values for the controls of input forms. To do so, let's first open
+a page that has a bunch of controls:
+ >>> browser.open('http://localhost/@@/testbrowser/controls.html')
+
+Control Mappings
+~~~~~~~~~~~~~~~~
+
+You can look up a control's value from a mapping attribute:
+
+ >>> browser.controls['text-value']
+ 'Some Text'
+
+The key is matched against the value, id and name of the control. The
+`controls` mapping provides oterh functions too:
+
+ - Getting the value with a default option:
+
+ >>> browser.controls.get('text-value')
+ 'Some Text'
+ >>> browser.controls.get('foo-value', 42)
+ 42
+
+ - Asking for existence:
+
+ >>> 'text-value' in browser.controls
+ True
+ >>> 'foo-value' in browser.controls
+ False
+
+ - Setting an item to a new value:
+
+ >>> browser.controls['text-value'] = 'Some other Text'
+ >>> browser.controls['text-value']
+ 'Some other Text'
+
+ - Updating a lot of values at once:
+
+ >>> browser.controls['password-value']
+ 'Password'
+
+ >>> browser.controls.update({'text-value': 'More Text',
+ ... 'password-value': 'pass now'})
+
+ >>> browser.controls['text-value']
+ 'More Text'
+ >>> browser.controls['password-value']
+ 'pass now'
+
+
+Control Objects
+~~~~~~~~~~~~~~~
+
+But the value of a control is not always everything that there is to know or
+interesting. In those cases, one can access the control object:
+
+ >>> ctrl = browser.getControl('text-value')
+ >>> ctrl
+ Control(name='text-value', type='text')
+
+The string passed into the function will be matched against the value, id and
+name of the control. The control has several useful attributes:
+
+ - the name as which the control is known to the form:
+
+ >>> ctrl.name
+ 'text-value'
+
+ - the value of the control; this attribute can also be set, of course:
+
+ >>> ctrl.value
+ 'More Text'
+ >>> ctrl.value = 'Some Text'
+
+ - the type of the control:
+
+ >>> ctrl.type
+ 'text'
+
+ - a flag describing whether the control is disabled:
+
+ >>> ctrl.disabled
+ False
+
+ - another flag describing whether the value can be changed; this might seem
+ strange, but for example hidden field values cannot be modified:
+
+ >>> ctrl.readonly
+ False
+
+ - there is a flag to tell us whether the control can have multiple values:
+
+ >>> ctrl.multiple
+
+ - and finally there is an attribute that provides all available value
+ options. This is of course not sensible for a text input control and thus
+ not available:
+
+ >>> ctrl.options
+ Traceback (most recent call last):
+ ...
+ AttributeError: options
+
+
+Various Controls
+~~~~~~~~~~~~~~~~
+
+There are various types of controls. They are demonstrated here.
+
+ - Text Control
+
+ The text control we already introduced above.
+
+ - Password Control
+
+ >>> ctrl = browser.getControl('password-value')
+ >>> ctrl
+ Control(name='password-value', type='password')
+ >>> ctrl.value
+ 'pass now'
+ >>> ctrl.value = 'Password'
+ >>> ctrl.disabled
+ False
+ >>> ctrl.readonly
+ False
+ >>> ctrl.multiple
+ >>> ctrl.options
+ Traceback (most recent call last):
+ ...
+ AttributeError: options
+
+ - Hidden Control
+
+ >>> ctrl = browser.getControl('hidden-value')
+ >>> ctrl
+ Control(name='hidden-value', type='hidden')
+ >>> ctrl.value
+ 'Hidden'
+ >>> ctrl.value = 'More Hidden'
+ Traceback (most recent call last):
+ ...
+ AttributeError: control 'hidden-value' is readonly
+ >>> ctrl.disabled
+ False
+ >>> ctrl.readonly
+ True
+ >>> ctrl.multiple
+ >>> ctrl.options
+ Traceback (most recent call last):
+ ...
+ AttributeError: options
+
+ - Text Area Control
+
+ >>> ctrl = browser.getControl('textarea-value')
+ >>> ctrl
+ Control(name='textarea-value', type='textarea')
+ >>> ctrl.value
+ '\n Text inside\n area!\n '
+ >>> ctrl.value = 'A lot of\n text.'
+ >>> ctrl.disabled
+ False
+ >>> ctrl.readonly
+ False
+ >>> ctrl.multiple
+ >>> ctrl.options
+ Traceback (most recent call last):
+ ...
+ AttributeError: options
+
+ - File Control
+
+ >>> ctrl = browser.getControl('file-value')
+ >>> ctrl
+ Control(name='file-value', type='file')
+ >>> ctrl.value
+ >>> import cStringIO
+ >>> ctrl.value = cStringIO.StringIO('File contents')
+ >>> ctrl.disabled
+ False
+ >>> ctrl.readonly
+ False
+ >>> ctrl.multiple
+ >>> ctrl.options
+ Traceback (most recent call last):
+ ...
+ AttributeError: options
+
+ - Selection Control (Single-Valued)
+
+ >>> ctrl = browser.getControl('single-select-value')
+ >>> ctrl
+ Control(name='single-select-value', type='select')
+ >>> ctrl.value
+ ['1']
+ >>> ctrl.value = ['2']
+ >>> ctrl.disabled
+ False
+ >>> ctrl.readonly
+ False
+ >>> ctrl.multiple
+ False
+ >>> ctrl.options
+ ['1', '2', '3']
+
+ - Selection Control (Multi-Valued)
+
+ >>> ctrl = browser.getControl('multi-select-value')
+ >>> ctrl
+ Control(name='multi-select-value', type='select')
+ >>> ctrl.value
+ []
+ >>> ctrl.value = ['1', '2']
+ >>> ctrl.disabled
+ False
+ >>> ctrl.readonly
+ False
+ >>> ctrl.multiple
+ True
+ >>> ctrl.options
+ ['1', '2', '3']
+
+ - Checkbox Control (Single-Valued; Unvalued)
+
+ >>> ctrl = browser.getControl('single-unvalued-checkbox-value')
+ >>> ctrl
+ Control(name='single-unvalued-checkbox-value', type='checkbox')
+ >>> ctrl.value
+ True
+ >>> ctrl.value = False
+ >>> ctrl.disabled
+ False
+ >>> ctrl.readonly
+ False
+ >>> ctrl.multiple
+ True
+ >>> ctrl.options
+ ['on']
+
+ - Checkbox Control (Single-Valued, Valued)
+
+ >>> ctrl = browser.getControl('single-valued-checkbox-value')
+ >>> ctrl
+ Control(name='single-valued-checkbox-value', type='checkbox')
+ >>> ctrl.value
+ ['1']
+ >>> ctrl.value = []
+ >>> ctrl.disabled
+ False
+ >>> ctrl.readonly
+ False
+ >>> ctrl.multiple
+ True
+ >>> ctrl.options
+ ['1']
+
+ - Checkbox Control (Multi-Valued)
+
+ >>> ctrl = browser.getControl('multi-checkbox-value')
+ >>> ctrl
+ Control(name='multi-checkbox-value', type='checkbox')
+ >>> ctrl.value
+ ['1', '3']
+ >>> ctrl.value = ['1', '2']
+ >>> ctrl.disabled
+ False
+ >>> ctrl.readonly
+ False
+ >>> ctrl.multiple
+ True
+ >>> ctrl.options
+ ['1', '2', '3']
+
+
Forms
-----
@@ -325,61 +597,7 @@
## >>> form.controls['portlet_action']
## '...'
-More Forms
-----------
-Now, let's navegate to a page with a slightly more complex form.
-
- >>> browser.click('Registration')
- >>> browser.click('Advanced Options')
- >>> browser.click('UtilityRegistration')
-
-Is the expected control on the page?
-
- >>> 'field.permission' in browser.controls
- True
-
-Good, let's retrieve it then:
-
- >>> permission = browser.getControl('field.permission')
-
-What kind of control is it?
-
- >>> permission.type
- 'select'
-
-Is it a single- or multi-select?
-
- >>> permission.multiple
- False
-
-What options are available for the "field.permission" control?
-
- >>> permission.options
- ['', 'zope.Public', ... 'zope.ManageContent', ... 'zope.View', ...]
-
-
-We'll store the current setting so we can set it back later.
-
- >>> original_permission = permission.value
-
-Let's set one of the options and submit the form.
-
- >>> permission.value = ['zope.Public']
- >>> browser.click('Change')
-
-Ok, did our change take effect? (Note that the order may not be preserved for
-multi-selects.)
-
- >>> browser.controls['field.permission'] == ['zope.Public']
- True
-
-Let's set it back, so we don't mess anything up.
-
- >>> permission.value = original_permission
- >>> browser.click('Change')
-
-
Handling Errors
---------------
Modified: Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/browser.py
===================================================================
--- Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/browser.py 2005-07-27 20:40:46 UTC (rev 37499)
+++ Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/browser.py 2005-07-27 21:27:30 UTC (rev 37500)
@@ -99,8 +99,8 @@
def open(self, url, data=None):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
-
self.mech_browser.open(url, data)
+ self._changed()
def reload(self):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
@@ -201,7 +201,7 @@
def __getattr__(self, name):
# See zope.app.testing.testbrowser.interfaces.IControl
- names = ['options', 'disabled', 'type', 'name', 'readonly', 'multiple']
+ names = ['disabled', 'type', 'name', 'readonly', 'multiple']
if name in names:
return getattr(self.mech_control, name, None)
else:
@@ -210,16 +210,18 @@
@apply
def value():
"""See zope.app.testing.testbrowser.interfaces.IControl"""
+
def fget(self):
value = self.mech_control.value
- if self.mech_control.type == 'checkbox':
+ if self.type == 'checkbox' and self.options == ['on']:
value = bool(value)
return value
+
def fset(self, value):
if self.mech_control.type == 'file':
self.mech_control.add_file(value)
return
- if self.mech_control.type == 'checkbox':
+ if self.type == 'checkbox' and self.options == ['on']:
if value:
value = ['on']
else:
@@ -238,7 +240,10 @@
except:
raise AttributeError('options')
+ def __repr__(self):
+ return "Control(name='%s', type='%s')" %(self.name, self.type)
+
class FormsMapping(object):
"""All forms on the page of the browser."""
zope.interface.implements(interfaces.IFormsMapping)
@@ -288,12 +293,12 @@
raise KeyError(key)
return Control(control).value
- def __setitem__(self, key, value):
- """See zope.app.testing.testbrowser.interfaces.IControlsMapping"""
- form, control = self.browser._findControl(key, key, key)
- if control is None:
- raise KeyError(key)
- Control(control).value = value
+ def get(self, key, default=None):
+ """See zope.interface.common.mapping.IReadMapping"""
+ try:
+ return self[key]
+ except KeyError:
+ return default
def __contains__(self, item):
"""See zope.app.testing.testbrowser.interfaces.IControlsMapping"""
@@ -304,6 +309,13 @@
else:
return True
+ def __setitem__(self, key, value):
+ """See zope.app.testing.testbrowser.interfaces.IControlsMapping"""
+ form, control = self.browser._findControl(key, key, key)
+ if control is None:
+ raise KeyError(key)
+ Control(control).value = value
+
def update(self, mapping):
"""See zope.app.testing.testbrowser.interfaces.IControlsMapping"""
for k, v in mapping.items():
Added: Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/ftests/controls.html
===================================================================
--- Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/ftests/controls.html 2005-07-27 20:40:46 UTC (rev 37499)
+++ Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/ftests/controls.html 2005-07-27 21:27:30 UTC (rev 37500)
@@ -0,0 +1,76 @@
+<html>
+ <body>
+
+ <h1>Controls Tests</h1>
+
+ <form action="controls.html" method="post">
+
+ <em tal:condition="request/text-value|nothing"
+ tal:content="request/text-value" />
+ <input type="text" name="text-value" value="Some Text" />
+
+ <em tal:condition="request/password-value|nothing"
+ tal:content="request/password-value" />
+ <input type="password" name="password-value" value="Password" />
+
+ <em tal:condition="request/hidden-value|nothing"
+ tal:content="request/hidden-value" />
+ <input type="hidden" name="hidden-value" value="Hidden" />
+
+ <em tal:condition="request/textarea-value|nothing"
+ tal:content="request/textarea-value" />
+ <textarea name="textarea-value">
+ Text inside
+ area!
+ </textarea>
+
+ <em tal:condition="request/file-value|nothing"
+ tal:content="request/file-value" />
+ <input type="file" name="file-value" />
+
+ <em tal:condition="request/single-select-value|nothing"
+ tal:content="request/single-select-value" />
+ <select name="single-select-value">
+ <option value="1">One</option>
+ <option value="2">Two</option>
+ <option value="3">Three</option>
+ </select>
+
+ <em tal:condition="request/multi-select-value|nothing"
+ tal:content="request/multi-select-value" />
+ <select name="multi-select-value" multiple="multiple">
+ <option value="1">One</option>
+ <option value="2">Two</option>
+ <option value="3">Three</option>
+ </select>
+
+ <em tal:condition="request/single-unvalued-checkbox-value|nothing"
+ tal:content="request/single-unvalued-checkbox-value" />
+ <input type="checkbox" name="single-unvalued-checkbox-value"
+ checked="checked" />
+
+ <em tal:condition="request/single-valued-checkbox-value|nothing"
+ tal:content="request/single-valued-checkbox-value" />
+ <input type="checkbox" name="single-valued-checkbox-value"
+ value="1" checked="checked" />
+
+ <em tal:condition="request/multi-checkbox-value|nothing"
+ tal:content="request/multi-checkbox-value" />
+ <input type="checkbox" name="multi-checkbox-value" value="1"
+ checked="checked" />
+ <input type="checkbox" name="multi-checkbox-value" value="2" />
+ <input type="checkbox" name="multi-checkbox-value" value="3"
+ checked="checked" />
+
+ <em tal:condition="request/radio-value|nothing"
+ tal:content="request/radio-value" />
+ <radio name="radio-value" value="1" />
+ <radio name="radio-value" value="2" selected="selected" />
+ <radio name="radio-value" value="3" />
+
+ <input type="image" name="image" src="zope3logo.gif" />
+ <input type="submit" name="submit" value="Submit" />
+ </form>
+
+ </body>
+</html>
\ No newline at end of file
Modified: Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/interfaces.py
===================================================================
--- Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/interfaces.py 2005-07-27 20:40:46 UTC (rev 37499)
+++ Zope3/branches/testbrowser-integration/src/zope/app/testing/testbrowser/interfaces.py 2005-07-27 21:27:30 UTC (rev 37500)
@@ -52,7 +52,7 @@
type = zope.schema.Choice(
title=u"Type",
description=u"The type of the control",
- values=['text', 'hidden', 'submit', 'checkbox', 'select',
+ values=['text', 'password', 'hidden', 'submit', 'checkbox', 'select',
'radio', 'image', 'file'],
required=True)
More information about the Zope3-Checkins
mailing list