[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