[Zope3-checkins] CVS: Zope3/src/zope/testing - functional.py:1.6

Marius Gedminas mgedmin@codeworks.lt
Thu, 1 May 2003 10:07:30 -0400


Update of /cvs-repository/Zope3/src/zope/testing
In directory cvs.zope.org:/tmp/cvs-serv17091/src/zope/testing

Modified Files:
	functional.py 
Log Message:
FunctionalTestCase.checkForBrokenLinks now pays attention to <base> element
and actually performs the traversal properly.


=== Zope3/src/zope/testing/functional.py 1.5 => 1.6 ===
--- Zope3/src/zope/testing/functional.py:1.5	Fri Apr 25 15:28:41 2003
+++ Zope3/src/zope/testing/functional.py	Thu May  1 10:07:29 2003
@@ -34,6 +34,7 @@
 from zope.app.traversing import traverse
 from zope.publisher.browser import BrowserRequest
 from zope.publisher.publish import publish
+from zope.exceptions import Forbidden, Unauthorized
 
 
 class ResponseWrapper:
@@ -190,40 +191,60 @@
         publish(request, handle_errors=handle_errors)
         return response
 
-    def checkForBrokenLinks(self, body, path):
+    def checkForBrokenLinks(self, body, path, basic=None):
         """Looks for broken links in a page by trying to traverse relative
         URIs.
         """
         if not body: return
+
         from htmllib import HTMLParser
         from formatter import NullFormatter
-        parser = HTMLParser(NullFormatter())
+        class SimpleHTMLParser(HTMLParser):
+            def __init__(self, fmt, base):
+                HTMLParser.__init__(self, fmt)
+                self.base = base
+            def do_base(self, attrs):
+                self.base = dict(attrs).get('href', self.base)
+
+        parser = SimpleHTMLParser(NullFormatter(), path)
         parser.feed(body)
         parser.close()
-
-        root = self.getRootFolder()
-        base = path
-        if not base.startswith('/'):
-            base = '/' + base
+        base = parser.base
         while not base.endswith('/'):
             base = base[:-1]
+        if base.startswith('http://localhost/'):
+            base = base[len('http://localhost/') - 1:]
+
         errors = []
         for a in parser.anchorlist:
             if a.startswith('http://localhost/'):
                 a = a[len('http://localhost/') - 1:]
             elif a.find(':') != -1:
-                # XXX assume it is "proto:someuri"
+                # Assume it is an external link
                 continue
             elif not a.startswith('/'):
                 a = base + a
             if a.find('#') != -1:
                 a = a[:a.index('#') - 1]
-            rq = self.makeRequest()
+            # XXX what about queries (/path/to/foo?bar=baz&etc)?
+            request = None
             try:
-                rq.traverse(a)
-            except (KeyError, NameError, AttributeError):
-                e = traceback.format_exception_only(*sys.exc_info()[:2])[-1]
-                errors.append((a, e.strip()))
+                try:
+                    request = self.makeRequest(a, basic=basic)
+                    publication = request.publication
+                    request.processInputs()
+                    publication.beforeTraversal(request)
+                    object = publication.getApplication(request)
+                    object = request.traverse(object)
+                    publication.afterTraversal(request, object)
+                except (KeyError, NameError, AttributeError, Unauthorized, Forbidden):
+                    e = traceback.format_exception_only(*sys.exc_info()[:2])[-1]
+                    errors.append((a, e.strip()))
+            finally:
+                # Bad Things(TM) related to garbage collection and special
+                # __del__ methods happen if request.close() is not called here
+                if request:
+                    request.close()
         if errors:
             self.fail("%s contains broken links:\n" % path
                       + "\n".join(["  %s:\t%s" % (a, e) for a, e in errors]))