-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added an ExtendedTestBrowser that speaks HTTP
- Loading branch information
Thomas Lotze
committed
Jul 8, 2010
1 parent
92a528a
commit a2a6763
Showing
6 changed files
with
163 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
############################################################################## | ||
# | ||
# Copyright (c) 2006 Zope Foundation 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. | ||
# | ||
############################################################################## | ||
"""Extensions for z3c.etestbrowser | ||
$Id$ | ||
""" | ||
|
||
import re | ||
import htmllib | ||
import formatter | ||
|
||
import lxml.etree | ||
import lxml.html | ||
|
||
import zope.testbrowser.browser | ||
|
||
|
||
RE_CHARSET = re.compile('.*;charset=(.*)') | ||
|
||
|
||
def indent(elem, level=0): | ||
i = "\n" + level*" " | ||
if len(elem): | ||
if not elem.text or not elem.text.strip(): | ||
elem.text = i + " " | ||
for e in elem: | ||
indent(e, level+1) | ||
if not e.tail or not e.tail.strip(): | ||
e.tail = i + " " | ||
if not e.tail or not e.tail.strip(): | ||
e.tail = i | ||
else: | ||
if level and (not elem.tail or not elem.tail.strip()): | ||
elem.tail = i | ||
|
||
|
||
class ExtendedTestBrowser(zope.testbrowser.browser.Browser): | ||
"""An extended testbrowser implementation. | ||
Features: | ||
- offers the content also as parsed etree | ||
""" | ||
|
||
xml_strict = False | ||
|
||
_etree = None | ||
_normalized_contents = None | ||
|
||
@property | ||
def etree(self): | ||
if self._etree is not None: | ||
return self._etree | ||
# I'm not using any internal knowledge about testbrowser | ||
# here, to avoid breakage. Memory usage won't be a problem. | ||
if self.xml_strict: | ||
self._etree = lxml.etree.fromstring( | ||
self.contents, | ||
parser=lxml.etree.XMLParser(resolve_entities=False)) | ||
else: | ||
# This is a workaround against the broken fallback for | ||
# encoding detection of libxml2. | ||
# We have a chance of knowing the encoding as Zope states this in | ||
# the content-type response header. | ||
content = self.contents | ||
content_type = self.headers['content-type'] | ||
match = RE_CHARSET.match(content_type) | ||
if match is not None: | ||
charset = match.groups()[0] | ||
content = content.decode(charset) | ||
self._etree = lxml.etree.HTML(content) | ||
|
||
return self._etree | ||
|
||
@property | ||
def normalized_contents(self): | ||
if self._normalized_contents is None: | ||
indent(self.etree) | ||
self._normalized_contents = lxml.etree.tostring( | ||
self.etree, pretty_print=True) | ||
return self._normalized_contents | ||
|
||
def _changed(self): | ||
super(ExtendedTestBrowser, self)._changed() | ||
self._etree = None | ||
self._normalized_contents = None | ||
|
||
def pretty_print(self): | ||
"""Print a pretty (formatted) version of the HTML content. | ||
If the content is not text/html then it is just printed. | ||
""" | ||
if not self.headers['content-type'].lower().startswith('text/html'): | ||
print self.contents | ||
else: | ||
parser = htmllib.HTMLParser( | ||
formatter.AbstractFormatter(formatter.DumbWriter())) | ||
parser.feed(self.contents) | ||
parser.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
================================= | ||
Using testbrowser On the Internet | ||
================================= | ||
|
||
The ``z3c.etestbrowser`` module exposes an ``ExtendedTestBrowser`` class that | ||
simulates a web browser similar to Mozilla Firefox or IE. | ||
|
||
>>> from z3c.etestbrowser.browser import ExtendedTestBrowser | ||
>>> browser = ExtendedTestBrowser() | ||
|
||
It can send arbitrary headers; this is helpful for setting the language value, | ||
so that your tests format values the way you expect in your tests, if you rely | ||
on zope.i18n locale-based formatting or a similar approach. | ||
|
||
>>> browser.addHeader('Accept-Language', 'en-US') | ||
|
||
The browser can `open` web pages: | ||
|
||
>>> # This is tricky, since in Germany I am forwarded to google.de usually; | ||
>>> # The `ncr` forces to really go to google.com. | ||
>>> browser.open('http://google.com/ncr') | ||
>>> browser.url | ||
'http://www.google.com/' | ||
>>> 'html' in browser.contents.lower() | ||
True | ||
|
||
We can access the etree of the page .. contents: | ||
|
||
>>> browser.etree.xpath('//body') | ||
[<Element body at ...>] | ||
|
||
We'll put some text in the query box... | ||
|
||
>>> browser.getControl(name='q').value = 'z3c.etestbrowser' | ||
|
||
...and then click the search button. | ||
|
||
>>> browser.getControl('Google Search').click() | ||
Traceback (most recent call last): | ||
... | ||
RobotExclusionError: HTTP Error 403: request disallowed by robots.txt | ||
|
||
Oops! Google doesn't let robots use their search engine. Oh well. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters