Skip to content

Commit

Permalink
Finished doc strings for objects.
Browse files Browse the repository at this point in the history
  • Loading branch information
strichter committed Jul 27, 2005
1 parent 5b90d5c commit 3a2871b
Showing 1 changed file with 322 additions and 0 deletions.
322 changes: 322 additions & 0 deletions testbrowser/browser.py
@@ -0,0 +1,322 @@
##############################################################################
#
# Copyright (c) 2005 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.
#
##############################################################################
"""Mechanize-based Functional Doctest interfaces
$Id$
"""
__docformat__ = "reStructuredText"
import re
import zope.interface

from zope.app.testing.testbrowser import interfaces

class Browser(object):
"""A Test Browser based on ``mechanize``."""
zope.interface.implements(interfaces.IBrowser)

def __init__(self, url=None, mech_browser=None):
if mech_browser is None:
import mechanize
mech_browser = mechanize.Browser()

self.mech_browser = mech_browser
if url is not None:
self.open(url)

def open(self, url, data=None):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
self.mech_browser.open(url, data)

def addHeader(self, key, value):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
self.mech_browser.addheaders.append( (key, value) )

@property
def url(self):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
return self.mech_browser.geturl()

def reload(self):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
self.mech_browser.reload()
self._changed()

def goBack(self, count=1):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
self.mech_browser.back(self, count)
self._changed()

@property
def isHtml(self):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
return self.mech_browser.viewing_html()

@property
def title(self):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
return self.mech_browser.title()

def click(self, text=None, url=None, id=None, name=None, coord=(1,1)):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
form, control = self._findControl(text, id, name, type='submit')
if control is not None:
self._clickSubmit(form, control, coord)
self._changed()
return

# if we get here, we didn't find a control to click, so we'll look for
# a regular link

if id is not None:
predicate = lambda link: link.attrs.get('id') == id
self.mech_browser.follow_link(predicate=predicate)
else:
if text is not None:
text_regex = re.compile(text)
else:
text_regex = None
if url is not None:
url_regex = re.compile(url)
else:
url_regex = None

self.mech_browser.follow_link(text_regex=text_regex,
url_regex=url_regex)
self._changed()

@property
def _findControl(self):
def _findControl(text, id, name, type=None, form=None):
for control_form, control in self._controls:
if form is None or control_form == form:
if (((id is not None and control.id == id)
or (name is not None and control.name == name)
or (text is not None and re.search(text, str(control.value)))
) and (type is None or control.type == type)):
self.mech_browser.form = control_form
return control_form, control

return None, None
return _findControl

def _findForm(self, id, name, action):
for form in self.mech_browser.forms():
if ((id is not None and form.attrs.get('id') == id)
or (name is not None and form.name == name)
or (action is not None and re.search(action, str(form.action)))):
self.mech_browser.form = form
return form

return None

def _clickSubmit(self, form, control, coord):
self.mech_browser.open(form.click(
id=control.id, name=control.name, coord=coord))

__controls = None
@property
def _controls(self):
if self.__controls is None:
self.__controls = []
for form in self.mech_browser.forms():
for control in form.controls:
self.__controls.append( (form, control) )
return self.__controls

@property
def controls(self):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
return ControlsMapping(self)

@property
def forms(self):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
return FormsMapping(self)

def getControl(self, text):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
form, control = self._findControl(text, text, text)
if control is None:
raise ValueError('could not locate control: ' + text)
return Control(control)

@property
def contents(self):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
response = self.mech_browser.response()
old_location = response.tell()
response.seek(0)
for line in iter(lambda: response.readline().strip(), ''):
pass
contents = response.read()
response.seek(old_location)
return contents

@property
def headers(self):
"""See zope.app.testing.testbrowser.interfaces.IBrowser"""
return self.mech_browser.response().info()

def _changed(self):
self.__controls = None


class Control(object):
"""A control of a form."""
zope.interface.implements(interfaces.IControl)

def __init__(self, control):
self.mech_control = control

def __getattr__(self, name):
# See zope.app.testing.testbrowser.interfaces.IControl
names = ['options', 'disabled', 'type', 'name', 'readonly', 'multiple']
if name in names:
return getattr(self.mech_control, name, None)
else:
raise AttributeError(name)

@apply
def value():
"""See zope.app.testing.testbrowser.interfaces.IControl"""
def fget(self):
value = self.mech_control.value
if self.mech_control.type == 'checkbox':
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 value:
value = ['on']
else:
value = []
self.mech_control.value = value
return property(fget, fset)

def clear(self):
self.mech_control.clear()

@property
def options(self):
"""See zope.app.testing.testbrowser.interfaces.IControl"""
try:
return self.mech_control.possible_items()
except:
raise AttributeError('options')


class FormsMapping(object):
"""All forms on the page of the browser."""
zope.interface.implements(interfaces.IFormsMapping)

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

def __getitem__(self, key):
"""See zope.interface.common.mapping.IItemMapping"""
try:
form = self.browser._findForm(key, key, None)
except ValueError:
raise KeyError(key)
return Form(self.browser, form)

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.interface.common.mapping.IReadMapping"""
return self.browser._findForm(key, key, None) is not None


class ControlsMapping(object):
"""A mapping of all controls in a form or a page."""
zope.interface.implements(interfaces.IControlsMapping)

def __init__(self, browser, form=None):
"""Initialize the ControlsMapping
browser - a Browser instance
form - a ClientForm instance
"""
self.browser = browser
self.mech_form = form

def __getitem__(self, key):
"""See zope.app.testing.testbrowser.interfaces.IControlsMapping"""
form, control = self.browser._findControl(key, key, key)
if control is None:
raise KeyError(key)
if self.mech_form is not None and self.mech_form != form:
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 __contains__(self, item):
"""See zope.app.testing.testbrowser.interfaces.IControlsMapping"""
try:
self[item]
except KeyError:
return False
else:
return True

def update(self, mapping):
"""See zope.app.testing.testbrowser.interfaces.IControlsMapping"""
for k, v in mapping.items():
self[k] = v


class Form(ControlsMapping):
"""HTML Form"""
zope.interface.implements(interfaces.IForm)

def __getattr__(self, name):
# See zope.app.testing.testbrowser.interfaces.IForm
names = ['action', 'method', 'enctype', 'name']
if name in names:
return getattr(self.mech_form, name, None)
else:
raise AttributeError(name)

@property
def id(self):
"""See zope.app.testing.testbrowser.interfaces.IForm"""
return self.mech_form.attrs.get(id)

@property
def controls(self):
"""See zope.app.testing.testbrowser.interfaces.IForm"""
return ControlsMapping(browser=self.browser, form=self.mech_form)

def submit(self, text=None, id=None, name=None, coord=(1,1)):
"""See zope.app.testing.testbrowser.interfaces.IForm"""
form, control = self.browser._findControl(
text, id, name, type='submit', form=self.mech_form)
if control is not None:
self.browser._clickSubmit(form, control, coord)
self.browser._changed()
return

0 comments on commit 3a2871b

Please sign in to comment.