[Checkins] SVN: zope.testbrowser/trunk/ - Added a
zope.testbrowser.testing.Browser.post method that allows
Benji York
benji at zope.com
Sun Mar 30 19:49:20 EDT 2008
Log message for revision 85021:
- Added a zope.testbrowser.testing.Browser.post method that allows
tests to supply a body and a content type. This is handy for
testing Ajax requests with non-form input (e.g. JSON).
- Move tests for fixed bugs to a separate file.
- Removed non-functional and undocumented code intended to help test servers
using virtual hosting.
Changed:
U zope.testbrowser/trunk/CHANGES.txt
U zope.testbrowser/trunk/buildout.cfg
U zope.testbrowser/trunk/setup.py
U zope.testbrowser/trunk/src/zope/testbrowser/README.txt
U zope.testbrowser/trunk/src/zope/testbrowser/browser.py
U zope.testbrowser/trunk/src/zope/testbrowser/fixed-bugs.txt
U zope.testbrowser/trunk/src/zope/testbrowser/ftests/__init__.py
U zope.testbrowser/trunk/src/zope/testbrowser/ftests/ftesting.zcml
U zope.testbrowser/trunk/src/zope/testbrowser/testing.py
-=-
Modified: zope.testbrowser/trunk/CHANGES.txt
===================================================================
--- zope.testbrowser/trunk/CHANGES.txt 2008-03-30 21:24:49 UTC (rev 85020)
+++ zope.testbrowser/trunk/CHANGES.txt 2008-03-30 23:49:20 UTC (rev 85021)
@@ -2,9 +2,14 @@
CHANGES
=======
+
3.5.0 (unreleased)
------------------
+- Added a zope.testbrowser.testing.Browser.post method that allows
+ tests to supply a body and a content type. This is handy for
+ testing Ajax requests with non-form input (e.g. JSON).
+
- Remove vendor import of mechanize.
- Fix bug that caused HTTP exception tracebacks to differ between version 3.4.0
@@ -23,7 +28,12 @@
- Fix browser.getLink documentation that was not updated since the last API
modification.
+- Move tests for fixed bugs to a separate file.
+- Removed non-functional and undocumented code intended to help test servers
+ using virtual hosting.
+
+
3.4.2 (2007-10-31)
------------------
Modified: zope.testbrowser/trunk/buildout.cfg
===================================================================
--- zope.testbrowser/trunk/buildout.cfg 2008-03-30 21:24:49 UTC (rev 85020)
+++ zope.testbrowser/trunk/buildout.cfg 2008-03-30 23:49:20 UTC (rev 85021)
@@ -1,8 +1,11 @@
[buildout]
develop = .
parts = test interpreter
+index = http://download.zope.org/simple
+extends = http://download.zope.org/zope3.4/versions.cfg
versions = versions
-extends = http://download.zope.org/zope3.4/versions.cfg
+allow-picked-versions = false
+use-dependency-links = false
[versions]
zope.testbrowser =
@@ -13,10 +16,9 @@
recipe = zc.recipe.testrunner
defaults = ['--tests-pattern', '^f?tests$']
eggs = zope.testbrowser [test]
- mechanize
[interpreter]
recipe = zc.recipe.egg
eggs = zope.testbrowser
+ mechanize
interpreter = py
- mechanize
Modified: zope.testbrowser/trunk/setup.py
===================================================================
--- zope.testbrowser/trunk/setup.py 2008-03-30 21:24:49 UTC (rev 85020)
+++ zope.testbrowser/trunk/setup.py 2008-03-30 23:49:20 UTC (rev 85021)
@@ -50,9 +50,9 @@
namespace_packages = ['zope',],
tests_require = ['zope.testing'],
install_requires = [
+ 'ClientForm',
+ 'mechanize',
'setuptools',
- 'mechanize',
- 'ClientForm',
'zope.interface',
'zope.schema',
],
@@ -60,9 +60,9 @@
test = [
'zope.app.component',
'zope.app.folder',
+ 'zope.app.securitypolicy',
'zope.app.testing',
'zope.app.zcmlfiles',
- 'zope.app.securitypolicy',
],
),
include_package_data = True,
Modified: zope.testbrowser/trunk/src/zope/testbrowser/README.txt
===================================================================
--- zope.testbrowser/trunk/src/zope/testbrowser/README.txt 2008-03-30 21:24:49 UTC (rev 85020)
+++ zope.testbrowser/trunk/src/zope/testbrowser/README.txt 2008-03-30 23:49:20 UTC (rev 85021)
@@ -1107,6 +1107,74 @@
ValueError: if no other arguments are given, index is required.
+Submitting a posts body directly
+--------------------------------
+
+In addition to the open method, zope.testbrowser.testing.Browser has a ``post``
+method that allows a request body to be supplied. This method is particularly
+helpful when testing Ajax methods.
+
+Let's visit a page that echos it's request:
+
+ >>> browser.open('http://localhost/@@echo.html')
+ >>> print browser.contents,
+ HTTP_USER_AGENT: Python-urllib/2.4
+ HTTP_CONNECTION: close
+ HTTP_COOKIE:
+ HTTP_REFERER: localhost
+ HTTP_ACCEPT_LANGUAGE: en-US
+ REQUEST_METHOD: GET
+ HTTP_HOST: localhost
+ PATH_INFO: /@@echo.html
+ SERVER_PROTOCOL: HTTP/1.1
+ QUERY_STRING:
+ Body: ''
+
+Now, we'll try a post. The post method takes a URL, a data string,
+and an optional content type. If we just pass a string, then
+a URL-encoded query string is assumed:
+
+ >>> browser.post('http://localhost/@@echo.html', 'x=1&y=2')
+ >>> print browser.contents,
+ CONTENT_LENGTH: 7
+ HTTP_USER_AGENT: Python-urllib/2.4
+ HTTP_CONNECTION: close
+ HTTP_COOKIE:
+ HTTP_REFERER: localhost
+ HTTP_ACCEPT_LANGUAGE: en-US
+ y: 2
+ REQUEST_METHOD: POST
+ HTTP_HOST: localhost
+ PATH_INFO: /@@echo.html
+ CONTENT_TYPE: application/x-www-form-urlencoded
+ SERVER_PROTOCOL: HTTP/1.1
+ QUERY_STRING:
+ x: 1
+ Body: ''
+
+
+The body is empty because it is consumed to get form data.
+
+We can pass a content-type explicitly:
+
+ >>> browser.post('http://localhost/@@echo.html',
+ ... '{"x":1,"y":2}', 'application/x-javascipt')
+ >>> print browser.contents,
+ CONTENT_LENGTH: 13
+ HTTP_USER_AGENT: Python-urllib/2.4
+ HTTP_CONNECTION: close
+ HTTP_COOKIE:
+ HTTP_REFERER: localhost
+ HTTP_ACCEPT_LANGUAGE: en-US
+ REQUEST_METHOD: POST
+ HTTP_HOST: localhost
+ PATH_INFO: /@@echo.html
+ CONTENT_TYPE: application/x-javascipt
+ SERVER_PROTOCOL: HTTP/1.1
+ Body: '{"x":1,"y":2}'
+
+Here, the body is left in place because it isn't form data.
+
Performance Testing
-------------------
@@ -1215,33 +1283,3 @@
Traceback (most recent call last):
...
AttributeError: 'Link' object has no attribute 'nonexistant'
-
-
-Fixed Bugs
-----------
-
-This section includes tests for bugs that were found and then fixed that don't
-fit into the more documentation-centric sections above.
-
-Spaces in URL
-~~~~~~~~~~~~~
-
-When URLs have spaces in them, they're handled correctly (before the bug was
-fixed, you'd get "ValueError: too many values to unpack"):
-
- >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
- >>> browser.getLink('Spaces in the URL').click()
-
-.goBack() Truncation
-~~~~~~~~~~~~~~~~~~~~
-
-The .goBack() method used to truncate the .contents.
-
- >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
- >>> actual_length = len(browser.contents)
-
- >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
- >>> browser.open('http://localhost/@@/testbrowser/simple.html')
- >>> browser.goBack()
- >>> len(browser.contents) == actual_length
- True
Modified: zope.testbrowser/trunk/src/zope/testbrowser/browser.py
===================================================================
--- zope.testbrowser/trunk/src/zope/testbrowser/browser.py 2008-03-30 21:24:49 UTC (rev 85020)
+++ zope.testbrowser/trunk/src/zope/testbrowser/browser.py 2008-03-30 23:49:20 UTC (rev 85021)
@@ -249,6 +249,11 @@
if self.raiseHttpErrors and code >= 400:
raise urllib2.HTTPError(url, code, msg, self.headers, fp=None)
+ def post(self, url, data, content_type=None):
+ if content_type is not None:
+ data = {'body': data, 'content-type': content_type}
+ return self.open(url, data)
+
def _start_timer(self):
self.timer.start()
Modified: zope.testbrowser/trunk/src/zope/testbrowser/fixed-bugs.txt
===================================================================
--- zope.testbrowser/trunk/src/zope/testbrowser/fixed-bugs.txt 2008-03-30 21:24:49 UTC (rev 85020)
+++ zope.testbrowser/trunk/src/zope/testbrowser/fixed-bugs.txt 2008-03-30 23:49:20 UTC (rev 85021)
@@ -1,3 +1,11 @@
+==========
+Fixed Bugs
+==========
+
+This file includes tests for bugs that were found and then fixed that don't fit
+into the more documentation-centric sections above.
+
+
Unicode URLs
============
@@ -25,3 +33,28 @@
>>> browser = Browser()
>>> browser.addHeader(u'Cookie', 'test')
>>> browser.open('http://localhost/@@/testbrowser/simple.html')
+
+
+Spaces in URL
+=============
+
+When URLs have spaces in them, they're handled correctly (before the bug was
+fixed, you'd get "ValueError: too many values to unpack"):
+
+ >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
+ >>> browser.getLink('Spaces in the URL').click()
+
+
+.goBack() Truncation
+====================
+
+The .goBack() method used to truncate the .contents.
+
+ >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
+ >>> actual_length = len(browser.contents)
+
+ >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
+ >>> browser.open('http://localhost/@@/testbrowser/simple.html')
+ >>> browser.goBack()
+ >>> len(browser.contents) == actual_length
+ True
Modified: zope.testbrowser/trunk/src/zope/testbrowser/ftests/__init__.py
===================================================================
--- zope.testbrowser/trunk/src/zope/testbrowser/ftests/__init__.py 2008-03-30 21:24:49 UTC (rev 85020)
+++ zope.testbrowser/trunk/src/zope/testbrowser/ftests/__init__.py 2008-03-30 23:49:20 UTC (rev 85021)
@@ -1 +1,23 @@
-# Make a package.
+##############################################################################
+#
+# Copyright (c) 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.
+#
+##############################################################################
+
+class Echo:
+ """Simply echo the contents of the request"""
+
+ def __init__(self, context, request):
+ self.request = request
+
+ def __call__(self):
+ return ('\n'.join('%s: %s' % x for x in self.request.items()) +
+ '\nBody: %r' % self.request.bodyStream.read())
Modified: zope.testbrowser/trunk/src/zope/testbrowser/ftests/ftesting.zcml
===================================================================
--- zope.testbrowser/trunk/src/zope/testbrowser/ftests/ftesting.zcml 2008-03-30 21:24:49 UTC (rev 85020)
+++ zope.testbrowser/trunk/src/zope/testbrowser/ftests/ftesting.zcml 2008-03-30 23:49:20 UTC (rev 85021)
@@ -30,6 +30,12 @@
<grant permission="zope.View"
role="zope.Anonymous" />
+ <browser:page
+ name="echo.html"
+ for="*"
+ class=".ftests.Echo"
+ permission="zope.Public"
+ />
<browser:resourceDirectory
name="testbrowser"
Modified: zope.testbrowser/trunk/src/zope/testbrowser/testing.py
===================================================================
--- zope.testbrowser/trunk/src/zope/testbrowser/testing.py 2008-03-30 21:24:49 UTC (rev 85020)
+++ zope.testbrowser/trunk/src/zope/testbrowser/testing.py 2008-03-30 23:49:20 UTC (rev 85021)
@@ -123,7 +123,15 @@
class PublisherHTTPHandler(urllib2.HTTPHandler):
"""Special HTTP handler to use the Zope Publisher."""
- http_request = urllib2.AbstractHTTPHandler.do_request_
+ def http_request(self, req):
+ # look at data and set content type
+ if req.has_data():
+ data = req.get_data()
+ if isinstance(data, dict):
+ req.add_data(data['body'])
+ req.add_unredirected_header('Content-type',
+ data['content-type'])
+ return urllib2.AbstractHTTPHandler.do_request_(self, req)
def http_open(self, req):
"""Open an HTTP connection having a ``urllib2`` request."""
@@ -159,94 +167,3 @@
def __init__(self, url=None):
mech_browser = PublisherMechanizeBrowser()
super(Browser, self).__init__(url=url, mech_browser=mech_browser)
-
-#### virtual host test suites ####
-
-example_path_re = re.compile('http://example.com/virtual_path/')
-
-class VirtualHostingPublisherConnection(PublisherConnection):
- def request(self, method, url, body=None, headers=None):
- if self.host == 'example.com':
- assert url.startswith('/virtual_path')
- url = url[13:]
- if not url:
- url = '/'
- url = '/vh_test_folder/++vh++http:example.com:80/virtual_path/++' + url
- super(VirtualHostingPublisherConnection, self).request(
- method, url, body, headers)
-
-class VirtualHostingPublisherHTTPHandler(urllib2.HTTPHandler):
- """Special HTTP handler to use the Zope Publisher."""
-
- http_request = urllib2.AbstractHTTPHandler.do_request_
-
- def http_open(self, req):
- """Open an HTTP connection having a ``urllib2`` request."""
- # Here we connect to the publisher.
- return self.do_open(VirtualHostingPublisherConnection, req)
-
-class VirtualHostingPublisherMechanizeBrowser(PublisherMechanizeBrowser):
- handler_classes = PublisherMechanizeBrowser.handler_classes.copy()
- handler_classes['http'] = VirtualHostingPublisherHTTPHandler
-
-class VirtualHostingBrowser(browser.Browser):
- """A Zope ``testbrowser` Browser that inserts ."""
-
- def __init__(self, url=None):
- mech_browser = VirtualHostingPublisherMechanizeBrowser()
- super(VirtualHostingBrowser, self).__init__(
- url=url, mech_browser=mech_browser)
-
-def virtualHostingSetUp(test):
- # need to create a folder named vh_test_folder in root
- root = test.globs['getRootFolder']()
- f = Folder()
- root['vh_test_folder'] = f
- f.setSiteManager(LocalSiteManager(f))
- transaction.commit()
-
-def VirtualHostTestBrowserSuite(*paths, **kw):
-# layer=None,
-# globs=None, setUp=None, normalizers=None, **kw):
-
- if 'checker' in kw:
- raise ValueError(
- 'Must not supply custom checker. To provide values for '
- 'zope.testing.renormalizing.RENormalizing checkers, include a '
- '"normalizers" argument that is a list of (compiled regex, '
- 'replacement) pairs.')
- kw['package'] = doctest._normalize_module(kw.get('package'))
- layer = kw.pop('layer', None)
- normalizers = kw.pop('normalizers', None)
- vh_kw = kw.copy()
- if 'globs' in kw:
- globs = kw['globs'] = kw['globs'].copy() # don't mutate the original
- else:
- globs = kw['globs'] = {}
- if 'Browser' in globs:
- raise ValueError('"Browser" must not be defined in globs')
- vh_kw['globs'] = globs.copy()
- globs['Browser'] = Browser
- vh_kw['globs']['Browser'] = VirtualHostingBrowser
- def vh_setUp(test):
- virtualHostingSetUp(test)
- if 'setUp' in kw:
- kw['setUp'](test)
- vh_kw['setUp'] = vh_setUp
- if normalizers is not None:
- kw['checker'] = renormalizing.RENormalizing(normalizers)
- vh_normalizers = normalizers[:]
- else:
- vh_normalizers = []
- vh_normalizers.append((example_path_re, 'http://localhost/'))
- vh_kw['checker'] = renormalizing.RENormalizing(vh_normalizers)
- suite = unittest.TestSuite()
- test = functional.FunctionalDocFileSuite(*paths, **kw)
- vh_test = functional.FunctionalDocFileSuite(*paths, **vh_kw)
- vh_test.level = 2
- if layer is not None:
- test.layer = layer
- vh_test.layer = layer
- suite.addTest(test)
- suite.addTest(vh_test)
- return suite
More information about the Checkins
mailing list