[Checkins] SVN: zope.app.wsgi/trunk/src/zope/app/wsgi/testlayer.py Improve testing story to be compatible with zope.app.testing.functional

Sylvain Viollon sylvain at infrae.com
Wed Apr 14 08:21:48 EDT 2010


Log message for revision 110857:
  Improve testing story to be compatible with zope.app.testing.functional
  

Changed:
  U   zope.app.wsgi/trunk/src/zope/app/wsgi/testlayer.py

-=-
Modified: zope.app.wsgi/trunk/src/zope/app/wsgi/testlayer.py
===================================================================
--- zope.app.wsgi/trunk/src/zope/app/wsgi/testlayer.py	2010-04-14 12:20:36 UTC (rev 110856)
+++ zope.app.wsgi/trunk/src/zope/app/wsgi/testlayer.py	2010-04-14 12:21:48 UTC (rev 110857)
@@ -12,15 +12,21 @@
 #
 ##############################################################################
 from StringIO import StringIO
+import re
+import base64
 
-import wsgi_intercept
+from transaction import commit
+from wsgi_intercept.mechanize_intercept import Browser as BaseInterceptBrowser
 from zope.app.appsetup.testlayer import ZODBLayer
-
+from zope.app.publication.httpfactory import HTTPPublicationRequestFactory
 from zope.app.wsgi import WSGIPublisherApplication
-from zope.app.publication.httpfactory import HTTPPublicationRequestFactory
-from wsgi_intercept.mechanize_intercept import Browser as BaseInterceptBrowser
 from zope.testbrowser.browser import Browser as ZopeTestbrowser
+import wsgi_intercept
 
+# List of hostname where the test browser/http function replies to
+TEST_HOSTS = ['localhost', '127.0.0.1']
+
+
 class InterceptBrowser(BaseInterceptBrowser):
 
     default_schemes = ['http']
@@ -40,6 +46,53 @@
         ZopeTestbrowser.__init__(self, *args, **kwargs)
 
 
+basicre = re.compile('Basic (.+)?:(.+)?$')
+def auth_header(header):
+    """This function takes an authorization HTTP header and encode the
+    couple user, password into base 64 like the HTTP protocol wants
+    it.
+    """
+    match = basicre.match(header)
+    if match:
+        u, p = match.group(1, 2)
+        if u is None:
+            u = ''
+        if p is None:
+            p = ''
+        auth = base64.encodestring('%s:%s' % (u, p))
+        return 'Basic %s' % auth[:-1]
+    return header
+
+
+class TestBrowserMiddleware(object):
+    """This middleware makes the WSGI application compatible with the
+    HTTPCaller behavior defined in zope.app.testing.functional:
+    - It commits and synchronises the current transaction before and
+      after the test.
+    - It honors the X-zope-handle-errors header in order to support
+      zope.testbrowser Browser handleErrors flag.
+    - It modifies the HTTP Authorization header to encode user and
+      password into base 64 if it is Basic authentication.
+    """
+
+    def __init__(self, app, root):
+        self.root = root
+        self.app = app
+
+    def __call__(self, environ, start_response):
+        handle_errors = environ.get('HTTP_X_ZOPE_HANDLE_ERRORS', 'True')
+        self.app.handleErrors = handle_errors == 'True'
+
+        auth_key = 'HTTP_AUTHORIZATION'
+        if environ.has_key(auth_key):
+            environ[auth_key] = auth_header(environ[auth_key])
+
+        commit()
+        for entry in self.app(environ, start_response):
+            yield entry
+        self.root._p_jar.sync()
+
+
 class BrowserLayer(ZODBLayer):
     """This create a test layer with a test database and register a wsgi
     application to use that test database.
@@ -49,22 +102,21 @@
     application.
     """
 
-    handleErrors = True
-
     def testSetUp(self):
         super(BrowserLayer, self).testSetUp()
         wsgi_app = WSGIPublisherApplication(
-            self.db, HTTPPublicationRequestFactory, self.handleErrors)
+            self.db, HTTPPublicationRequestFactory, True)
 
         def factory():
-            return wsgi_app
+            return TestBrowserMiddleware(wsgi_app, self.getRootFolder())
 
-        wsgi_intercept.add_wsgi_intercept('localhost', 80, factory)
+        for host in TEST_HOSTS:
+            wsgi_intercept.add_wsgi_intercept(host, 80, factory)
 
-
     def testTearDown(self):
+        for host in TEST_HOSTS:
+            wsgi_intercept.remove_wsgi_intercept(host, 80)
         super(BrowserLayer, self).testTearDown()
-        wsgi_intercept.remove_wsgi_intercept('localhost', 80)
 
 
 class NotInBrowserLayer(Exception):



More information about the checkins mailing list