Source code for leo.testing.browser
from leo.testing.mech import LeoMechanizeBrowser
from leo.testing.mime import multipart_formdata
from plone.portlets.interfaces import IPortletAssignmentMapping
from plone.portlets.interfaces import IPortletManager
from plone.testing import z2
from tempfile import gettempdir
# from Testing.ZopeTestCase.utils import startZServer
from zope.component import getMultiAdapter
from zope.component import getUtility
import os
import webbrowser
[docs]class Browser(z2.Browser):
"""Enhanced test browser."""
_base_url = None
def __init__(self, app, url=None):
"""Use __init__ method from the super class,
but pass LeoMechanizeBrowser instance to mech_browser to use
POST method for <form />s instead of GET method.
:param app: Application object.
:type app: object
:param url: URL.
:type url: str
"""
super(z2.Browser, self).__init__(url=url, mech_browser=LeoMechanizeBrowser(app))
[docs] def setBaseUrl(self, base_url):
"""Sets a base URL for all subsequent requests.
Usually this url is portal_url.
:param base_url: Base URL to avoide repetetive usage of the URL in testing.
:type base_url: str
"""
self._base_url = base_url
[docs] def dump(self, filename):
"""Dumps the browser contents to the given file.
:param filename: File name.
:type filename: str
"""
fh = open(filename, 'w')
fh.write(self.contents)
fh.close()
[docs] def open(self, url, data=None):
"""Adds support for absolute paths without the base component.
:param url: Absolute path.
:type url: str
:param data: Request Data.
:type data: dict
"""
if self._base_url is not None and url.startswith('/'):
url = '{0}{1}'.format(self._base_url, url)
super(self.__class__, self).open(url, data)
[docs] def login(self, username, password, login_url='/login_form'):
"""Logs into the portal.
:param username: User name.
:type username: str
:param password: Password.
:type password: str
:param login_url: Absolute path for the login URL.
:type login_url: str
"""
self.open(login_url)
self.getControl(name='__ac_name').value = username
self.getControl(name='__ac_password').value = password
self.getControl('Log in').click()
[docs] def deletePortletManager(self, portal, name):
"""Delete portlet manager of the name.
Usually it is u'plone.leftcolumn' or u'plone.rightcolumn'.
:param portal: Portal object.
:type portal: object
:param name: Portlet manager name.
:type name: unicode
"""
column = getUtility(IPortletManager, name=name)
assignable = getMultiAdapter((portal, column), IPortletAssignmentMapping)
del assignable[name]
## This method is not working properly for now.
# def startZserver(self, browser=None):
# """Start ZServer so we can inspect site state with a normal browser
# like FireFox.
# If browser is not specified, system default browser will be used.
# :param browser: Excutable browser name such as 'firefox'.
# :type browser: str
# """
# host, port = startZServer()
# url = 'http://{0}:{1}/plone'.format(host, port)
# wbrowser = webbrowser if browser is None else webbrowser.get(browser)
# wbrowser.open_new_tab(url)
[docs] def openBrowser(self, browser=None, filename='testbrowser.html'):
"""Dumps self.browser.contents (HTML) to a file and opens it with
a normal browser.
If browser is not specified, system default browser will be used.
:param browser: Excutable browser name such as 'firefox'.
:type browser: str
:param filename: HTML file name where the results of html contents will be writen.
:type filename: str
"""
filepath = os.path.join(gettempdir(), filename)
with open(filepath, 'w') as file:
file.write(self.contents)
if browser == None:
wbrowser = webbrowser
else:
wbrowser = webbrowser.get(browser)
wbrowser.open_new_tab('file://' + filepath)
[docs] def post(self, url, data):
"""Posting to url with multipart/form-data instead of application/x-www-form-urlencoded.
:param url: where data will be posted.
:type url: str
:param data: Data which is a list of tuples for data posting.
:type data: list
"""
body, content_type = multipart_formdata(data)
data = "Content-Type: {0}\r\n\r\n{1}".format(content_type, body)
return super(Browser, self).post(url, data)