[Checkins] SVN: z3c.dav/trunk/src/z3c/dav/ Better support for testing 207 Multi-Status response bodies which should also

Michael Kerrin michael.kerrin at openapp.ie
Sun May 6 10:41:47 EDT 2007


Log message for revision 75566:
  Better support for testing 207 Multi-Status response bodies which should also
  work with doctests. Updated all the current functional tests to use this new
  functionality.
  

Changed:
  A   z3c.dav/trunk/src/z3c/dav/ftesting.zcml
  U   z3c.dav/trunk/src/z3c/dav/ftests/dav.py
  U   z3c.dav/trunk/src/z3c/dav/ftests/ftesting-locking.zcml
  U   z3c.dav/trunk/src/z3c/dav/ftests/ftesting.zcml
  U   z3c.dav/trunk/src/z3c/dav/ftests/test_propfind.py
  U   z3c.dav/trunk/src/z3c/dav/ftests/test_proppatch.py
  U   z3c.dav/trunk/src/z3c/dav/ftests/test_z3_locking.py
  A   z3c.dav/trunk/src/z3c/dav/testing.py
  U   z3c.dav/trunk/src/z3c/dav/tests/test_doctests.py

-=-
Added: z3c.dav/trunk/src/z3c/dav/ftesting.zcml
===================================================================
--- z3c.dav/trunk/src/z3c/dav/ftesting.zcml	2007-05-06 14:10:22 UTC (rev 75565)
+++ z3c.dav/trunk/src/z3c/dav/ftesting.zcml	2007-05-06 14:41:45 UTC (rev 75566)
@@ -0,0 +1,62 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:zcml="http://namespaces.zope.org/zcml"
+           i18n_domain="zope">
+
+  <!--
+      Common Zope configuration file shared by the functional tests of
+      the different WebDAV components.
+  -->
+
+  <include zcml:condition="installed zope.app.zcmlfiles"
+           package="zope.app.zcmlfiles" />
+  <include zcml:condition="not-installed zope.app.zcmlfiles"
+           package="zope.app.zcmlfiles" />
+
+  <include package="zope.app.securitypolicy" file="meta.zcml" />
+  <include package="zope.app.securitypolicy" />
+
+  <securityPolicy
+     component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy"
+     />
+
+  <role
+     id="zope.Anonymous"
+     title="Everybody"
+     description="All users have this role implicitly"
+     />
+
+  <unauthenticatedPrincipal id="zope.anybody" title="Unauthenticated User" />
+  <grant
+     permission="zope.View"
+     role="zope.Anonymous"
+     />
+  <grant
+     permission="zope.app.dublincore.view"
+     role="zope.Anonymous"
+     />
+
+  <role
+     id="zope.Manager"
+     title="Site Manager"
+     />
+
+  <principal id="zope.mgr" title="Manager" login="mgr" password="mgrpw" />
+  <grant
+     role="zope.Manager"
+     principal="zope.mgr"
+     />
+
+  <grantAll role="zope.Manager" />
+
+  <include package="zope.app.authentication" />
+
+  <include package="z3c.dav" />
+
+<!-- This is usually how we register the elementtree engine to use within
+     our application but for testing purposes we use the .dav.WebDAVLayerClass
+  <utility
+     factory="z3c.etree.etree.EtreeEtree"
+     />
+-->
+
+</configure>

Modified: z3c.dav/trunk/src/z3c/dav/ftests/dav.py
===================================================================
--- z3c.dav/trunk/src/z3c/dav/ftests/dav.py	2007-05-06 14:10:22 UTC (rev 75565)
+++ z3c.dav/trunk/src/z3c/dav/ftests/dav.py	2007-05-06 14:41:45 UTC (rev 75566)
@@ -28,7 +28,6 @@
 from zope import interface
 from zope import component
 from zope import schema
-import zope.app.testing.functional
 
 from zope.security.proxy import removeSecurityProxy
 from zope.app.folder.folder import Folder
@@ -38,30 +37,15 @@
 from zope.security.testing import Principal, Participation
 from zope.dublincore.interfaces import IWriteZopeDublinCore
 
-import z3c.etree
-import z3c.etree.testing
 from z3c.dav.publisher import WebDAVRequest
 from z3c.dav.properties import DAVProperty
 from z3c.dav.tests.utils import TestMultiStatusBody
 
+import z3c.dav.testing
 
-class WebDAVLayerClass(zope.app.testing.functional.ZCMLLayer):
-    """
-    """
-
-    def setUp(self):
-        zope.app.testing.functional.ZCMLLayer.setUp(self)
-        z3c.etree.testing.etreeSetup()
-
-    def tearDown(self):
-        zope.app.testing.functional.ZCMLLayer.tearDown(self)
-        z3c.etree.testing.etreeTearDown()
-
 here = os.path.dirname(os.path.realpath(__file__))
-WebDAVLayer = WebDAVLayerClass(
-    os.path.join(here, "ftesting.zcml"),
-    __name__, "WebDAVLayer",
-    allow_teardown = True)
+WebDAVLayer = z3c.dav.testing.WebDAVLayerClass(
+    os.path.join(here, "ftesting.zcml"), __name__, "WebDAVLayer")
 
 
 class IExamplePropertyStorage(interface.Interface):
@@ -137,8 +121,7 @@
             self.xmlDataSource[0][0].append(elem)
 
 
-class DAVTestCase(zope.app.testing.functional.HTTPTestCase,
-                  TestMultiStatusBody):
+class DAVTestCase(z3c.dav.testing.WebDAVTestCase, TestMultiStatusBody):
 
     layer = WebDAVLayer
 
@@ -212,31 +195,6 @@
         self.addResource("/a/r3", "third resource", contentType = "text/plain")
         self.createObject("/b", Folder())
 
-    #
-    # Now some methods for creating, and publishing request.
-    #
-    def makeRequest(self, path = "", basic = None, form = None, env = {},
-                    instream = None):
-        """Create a new WebDAV request
-        """
-        if instream is None:
-            instream = ""
-        environment = {"HTTP_HOST": "localhost",
-                       "HTTP_REFERER": "localhost"}
-        environment.update(env)
-
-        if instream and not environment.has_key("CONTENT_LENGTH"):
-            if getattr(instream, "getvalue", None) is not None:
-                instream = instream.getvalue()
-            environment["CONTENT_LENGTH"] = len(instream)
-
-        app = zope.app.testing.functional.FunctionalTestSetup().getApplication()
-        request = app._request(path, instream, environment = environment,
-                               basic = basic, form = form,
-                               request = WebDAVRequest,
-                               publication = HTTPPublication)
-        return request
-
     def checkPropfind(self, path = "/", basic = None, env = {},
                       properties = None):
         # - properties if set is a string containing the contents of the
@@ -263,12 +221,8 @@
         self.assertEqual(response.getStatus(), 207)
         self.assertEqual(response.getHeader("content-type"), "application/xml")
 
-        respbody = response.getBody()
-        etree = z3c.etree.getEngine()
-        xmlbody = etree.fromstring(respbody)
+        return response
 
-        return response, xmlbody
-
     def checkProppatch(self, path = '/', basic = None, env = {},
                        set_properties = None, remove_properties = None,
                        handle_errors = True):
@@ -308,8 +262,4 @@
         self.assertEqual(response.getStatus(), 207)
         self.assertEqual(response.getHeader("content-type"), "application/xml")
 
-        respbody = response.getBody()
-        etree = z3c.etree.getEngine()
-        xmlbody = etree.fromstring(respbody)
-
-        return response, xmlbody
+        return response

Modified: z3c.dav/trunk/src/z3c/dav/ftests/ftesting-locking.zcml
===================================================================
--- z3c.dav/trunk/src/z3c/dav/ftests/ftesting-locking.zcml	2007-05-06 14:10:22 UTC (rev 75565)
+++ z3c.dav/trunk/src/z3c/dav/ftests/ftesting-locking.zcml	2007-05-06 14:41:45 UTC (rev 75566)
@@ -1,8 +1,10 @@
 <configure xmlns="http://namespaces.zope.org/zope">
 
-  <include package="z3c.dav.ftests" file="ftesting.zcml" />
+  <include package="z3c.dav" file="ftesting.zcml" />
 
+  <include package="zope.app.file" />
   <include package="zope.app.keyreference" />
+
   <include package="zope.locking" />
 
 </configure>

Modified: z3c.dav/trunk/src/z3c/dav/ftests/ftesting.zcml
===================================================================
--- z3c.dav/trunk/src/z3c/dav/ftests/ftesting.zcml	2007-05-06 14:10:22 UTC (rev 75565)
+++ z3c.dav/trunk/src/z3c/dav/ftests/ftesting.zcml	2007-05-06 14:41:45 UTC (rev 75566)
@@ -1,60 +1,7 @@
-<configure xmlns="http://namespaces.zope.org/zope"
-           xmlns:zcml="http://namespaces.zope.org/zcml"
-           i18n_domain="zope">
+<configure xmlns="http://namespaces.zope.org/zope">
 
-  <include zcml:condition="installed zope.app.zcmlfiles"
-           package="zope.app.zcmlfiles" />
-  <include zcml:condition="not-installed zope.app.zcmlfiles"
-           package="zope.app.zcmlfiles" />
+  <include package="z3c.dav" file="ftesting.zcml" />
 
-  <include package="zope.app.securitypolicy" file="meta.zcml" />
-  <include package="zope.app.securitypolicy" />
-
-  <securityPolicy
-     component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy"
-     />
-
-  <role
-     id="zope.Anonymous"
-     title="Everybody"
-     description="All users have this role implicitly"
-     />
-
-  <unauthenticatedPrincipal id="zope.anybody" title="Unauthenticated User" />
-  <grant
-     permission="zope.View"
-     role="zope.Anonymous"
-     />
-  <grant
-     permission="zope.app.dublincore.view"
-     role="zope.Anonymous"
-     />
-
-  <role
-     id="zope.Manager"
-     title="Site Manager"
-     />
-
-  <principal id="zope.mgr" title="Manager" login="mgr" password="mgrpw" />
-  <grant
-     role="zope.Manager"
-     principal="zope.mgr"
-     />
-
-  <grantAll role="zope.Manager" />
-
-  <include package="zope.app.authentication" />
-
-  <include package="z3c.dav" />
-
-<!-- This is usually how we register the elementtree engine to use within
-     our application but for testing purposes we use the .dav.WebDAVLayerClass
-  <utility
-     factory="z3c.etree.etree.EtreeEtree"
-     />
--->
-
-  <include package="zope.app.folder" />
   <include package="zope.app.file" />
 
   <!--

Modified: z3c.dav/trunk/src/z3c/dav/ftests/test_propfind.py
===================================================================
--- z3c.dav/trunk/src/z3c/dav/ftests/test_propfind.py	2007-05-06 14:10:22 UTC (rev 75565)
+++ z3c.dav/trunk/src/z3c/dav/ftests/test_propfind.py	2007-05-06 14:41:45 UTC (rev 75566)
@@ -17,6 +17,7 @@
 """
 __docformat__ = 'restructuredtext'
 
+import urllib
 import unittest
 from cStringIO import StringIO
 import transaction
@@ -24,6 +25,7 @@
 import dav
 from zope import component
 import z3c.dav.interfaces
+import z3c.etree.testing
 
 class PROPFINDTests(dav.DAVTestCase):
 
@@ -71,239 +73,258 @@
     <ff0:resourcetype/>
   </ff0:prop>
 </ff0:propfind>"""
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/", env = {"DEPTH": "0", "CONTENT_TYPE": "text/xml"},
             properties = "<D:prop><D:resourcetype/></D:prop>")
-        hrefs = xmlbody.findall("{DAV:}response/{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/")
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
 
-        props = xmlbody.findall("{DAV:}response/{DAV:}propstat/{DAV:}prop")
-        self.assertEqual(len(props), 1) # only one prop element
-        propel = props[0]
+        resourcetype = httpresponse.getMSProperty(
+            "http://localhost/", "{DAV:}resourcetype")
+        z3c.etree.testing.assertXMLEqual(
+            """<resourcetype xmlns="DAV:">
+                 <collection />
+               </resourcetype>""",
+            resourcetype)
 
-        self.assertEqual(len(propel), 1) # only one property defined
-        self.assertEqual(propel[0].tag, "{DAV:}resourcetype")
-        self.assertEqual(propel[0].text, None)
-        self.assertEqual(len(propel[0]), 1)
-        self.assertEqual(propel[0][0].tag, "{DAV:}collection")
-
     def test_propnames_on_collection(self):
         collection = self.addCollection("/coll")
         
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/coll", env = {"DEPTH": "0"}, properties = "<D:propname />")
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/coll/")
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
 
-        props = response.findall("{DAV:}propstat/{DAV:}prop")
-        self.assertEqual(len(props), 1)
-        propel = props[0]
+        z3c.etree.testing.assertXMLEqual(
+            '<resourcetype xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/coll/", "{DAV:}resourcetype"))
+        z3c.etree.testing.assertXMLEqual(
+            '<creationdate xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/coll/", "{DAV:}creationdate"))
+        z3c.etree.testing.assertXMLEqual(
+            '<displayname xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/coll/", "{DAV:}displayname"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getlastmodified xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/coll/", "{DAV:}getlastmodified"))
 
-        self.assertMSPropertyValue(response, "{DAV:}resourcetype")
-        self.assertMSPropertyValue(response, "{DAV:}creationdate")
-        self.assertMSPropertyValue(response, "{DAV:}displayname")
-        self.assertMSPropertyValue(response, "{DAV:}getlastmodified")
-
     def test_propnames_on_resource(self):
         self.addResource("/r1", "some content")
         
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/r1", env = {"DEPTH": "0"}, properties = "<D:propname />")
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/r1")
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
 
-        props = response.findall("{DAV:}propstat/{DAV:}prop")
-        self.assertEqual(len(props), 1)
+        z3c.etree.testing.assertXMLEqual(
+            '<resourcetype xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}resourcetype"))
+        z3c.etree.testing.assertXMLEqual(
+            '<creationdate xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}creationdate"))
+        z3c.etree.testing.assertXMLEqual(
+            '<displayname xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}displayname"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getlastmodified xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}getlastmodified"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getcontenttype xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}getcontenttype"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getcontentlength xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}getcontentlength"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getcontentlanguage xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}getcontentlanguage"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getetag xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}getetag"))
 
-        ## See README.txt for a list of properties defined for these tests.
-        self.assertMSPropertyValue(response, "{DAV:}resourcetype")
-        self.assertMSPropertyValue(response, "{DAV:}creationdate")
-        self.assertMSPropertyValue(response, "{DAV:}displayname")
-        self.assertMSPropertyValue(response, "{DAV:}getlastmodified")
-        self.assertMSPropertyValue(response, "{DAV:}getcontenttype")
-        self.assertMSPropertyValue(response, "{DAV:}getcontentlength")
-        self.assertMSPropertyValue(response, "{DAV:}getcontentlanguage")
-        self.assertMSPropertyValue(response, "{DAV:}getetag")
-
     def test_allprop(self):
         collection = self.addCollection("/coll", title = u"Test Collection")
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/coll", env = {"DEPTH": "0"}, properties = "<D:allprop />")
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/coll/")
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
 
-        props = response.findall("{DAV:}propstat/{DAV:}prop")
-        self.assertEqual(len(props), 1) # only one prop element
+        z3c.etree.testing.assertXMLEqual(
+            """<resourcetype xmlns="DAV:">
+                 <collection />
+               </resourcetype>""",
+            httpresponse.getMSProperty(
+                "http://localhost/coll/", "{DAV:}resourcetype"))
+        z3c.etree.testing.assertXMLEqual(
+            """<displayname xmlns="DAV:">Test Collection</displayname>""",
+            httpresponse.getMSProperty(
+                "http://localhost/coll/", "{DAV:}displayname"))
 
-        ## See README.txt for a list of properties defined for these tests.
-        self.assertMSPropertyValue(response, "{DAV:}resourcetype",
-                                   tag = "{DAV:}collection", text_value = None)
-        self.assertMSPropertyValue(response, "{DAV:}displayname",
-                                   text_value = "Test Collection")
-
     def test_allprop_on_resource(self):
         collection = self.addResource("/r1", "test resource content",
                                       title = u"Test Resource")
 
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/r1", env = {"DEPTH": "0"}, properties = "<D:allprop />")
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/r1")
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
 
-        props = response.findall("{DAV:}propstat/{DAV:}prop")
-        self.assertEqual(len(props), 1) # only one prop element
+        z3c.etree.testing.assertXMLEqual(
+            '<resourcetype xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}resourcetype"))
+        z3c.etree.testing.assertXMLEqual(
+            '<creationdate xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}creationdate"))
+        z3c.etree.testing.assertXMLEqual(
+            '<displayname xmlns="DAV:">Test Resource</displayname>',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}displayname"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getlastmodified xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}getlastmodified"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getcontenttype xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}getcontenttype"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getcontentlength xmlns="DAV:">21</getcontentlength>',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}getcontentlength"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getcontentlanguage xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}getcontentlanguage"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getetag xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r1", "{DAV:}getetag"))
 
-        ## See README.txt for a list of properties defined for these tests.
-        self.assertMSPropertyValue(response, "{DAV:}resourcetype")
-        self.assertMSPropertyValue(response, "{DAV:}creationdate")
-        self.assertMSPropertyValue(response, "{DAV:}displayname",
-                                   text_value = "Test Resource")
-        self.assertMSPropertyValue(response, "{DAV:}getlastmodified")
-        self.assertMSPropertyValue(response, "{DAV:}getcontenttype")
-        self.assertMSPropertyValue(response, "{DAV:}getcontentlength",
-                                   text_value = "21")
-        self.assertMSPropertyValue(response, "{DAV:}getcontentlanguage")
-        self.assertMSPropertyValue(response, "{DAV:}getetag")
-
     def test_allprop_by_default(self):
         self.addCollection("/coll")
-        httpresponse, xmlbody = self.checkPropfind("/coll",
-                                                   env = {"DEPTH": "0"},
-                                                   properties = "<D:prop />")
-        # the rest is copied from the previous code.
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/coll/")
+        httpresponse = self.checkPropfind("/coll",
+                                          env = {"DEPTH": "0"},
+                                          properties = "<D:prop />")
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
 
-        props = response.findall("{DAV:}propstat/{DAV:}prop")
-        self.assertEqual(len(props), 1) # only one prop element
+        z3c.etree.testing.assertXMLEqual(
+            '<resourcetype xmlns="DAV:"><collection /></resourcetype>',
+            httpresponse.getMSProperty(
+                "http://localhost/coll/", "{DAV:}resourcetype"))
+        z3c.etree.testing.assertXMLEqual(
+            '<displayname xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/coll/", "{DAV:}displayname"))
 
-        ## See README.txt for a list of properties defined for these tests.
-        self.assertMSPropertyValue(response, "{DAV:}resourcetype",
-                                   tag = "{DAV:}collection", text_value = None)
-        self.assertMSPropertyValue(response, "{DAV:}displayname")
-
     def test_nobody_propfind(self):
         self.addCollection("/coll", title = u"Test Collection")
         
-        httpresponse, xmlbody = self.checkPropfind("/coll",
-                                                   env = {"DEPTH": "0"})
-        # the rest is copied from the previous code.
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/coll/")
+        httpresponse = self.checkPropfind("/coll",
+                                          env = {"DEPTH": "0"})
 
-        props = response.findall("{DAV:}propstat/{DAV:}prop")
-        self.assertEqual(len(props), 1) # only one prop element
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
 
-        ## See README.txt for a list of properties defined for these tests.
-        self.assertMSPropertyValue(response, "{DAV:}resourcetype",
-                                   tag = "{DAV:}collection")
-        self.assertMSPropertyValue(response, "{DAV:}displayname",
-                                   text_value = "Test Collection")
+        z3c.etree.testing.assertXMLEqual(
+            '<resourcetype xmlns="DAV:"><collection /></resourcetype>',
+            httpresponse.getMSProperty(
+                "http://localhost/coll/", "{DAV:}resourcetype"))
+        z3c.etree.testing.assertXMLEqual(
+            '<displayname xmlns="DAV:">Test Collection</displayname>',
+            httpresponse.getMSProperty(
+                "http://localhost/coll/", "{DAV:}displayname"))
 
     def test_notfound_property(self):
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/", env = {"DEPTH": "0"},
             properties = """<D:prop>
   <D:resourcetype />
   <D:missingproperty />
 </D:prop>""")
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/")
 
-        self.assertMSPropertyValue(response, "{DAV:}resourcetype",
-                                   tag = "{DAV:}collection")
-        self.assertMSPropertyValue(response, "{DAV:}missingproperty",
-                                   status = 404)
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
+        z3c.etree.testing.assertXMLEqual(
+            '<resourcetype xmlns="DAV:"><collection /></resourcetype>',
+            httpresponse.getMSProperty(
+                "http://localhost/", "{DAV:}resourcetype"))
+        z3c.etree.testing.assertXMLEqual(
+            '<missingproperty xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/", "{DAV:}missingproperty", status = 404))
 
     def test_depthinf(self):
         self.createCollectionResourceStructure()
 
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/", env = {"DEPTH": "infinity"},
             properties = "<D:prop><D:resourcetype /></D:prop>")
 
-        responses = xmlbody.findall("{DAV:}response")
+        responses = httpresponse.getMSResponses()
         self.assertEqual(len(responses), 7)
 
-        # make sure we have all 200 status codes, and the hrefs differ
+        # make sure we have all 200 status codes, and collect all hrefs
+        allhrefs = []
         for response in responses:
             propstats  = response.findall("{DAV:}propstat")
             self.assertEqual(len(propstats), 1)
             statusresp = response.findall("{DAV:}propstat/{DAV:}status")
             self.assertEqual(len(statusresp), 1)
             self.assertEqual(statusresp[0].text, "HTTP/1.1 200 OK")
+            hrefs = response.findall("{DAV:}href")
+            self.assertEqual(len(hrefs), 1)
+            allhrefs.append(hrefs[0].text)
 
-        hrefs = [href.text for href in
-                 xmlbody.findall("{DAV:}response/{DAV:}href")]
-        hrefs.sort()
-        self.assertEqual(hrefs, ["http://localhost/",
-                                 "http://localhost/++etc++site/",
-                                 "http://localhost/a/",
-                                 "http://localhost/a/r2",
-                                 "http://localhost/a/r3",
-                                 "http://localhost/b/",
-                                 "http://localhost/r1"])
+        allhrefs.sort()
 
+        self.assertEqual(allhrefs, ["http://localhost/",
+                                    "http://localhost/++etc++site/",
+                                    "http://localhost/a/",
+                                    "http://localhost/a/r2",
+                                    "http://localhost/a/r3",
+                                    "http://localhost/b/",
+                                    "http://localhost/r1"])
+
     def test_depthone(self):
         self.createCollectionResourceStructure()
 
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/", env = {"DEPTH": "1"},
             properties = "<D:prop><D:resourcetype /></D:prop>")
 
-        responses = xmlbody.findall("{DAV:}response")
+        responses = httpresponse.getMSResponses()
         self.assertEqual(len(responses), 5)
 
-        # make sure we have all 200 status codes, and the hrefs differ
+        # make sure we have all 200 status codes, and collect all hrefs
+        allhrefs = []
         for response in responses:
             propstats  = response.findall("{DAV:}propstat")
             self.assertEqual(len(propstats), 1)
             statusresp = response.findall("{DAV:}propstat/{DAV:}status")
             self.assertEqual(len(statusresp), 1)
             self.assertEqual(statusresp[0].text, "HTTP/1.1 200 OK")
+            hrefs = response.findall("{DAV:}href")
+            self.assertEqual(len(hrefs), 1)
+            allhrefs.append(hrefs[0].text)
 
-        hrefs = [href.text for href in
-                 xmlbody.findall("{DAV:}response/{DAV:}href")]
-        hrefs.sort()
-        self.assertEqual(hrefs, ["http://localhost/",
-                                 "http://localhost/++etc++site/",
-                                 "http://localhost/a/",
-                                 "http://localhost/b/",
-                                 "http://localhost/r1"])
+        allhrefs.sort()
 
+        self.assertEqual(allhrefs, ["http://localhost/",
+                                    "http://localhost/++etc++site/",
+                                    "http://localhost/a/",
+                                    "http://localhost/b/",
+                                    "http://localhost/r1"])
+
     def test_opaque_properties(self):
         file = self.addResource("/r", "some file content",
                                 title = u"Test resource")
@@ -318,26 +339,19 @@
 <D:resourcetype /><E:testdeadprop />
 </D:prop>
 """
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/r", env = {"DEPTH": "0"}, properties = properties)
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
+        z3c.etree.testing.assertXMLEqual(
+            '<resourcetype xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r", "{DAV:}resourcetype"))
+        z3c.etree.testing.assertXMLEqual(
+            '<testdeadprop xmlns="examplens:">TEST</testdeadprop>',
+            httpresponse.getMSProperty(
+                "http://localhost/r", "{examplens:}testdeadprop"))
 
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/r")
-
-        propstats = response.findall("{DAV:}propstat")
-        self.assertEqual(len(propstats), 1)
-        props = propstats[0].findall("{DAV:}prop")
-        self.assertEqual(len(props), 1)
-
-        self.assertMSPropertyValue(response, "{DAV:}resourcetype")
-        self.assertMSPropertyValue(response, "{examplens:}testdeadprop",
-                                   text_value = "TEST")
-
     def test_allprop_with_opaque_properties(self):
         file = self.addResource("/r", "some file content",
                                 title = u"Test Resource")
@@ -349,7 +363,7 @@
         transaction.commit()
 
         properties = "<D:allprop />"
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/r", env = {"DEPTH": "0"}, properties = properties)
 
     def test_unicode_title(self):
@@ -357,18 +371,18 @@
         file = self.addResource(u"/" + teststr, "some file content",
                                 title = teststr)
 
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/" + teststr.encode("utf-8"), env = {"DEPTH": "0",
                                                   "CONTENT_TYPE": "text/xml"},
             properties = "<D:prop><D:displayname /></D:prop>")
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
+        want = '<displayname xmlns="DAV:">%s</displayname>' % teststr
+        z3c.etree.testing.assertXMLEqual(
+            want.encode("utf-8"), # needed in order for elementtree to parse
+            httpresponse.getMSProperty(
+                "http://localhost/%s" % urllib.quote(teststr.encode("utf-8")),
+                "{DAV:}displayname"))
 
-        self.assertMSPropertyValue(response, "{DAV:}displayname",
-                                   text_value = teststr)
-
     def test_allprop_with_deadprops(self):
         file = self.addResource("/r", "some content", title = u"Test Resource")
 
@@ -378,18 +392,17 @@
 This is a dead property.</X:deadprop>""")
         transaction.commit()
 
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/r", env = {"DEPTH": "0", "CONTENT_TYPE": "text/xml"},
             properties = "<D:allprop />")
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
+        z3c.etree.testing.assertXMLEqual(
+            """<deadprop xmlns="deadprop:">
+This is a dead property.</deadprop>""",
+            httpresponse.getMSProperty(
+                "http://localhost/r", "{deadprop:}deadprop"))
 
-        self.assertMSPropertyValue(response, "{deadprop:}deadprop",
-                                   text_value = """
-This is a dead property.""")
-
     def test_allprop_with_restricted(self):
         file = self.addResource("/r", "some content", title = u"Test Resource")
 
@@ -398,21 +411,13 @@
         examplePropStorage.exampletextprop = "EXAMPLE TEXT PROP"
         transaction.commit()
 
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/r", env = {"DEPTH": "0", "CONTENT_TYPE": "application/xml"},
             properties = "<D:allprop />")
 
-        hrefs = xmlbody.findall("{DAV:}response/{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/r")
+        self.assertRaises(KeyError, httpresponse.getMSProperty,
+                          "http://localhost/r", "{DAVtest:}exampletextprop")
 
-        props = xmlbody.findall("{DAV:}response/{DAV:}propstat/{DAV:}prop")
-        self.assertEqual(len(props), 1) # only one prop element
-
-        self.assertEqual([prop.tag for prop in
-                          props[0] if prop.tag == "{DAVtest:}exampletextprop"],
-                         [])
-
     def test_allprop_with_include(self):
         file = self.addResource("/r", "some content", title = u"Test Resource")
 
@@ -425,7 +430,7 @@
                                         name = "{DAVtest:}exampletextprop")
         textprop.restricted = True
 
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/r", env = {"DEPTH": "0", "CONTENT_TYPE": "application/xml"},
             properties = """<D:allprop />
 <D:include>
@@ -433,17 +438,12 @@
 </D:include>
 """)
 
-        hrefs = xmlbody.findall("{DAV:}response/{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/r")
+        z3c.etree.testing.assertXMLEqual(
+            """<exampletextprop
+                xmlns="DAVtest:">EXAMPLE TEXT PROP</exampletextprop>""",
+            httpresponse.getMSProperty(
+                "http://localhost/r", "{DAVtest:}exampletextprop"))
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
-
-        self.assertMSPropertyValue(response, "{DAVtest:}exampletextprop",
-                                   text_value = "EXAMPLE TEXT PROP")
-
     def test_allprop_with_include_on_unauthorized(self):
         file = self.addResource("/r", "some content", title = u"Test Resource")
 
@@ -455,7 +455,7 @@
   </D:include>
 </propfind>"""
 
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/r", env = {"DEPTH": "0", "CONTENT_TYPE": "application/xml"},
             properties = """<D:allprop />
 <D:include>
@@ -463,52 +463,54 @@
 </D:include>
 """)
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
 
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/r")
+        z3c.etree.testing.assertXMLEqual(
+            '<unauthprop xmlns="DAVtest:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r", "{DAVtest:}unauthprop", status = 401))
 
-        propstats = response.findall("{DAV:}propstat")
-        self.assertEqual(len(propstats), 2)
-        props = propstats[0].findall("{DAV:}prop")
-        self.assertEqual(len(props), 1)
-
-        self.assertMSPropertyValue(response, "{DAVtest:}unauthprop",
-                                   status = 401)
-
     def test_propfind_onfile(self):
         self.addResource("/testfile", "some file content",
                          contentType = "text/plain")
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/testfile", env = {"DEPTH": "0"}, properties = "<D:allprop />")
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
 
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/testfile")
-
-        propstats = response.findall("{DAV:}propstat")
-        self.assertEqual(len(propstats), 1)
-        props = propstats[0].findall("{DAV:}prop")
-        self.assertEqual(len(props), 1)
-
         # all properties should be defined on a file.
-        self.assertMSPropertyValue(response, "{DAV:}resourcetype")
-        self.assertMSPropertyValue(response, "{DAV:}creationdate")
-        self.assertMSPropertyValue(response, "{DAV:}displayname")
-        self.assertMSPropertyValue(response, "{DAV:}getcontentlanguage")
-        self.assertMSPropertyValue(response, "{DAV:}getcontentlength",
-                                   text_value = "17")
-        self.assertMSPropertyValue(response, "{DAV:}getcontenttype",
-                                   text_value = "text/plain")
-        self.assertMSPropertyValue(response, "{DAV:}getetag")
-        self.assertMSPropertyValue(response, "{DAV:}getlastmodified")
+        z3c.etree.testing.assertXMLEqual(
+            '<resourcetype xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/testfile", "{DAV:}resourcetype"))
+        z3c.etree.testing.assertXMLEqual(
+            '<creationdate xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/testfile", "{DAV:}creationdate"))
+        z3c.etree.testing.assertXMLEqual(
+            '<displayname xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/testfile", "{DAV:}displayname"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getcontentlanguage xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/testfile", "{DAV:}getcontentlanguage"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getcontentlength xmlns="DAV:">17</getcontentlength>',
+            httpresponse.getMSProperty(
+                "http://localhost/testfile", "{DAV:}getcontentlength"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getcontenttype xmlns="DAV:">text/plain</getcontenttype>',
+            httpresponse.getMSProperty(
+                "http://localhost/testfile", "{DAV:}getcontenttype"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getetag xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/testfile", "{DAV:}getetag"))
+        z3c.etree.testing.assertXMLEqual(
+            '<getlastmodified xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/testfile", "{DAV:}getlastmodified"))
 
 
 def test_suite():

Modified: z3c.dav/trunk/src/z3c/dav/ftests/test_proppatch.py
===================================================================
--- z3c.dav/trunk/src/z3c/dav/ftests/test_proppatch.py	2007-05-06 14:10:22 UTC (rev 75565)
+++ z3c.dav/trunk/src/z3c/dav/ftests/test_proppatch.py	2007-05-06 14:41:45 UTC (rev 75566)
@@ -16,6 +16,7 @@
 $Id$
 """
 
+import urllib
 import unittest
 from cStringIO import StringIO
 import transaction
@@ -79,15 +80,14 @@
         set_properties = "<D:displayname>Test File</D:displayname>"
         self.addResource("/r", "some content", title = u"Test Resource")
 
-        httpresponse, xmlbody = self.checkProppatch(
+        httpresponse = self.checkProppatch(
             "/r", basic = "mgr:mgrpw", set_properties = set_properties)
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
+        assertXMLEqual('<displayname xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r", "{DAV:}displayname"))
 
-        self.assertMSPropertyValue(response, "{DAV:}displayname")
-
         title = IZopeDublinCore(self.getRootFolder()["r"]).title
         self.assertEqual(title, u"Test File")
 
@@ -95,39 +95,32 @@
         set_properties = "<D:getcontentlength>10</D:getcontentlength>"
         self.addResource("/r", "some file content", title = u"Test Resource")
 
-        httpresponse, xmlbody = self.checkProppatch(
+        httpresponse = self.checkProppatch(
             "/r", basic = "mgr:mgrpw", set_properties = set_properties)
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/r")
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
+        assertXMLEqual(
+            '<getcontentlength xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r", "{DAV:}getcontentlength", status = 403))
 
-        self.assertMSPropertyValue(response, "{DAV:}getcontentlength",
-                                   status = 403)
-
     def test_badinput(self):
         set_properties = """
         <E:exampleintprop xmlns:E="DAVtest:">BAD INT</E:exampleintprop>
         """
         resource = self.addResource("/testresource", "some resource content")
 
-        httpresponse, xmlbody = self.checkProppatch(
+        httpresponse = self.checkProppatch(
             "/testresource", basic = "mgr:mgrpw",
             set_properties = set_properties)
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/testresource")
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
+        assertXMLEqual(
+            '<exampleintprop xmlns="DAVtest:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/testresource", "{DAVtest:}exampleintprop",
+                status = 409))
 
-        self.assertMSPropertyValue(response, "{DAVtest:}exampleintprop",
-                                   status = 409)
-
     def test_badinput_plus_faileddep(self):
         set_properties = """
         <E:exampleintprop xmlns:E="DAVtest:">BAD INT</E:exampleintprop>
@@ -144,22 +137,22 @@
         exampleStorage.exampletextprop = u"Example Text Property"
         transaction.commit()
 
-        httpresponse, xmlbody = self.checkProppatch(
+        httpresponse = self.checkProppatch(
             "/testresource", basic = "mgr:mgrpw",
             set_properties = set_properties)
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/testresource")
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
+        assertXMLEqual(
+            '<exampletextprop xmlns="DAVtest:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/testresource", "{DAVtest:}exampletextprop",
+                status = 424))
+        assertXMLEqual(
+            '<exampleintprop xmlns="DAVtest:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/testresource", "{DAVtest:}exampleintprop",
+                status = 409))
 
-        self.assertMSPropertyValue(response, "{DAVtest:}exampletextprop",
-                                   status = 424)
-        self.assertMSPropertyValue(response, "{DAVtest:}exampleintprop",
-                                   409)
-
         exampleStorage = component.getMultiAdapter((resource, request),
                                                    dav.IExamplePropertyStorage)
         self.assertEqual(exampleStorage.exampletextprop,
@@ -173,7 +166,7 @@
         file = self.addResource("/r", "some content",
                                 title = u"Test Resource")
 
-        httpresponse, xmlbody = self.checkProppatch(
+        httpresponse = self.checkProppatch(
             "/r", basic = "mgr:mgrpw", set_properties = set_properties)
 
         opaqueProperties = z3c.dav.interfaces.IOpaquePropertyStorage(file)
@@ -194,7 +187,7 @@
 
         file = self.addResource("/r", "some content", title = u"Test Resource")
 
-        httpresponse, xmlbody = self.checkProppatch(
+        httpresponse = self.checkProppatch(
             "/r", basic = "mgr:mgrpw", set_properties = set_properties)
 
         opaqueProperties = z3c.dav.interfaces.IOpaquePropertyStorage(file)
@@ -208,15 +201,15 @@
         set_properties = "<D:displayname>%s</D:displayname>" % teststr
         self.addResource("/r", "some content", title = u"Test Resource")
 
-        httpresponse, xmlbody = self.checkProppatch(
+        httpresponse = self.checkProppatch(
             "/r", basic = "mgr:mgrpw", set_properties = set_properties)
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
+        assertXMLEqual(
+            '<displayname xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r", "{DAV:}displayname"))
 
-        self.assertMSPropertyValue(response, "{DAV:}displayname")
-
     def test_remove_live_prop(self):
         file = self.addResource("/r", "some content", title = u"Test Resource")
 
@@ -226,31 +219,18 @@
 This is a dead property.</X:deadprop>""")
         transaction.commit()
 
-        httpresponse, xmlbody = self.checkProppatch(
+        httpresponse = self.checkProppatch(
             "/r", basic = "mgr:mgrpw",
             remove_properties = """<E:exampleintprop xmlns:E="DAVtest:" />""")
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
 
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/r")
+        assertXMLEqual(
+            '<exampleintprop xmlns="DAVtest:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r", "{DAVtest:}exampleintprop",
+                status = 409))
 
-        propstat = response.findall("{DAV:}propstat")
-        self.assertEqual(len(propstat), 1)
-        propstat = propstat[0]
-
-        self.assertEqual(len(propstat), 2)
-
-        props = propstat.findall("{DAV:}prop")
-        self.assertEqual(len(props), 1)
-        self.assertEqual(len(props[0]), 1) # there is only one property.
-
-        self.assertMSPropertyValue(response, "{DAVtest:}exampleintprop",
-                                   status = 409)
-
     def test_remove_dead_prop(self):
         proptag = "{deadprop:}deadprop"
         file = self.addResource("/r", "some content", title = u"Test Resource")
@@ -261,16 +241,16 @@
 This is a dead property.</X:deadprop>""")
         transaction.commit()
 
-        httpresponse, xmlbody = self.checkProppatch(
+        httpresponse = self.checkProppatch(
             "/r", basic = "mgr:mgrpw",
             remove_properties = """<X:deadprop xmlns:X="deadprop:" />""")
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
+        assertXMLEqual(
+            '<deadprop xmlns="deadprop:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/r", "{deadprop:}deadprop"))
 
-        self.assertMSPropertyValue(response, proptag)
-
         opaqueProperties = z3c.dav.interfaces.IOpaquePropertyStorage(file)
         self.assertEqual(opaqueProperties.hasProperty(proptag), False)
 
@@ -279,15 +259,17 @@
         self.addResource(u"/" + teststr, "some file content",
                          title = u"Old title")
 
-        httpresponse, xmlbody = self.checkProppatch(
+        httpresponse = self.checkProppatch(
             "/" + teststr.encode("utf-8"), basic = "mgr:mgrpw",
             set_properties = "<D:displayname>%s</D:displayname>" % teststr)
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
+        assertXMLEqual(
+            '<displayname xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/%s" % urllib.quote(teststr.encode("utf-8")),
+                "{DAV:}displayname"))
 
-        self.assertMSPropertyValue(response, "{DAV:}displayname")
         resourcetitle = IZopeDublinCore(self.getRootFolder()[teststr]).title
         self.assertEqual(resourcetitle, teststr)
 

Modified: z3c.dav/trunk/src/z3c/dav/ftests/test_z3_locking.py
===================================================================
--- z3c.dav/trunk/src/z3c/dav/ftests/test_z3_locking.py	2007-05-06 14:10:22 UTC (rev 75565)
+++ z3c.dav/trunk/src/z3c/dav/ftests/test_z3_locking.py	2007-05-06 14:41:45 UTC (rev 75566)
@@ -23,6 +23,7 @@
 from cStringIO import StringIO
 import os.path
 
+import z3c.dav.testing
 import z3c.dav.ftests.dav
 
 from zope import component
@@ -40,7 +41,7 @@
 from z3c.etree.testing import assertXMLEqual
 
 here = os.path.dirname(os.path.realpath(__file__))
-WebDAVLockingLayer = z3c.dav.ftests.dav.WebDAVLayerClass(
+WebDAVLockingLayer = z3c.dav.testing.WebDAVLayerClass(
    os.path.join(here, "ftesting-locking.zcml"), __name__, "WebDAVLockingLayer")
 
 
@@ -69,23 +70,26 @@
         self.addResource("/testfile", "some file content",
                          contentType = "text/plain")
 
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/testfile", env = {"DEPTH": "0"},
             properties = """<D:prop>
 <D:supportedlock />
 <D:lockdiscovery />
 </D:prop>""")
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
+        assertXMLEqual(
+            '<supportedlock xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/testfile", "{DAV:}supportedlock",
+                status = 404))
+        assertXMLEqual(
+            '<lockdiscovery xmlns="DAV:" />',
+            httpresponse.getMSProperty(
+                "http://localhost/testfile", "{DAV:}lockdiscovery",
+                status = 404))
 
-        self.assertMSPropertyValue(response, "{DAV:}supportedlock",
-                                   status = 404)
-        self.assertMSPropertyValue(response, "{DAV:}lockdiscovery",
-                                   status = 404)
 
-
 class LOCKTestCase(z3c.dav.ftests.dav.DAVTestCase):
 
     layer = WebDAVLockingLayer
@@ -416,34 +420,13 @@
         locktoken = response.getHeader("lock-token")
         self.assert_(locktoken and locktoken[0] == "<" and locktoken[-1] == ">")
 
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/a/r2", env = {"DEPTH": "0", "CONTENT_TYPE": "text/xml"},
             properties = "<D:allprop />")
 
-        hrefs = xmlbody.findall("{DAV:}response/{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/a/r2")
-
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
-
-        propstat = response.findall("{DAV:}propstat")
-        self.assertEqual(len(propstat), 1)
-        propstat = propstat[0]
-
-        status = propstat.findall("{DAV:}status")
-        self.assertEqual(len(status), 1)
-        status = status[0]
-        self.assertEqual(status.text, "HTTP/1.1 200 OK")
-
-        props = propstat.findall("{DAV:}prop")
-        self.assertEqual(len(props), 1)
-        props = props[0]
-
-        supportedlock = props.findall("{DAV:}supportedlock")
-        self.assertEqual(len(supportedlock), 1)
-        assertXMLEqual(supportedlock[0], """<ns0:supportedlock xmlns:ns0="DAV:">
+        supportedlock = httpresponse.getMSProperty(
+            "http://localhost/a/r2", "{DAV:}supportedlock")
+        assertXMLEqual(supportedlock, """<ns0:supportedlock xmlns:ns0="DAV:">
 <ns0:lockentry xmlns:ns0="DAV:">
   <ns0:lockscope xmlns:ns0="DAV:"><ns0:exclusive xmlns:ns0="DAV:"/></ns0:lockscope>
   <ns0:locktype xmlns:ns0="DAV:"><ns0:write xmlns:ns0="DAV:"/></ns0:locktype>
@@ -453,9 +436,9 @@
   <ns0:locktype xmlns:ns0="DAV:"><ns0:write xmlns:ns0="DAV:"/></ns0:locktype>
 </ns0:lockentry></ns0:supportedlock>""")
 
-        lockdiscovery = props.findall("{DAV:}lockdiscovery")
-        self.assertEqual(len(lockdiscovery), 1)
-        assertXMLEqual(lockdiscovery[0], """<ns0:lockdiscovery xmlns:ns0="DAV:">
+        lockdiscovery = httpresponse.getMSProperty(
+            "http://localhost/a/r2", "{DAV:}lockdiscovery")
+        assertXMLEqual(lockdiscovery, """<ns0:lockdiscovery xmlns:ns0="DAV:">
 <ns0:activelock xmlns:ns0="DAV:">
   <ns0:lockscope xmlns:ns0="DAV:"><ns0:exclusive xmlns:ns0="DAV:"/></ns0:lockscope>
   <ns0:locktype xmlns:ns0="DAV:"><ns0:write xmlns:ns0="DAV:"/></ns0:locktype>
@@ -779,24 +762,11 @@
     def test_supportedlock_prop(self):
         file = self.addResource("/testfile", "some file content",
                                 contentType = "text/plain")
-        httpresponse, xmlbody = self.checkPropfind(
+        httpresponse = self.checkPropfind(
             "/testfile", properties = "<D:prop><D:supportedlock /></D:prop>")
 
-        responses = xmlbody.findall("{DAV:}response")
-        self.assertEqual(len(responses), 1)
-        response = responses[0]
+        self.assertEqual(len(httpresponse.getMSResponses()), 1)
 
-        hrefs = response.findall("{DAV:}href")
-        self.assertEqual(len(hrefs), 1)
-        self.assertEqual(hrefs[0].text, "http://localhost/testfile")
-
-        propstats = response.findall("{DAV:}propstat")
-        self.assertEqual(len(propstats), 1)
-        props = propstats[0].findall("{DAV:}prop")
-        self.assertEqual(len(props), 1)
-
-        self.assertEqual(len(props[0]), 1)
-
         expected = """<D:supportedlock xmlns:D="DAV:">
 <D:lockentry>
   <D:lockscope><D:exclusive /></D:lockscope>
@@ -806,9 +776,8 @@
   <D:lockscope><D:shared /></D:lockscope>
   <D:locktype><D:write /></D:locktype>
 </D:lockentry></D:supportedlock>"""
-        self.assertMSPropertyValue(response, "{DAV:}supportedlock",
-                                   tag = "{DAV:}lockentry",
-                                   prop_element = expected)
+        assertXMLEqual(expected, httpresponse.getMSProperty(
+            "http://localhost/testfile", "{DAV:}supportedlock"))
 
 
 def test_suite():

Added: z3c.dav/trunk/src/z3c/dav/testing.py
===================================================================
--- z3c.dav/trunk/src/z3c/dav/testing.py	2007-05-06 14:10:22 UTC (rev 75565)
+++ z3c.dav/trunk/src/z3c/dav/testing.py	2007-05-06 14:41:45 UTC (rev 75566)
@@ -0,0 +1,348 @@
+##############################################################################
+# Copyright (c) 2007 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.
+##############################################################################
+"""
+Miscellaneous utilities used for testing WebDAV components.
+
+$Id$
+"""
+__docformat__ = "restructuredtext"
+
+import zope.publisher.publish
+from zope.publisher.http import status_reasons
+import zope.app.testing.functional
+import zope.app.publication.http
+
+import z3c.etree.testing
+import z3c.dav.publisher
+
+class WebDAVLayerClass(zope.app.testing.functional.ZCMLLayer):
+
+    def setUp(self):
+        z3c.etree.testing.etreeSetup()
+        zope.app.testing.functional.ZCMLLayer.setUp(self)
+
+    def tearDown(self):
+        z3c.etree.testing.etreeTearDown()
+        zope.app.testing.functional.ZCMLLayer.tearDown(self)
+
+
+class WebDAVResponseWrapper(zope.app.testing.functional.ResponseWrapper):
+    """
+
+    A HTTP response wrapper that adds support for parsing and retrieving
+    information out of a 207 Multi-Status response. The idea is to make
+    writing tests for different WebDAV components a lot easier.
+
+      >>> from zope.publisher.http import HTTPResponse
+      >>> etree = z3c.etree.getEngine()
+
+      >>> response = HTTPResponse()
+      >>> wrapped = WebDAVResponseWrapper(response, '/testfile.txt')
+
+    Get a list of response sub elements from the multistatus response body
+    with the `getMSResponses` method.
+
+      >>> wrapped.getMSResponses()
+      Traceback (most recent call last):
+      ...
+      ValueError: Not a multistatus response
+
+      >>> response.setStatus(207)
+      >>> wrapped.getMSResponses()
+      Traceback (most recent call last):
+      ...
+      ValueError: Invalid response content type
+
+      >>> response.setHeader('content-type', 'application/xml')
+      >>> response.setResult('<testdata />')
+      >>> wrapped.getMSResponses()
+      Traceback (most recent call last):
+      ...
+      ValueError: Invalid multistatus response body
+
+      >>> response.setResult('<multistatus xmlns="DAV:" />')
+      >>> wrapped._body = None # turn off cache
+      >>> wrapped.getMSResponses()
+      Traceback (most recent call last):
+      ...
+      ValueError: No multistatus response present
+
+    Add some a valid multistatus response to test with. Even though this
+    data is in complete it is enough for the getMSResponses method to
+    work with.
+
+      >>> response.setResult('''<multistatus xmlns="DAV:">
+      ...   <response />
+      ... </multistatus>''')
+      >>> wrapped._body = None # turn off cache
+
+      >>> msresponses = wrapped.getMSResponses()
+      >>> len(msresponses)
+      1
+      >>> print etree.tostring(msresponses[0]) #doctest:+XMLDATA
+      <response xmlns="DAV:" />
+
+    Now use the `getMSResponse(href)` to get a response element who's href
+    element matches the argument.
+
+      >>> wrapped.getMSResponse('/testfile.txt')
+      Traceback (most recent call last):
+      ...
+      ValueError: Invalid multistatus response body
+
+      >>> response.setResult('''<multistatus xmlns="DAV:">
+      ...   <response>
+      ...     <href>/testfile.txt</href>
+      ...   </response>
+      ... </multistatus>''')
+      >>> wrapped._body = None # turn off cache
+
+      >>> print etree.tostring(
+      ...    wrapped.getMSResponse('/testfile.txt')) #doctest:+XMLDATA
+      <response xmlns="DAV:">
+        <href>/testfile.txt</href>
+      </response>
+
+    If no response element exist then a KeyError is raised.
+
+      >>> wrapped.getMSResponse('/missingfile.txt')
+      Traceback (most recent call last):
+      ...
+      KeyError: "Multistatus response contained no response for the resource '/missingfile.txt'"
+
+    Get the propstat element with a specific status via the `getMSPropstat`
+    method. We need to pass in a href and a status in order to find
+    a specific value. Note that all methods raise a ValueError when the
+    response doesn't correspond to the 207 multistatus protocol.
+
+      >>> wrapped.getMSPropstat('/testfile.txt', 404)
+      Traceback (most recent call last):
+      ...
+      ValueError: Response contains no propstats sub elements
+
+      >>> response.setResult('''<multistatus xmlns="DAV:">
+      ...   <response>
+      ...     <href>/testfile.txt</href>
+      ...     <propstat>
+      ...       <prop>
+      ...         <t1:testprop xmlns:t1="testns:">Test property</t1:testprop>
+      ...       </prop>
+      ...     </propstat>
+      ...   </response>
+      ... </multistatus>''')
+      >>> wrapped._body = None # turn off cache
+
+      >>> wrapped.getMSPropstat('/testfile.txt', 200)
+      Traceback (most recent call last):
+      ...
+      ValueError: Response containers invalid number of status elements
+
+    The propstat element is not complete here but again there is enough
+    information for `getMSPropstat` method to do its job.
+
+      >>> response.setResult('''<multistatus xmlns="DAV:">
+      ...   <response>
+      ...     <href>/testfile.txt</href>
+      ...     <propstat>
+      ...       <status>HTTP/1.1 404 Not Found</status>
+      ...     </propstat>
+      ...   </response>
+      ... </multistatus>''')
+      >>> wrapped._body = None # turn off cache
+
+      >>> wrapped.getMSPropstat('/testfile.txt', 200)
+      Traceback (most recent call last):
+      ...
+      KeyError: 'No propstats element with status 200'
+
+      >>> print etree.tostring(
+      ...    wrapped.getMSPropstat('/testfile.txt', 404)) #doctest:+XMLDATA
+      <propstat xmlns="DAV:">
+        <status>HTTP/1.1 404 Not Found</status>
+      </propstat>
+
+    Get a specific property value from a propstat element corresponding to
+    a specific status via the `getMSProperty` method.
+
+      >>> wrapped.getMSProperty('/testfile.txt', '{testns:}missin', 404)
+      Traceback (most recent call last):
+      ...
+      ValueError: Invalid propstat sub element - no prop element
+
+    Finally set up a completely valid multistatus response.
+
+      >>> response.setResult('''<multistatus xmlns="DAV:">
+      ...   <response>
+      ...     <href>/testfile.txt</href>
+      ...     <propstat>
+      ...       <prop>
+      ...         <t1:testprop xmlns:t1="testns:">Test property</t1:testprop>
+      ...       </prop>
+      ...       <status>HTTP/1.1 404 Not Found</status>
+      ...     </propstat>
+      ...   </response>
+      ... </multistatus>''')
+      >>> wrapped._body = None # turn off cache
+
+      >>> wrapped.getMSProperty('/testfile.txt', '{testns:}missing', 404)
+      Traceback (most recent call last):
+      ...
+      KeyError: "'{testns:}missing' property not found for resource /testfile.txt (404)"
+
+      >>> print etree.tostring(wrapped.getMSProperty(
+      ...    '/testfile.txt', '{testns:}testprop', 404)) #doctest:+XMLDATA
+      <testprop xmlns="testns:">Test property</testprop>
+
+    """
+
+    def __init__(self, response, path, omit = ()):
+        super(WebDAVResponseWrapper, self).__init__(response, path, omit)
+        self._xmlcachebody = None
+
+    def getMSResponses(self):
+        if self._response.getStatus() != 207:
+            raise ValueError("Not a multistatus response")
+        if self._response.getHeader('content-type') != 'application/xml':
+            raise ValueError("Invalid response content type")
+
+        etree = z3c.etree.getEngine()
+        self._xmlcachebody = etree.fromstring(self.getBody())
+        if self._xmlcachebody.tag != "{DAV:}multistatus":
+            raise ValueError("Invalid multistatus response body")
+
+        responses = self._xmlcachebody.findall("{DAV:}response")
+        if not responses:
+            raise ValueError("No multistatus response present")
+
+        return responses
+
+    def getMSResponse(self, href):
+        ret = []
+        for response in self.getMSResponses():
+            hrefs = response.findall("{DAV:}href")
+            if len(hrefs) != 1:
+                raise ValueError("Invalid multistatus response body")
+
+            if hrefs[0].text == href:
+                ret.append(response)
+
+        if not ret:
+            raise KeyError("Multistatus response contained no response for " \
+                           "the resource %r" % href)
+        if len(ret) > 1:
+            raise ValueError("Multistatus response contains too many " \
+                             "responses for the response %r" % href)
+
+        return ret[0]
+
+    def getMSPropstat(self, href, status = 200):
+        msresponse = self.getMSResponse(href)
+
+        propstats = msresponse.findall("{DAV:}propstat")
+        if not propstats:
+            raise ValueError("Response contains no propstats sub elements")
+
+        ret = []
+        for propstatus in propstats:
+            psstatus = propstatus.findall("{DAV:}status")
+            if len(psstatus) != 1:
+                raise ValueError("Response containers invalid number of " \
+                                 "status elements")
+
+            if psstatus[0].text == "HTTP/1.1 %d %s" %(status,
+                                                      status_reasons[status]):
+                ret.append(propstatus)
+
+        if not ret:
+            raise KeyError("No propstats element with status %d" % status)
+        if len(ret) > 1:
+            raise ValueError("Too many propstats with the same status")
+
+        return ret[0]
+
+    def getMSProperty(self, href, proptag, status = 200):
+        propstat = self.getMSPropstat(href, status)
+
+        props = propstat.findall("{DAV:}prop")
+        if len(props) != 1:
+            raise ValueError("Invalid propstat sub element - no prop element")
+        props = props[0]
+
+        ret = []
+        for prop in props:
+            if prop.tag == proptag:
+                ret.append(prop)
+
+        if not ret:
+            raise KeyError("%r property not found for resource %s (%d)" %(
+                proptag, href, status))
+        if len(ret) > 1:
+            raise ValueError("Too many %r properties found" % proptag)
+
+        return ret[0]
+
+
+class WebDAVTestCase(zope.app.testing.functional.HTTPTestCase):
+
+    def makeRequest(self, path = "", basic = None, form = None,
+                    env = {}, instream = None):
+        """Create a new WebDAV request
+        """
+        if instream is None:
+            instream = ""
+
+        environment = {"HTTP_HOST": "localhost",
+                       "HTTP_REFERER": "localhost"}
+        environment.update(env)
+        if instream and "CONTENT_LENGTH" not in environment:
+            if getattr(instream, "getvalue", None) is not None:
+                instream = instream.getvalue()
+            environment["CONTENT_LENGTH"] = len(instream)
+
+        app = \
+            zope.app.testing.functional.FunctionalTestSetup().getApplication()
+
+        request = app._request(
+            path, instream, environment = environment,
+            basic = basic, form = form,
+            request = z3c.dav.publisher.WebDAVRequest,
+            publication = zope.app.publication.http.HTTPPublication)
+
+        return request
+
+    def publish(self, path, basic = None, form = None, env = {},
+                handle_errors = False, request_body = ""):
+        request = self.makeRequest(path, basic = basic, form = form, env = env,
+                                   instream = request_body)
+        response = WebDAVResponseWrapper(request.response, path)
+
+        zope.publisher.publish.publish(request, handle_errors = handle_errors)
+
+        return response
+
+
+class WebDAVCaller(zope.app.testing.functional.HTTPCaller):
+
+    def __call__(self, request_string, handle_errors = True, form = None):
+        response = super(WebDAVCaller, self).__call__(
+            request_string, handle_errors, form)
+
+        # response should be a zope.app.testing.functional.ResponseWrapper
+        return WebDAVResponseWrapper(response, response._path, response.omit)
+
+
+def functionalSetUp(test):
+    test.globs["webdav"] = WebDAVCaller()
+
+
+def functionalTearDown(test):
+    del test.globs["webdav"]

Modified: z3c.dav/trunk/src/z3c/dav/tests/test_doctests.py
===================================================================
--- z3c.dav/trunk/src/z3c/dav/tests/test_doctests.py	2007-05-06 14:10:22 UTC (rev 75565)
+++ z3c.dav/trunk/src/z3c/dav/tests/test_doctests.py	2007-05-06 14:41:45 UTC (rev 75566)
@@ -255,4 +255,8 @@
                              setUp = z3c.etree.testing.etreeSetup,
                              tearDown = z3c.etree.testing.etreeTearDown),
         doctest.DocTestSuite("z3c.dav.mkcol"),
+        doctest.DocTestSuite("z3c.dav.testing",
+                             checker = z3c.etree.testing.xmlOutputChecker,
+                             setUp = z3c.etree.testing.etreeSetup,
+                             tearDown = z3c.etree.testing.etreeTearDown),
         ))



More information about the Checkins mailing list