backport stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 11 Feb 2011 12:17:47 +0100
changeset 6980 8e59c2cdcc99
parent 6975 75a232b2e477 (current diff)
parent 6979 a8fbcf9b6572 (diff)
child 6982 fe74a45204e3
backport stable
devtools/testlib.py
--- a/MANIFEST.in	Thu Feb 10 17:17:54 2011 +0100
+++ b/MANIFEST.in	Fri Feb 11 12:17:47 2011 +0100
@@ -21,7 +21,7 @@
 recursive-include entities/test/data bootstrap_cubes *.py
 recursive-include sobjects/test/data bootstrap_cubes *.py
 recursive-include hooks/test/data bootstrap_cubes *.py
-recursive-include server/test/data bootstrap_cubes *.py source*
+recursive-include server/test/data bootstrap_cubes *.py source* *.conf *.ldif
 recursive-include devtools/test/data bootstrap_cubes *.py *.txt *.js
 recursive-include web/test/data bootstrap_cubes pouet.css *.py
 
--- a/devtools/htmlparser.py	Thu Feb 10 17:17:54 2011 +0100
+++ b/devtools/htmlparser.py	Fri Feb 11 12:17:47 2011 +0100
@@ -127,20 +127,47 @@
         self.input_tags = self.find_tag('input')
         self.title_tags = [self.h1_tags, self.h2_tags, self.h3_tags, self.h4_tags]
 
+    def iterstr(self, tag):
+        if self.default_ns is None:
+            return ".//%s" % tag
+        else:
+            return ".//{%s}%s" % (self.default_ns, tag)
+
     def find_tag(self, tag, gettext=True):
         """return a list which contains text of all "tag" elements """
-        if self.default_ns is None:
-            iterstr = ".//%s" % tag
-        else:
-            iterstr = ".//{%s}%s" % (self.default_ns, tag)
+        iterstr = self.iterstr(tag)
         if not gettext or tag in ('a', 'input'):
-            return [(elt.text, elt.attrib) for elt in self.etree.iterfind(iterstr)]
-        return [u''.join(elt.xpath('.//text()')) for elt in self.etree.iterfind(iterstr)]
+            return [(elt.text, elt.attrib)
+                    for elt in self.etree.iterfind(iterstr)]
+        return [u''.join(elt.xpath('.//text()'))
+                for elt in self.etree.iterfind(iterstr)]
 
     def appears(self, text):
         """returns True if <text> appears in the page"""
         return text in self.raw_text
 
+    def has_tag(self, tag, nboccurs=1, **attrs):
+        """returns True if tag with given attributes appears in the page
+        `nbtimes` (any if None)
+        """
+        for elt in self.etree.iterfind(self.iterstr(tag)):
+            eltattrs  = elt.attrib
+            for attr, value in attrs.iteritems():
+                try:
+                    if eltattrs[attr] != value:
+                        break
+                except KeyError:
+                    break
+            else: # all attributes match
+                if nboccurs is None: # no need to check number of occurences
+                    return True
+                if not nboccurs: # too much occurences
+                    return False
+                nboccurs -= 1
+        if nboccurs == 0: # correct number of occurences
+            return True
+        return False # no matching tag/attrs
+
     def __contains__(self, text):
         return text in self.source
 
--- a/devtools/testlib.py	Thu Feb 10 17:17:54 2011 +0100
+++ b/devtools/testlib.py	Fri Feb 11 12:17:47 2011 +0100
@@ -664,13 +664,6 @@
 
     # content validation #######################################################
 
-    def assertDocTestFile(self, testfile):
-        # doctest returns tuple (failure_count, test_count)
-        result = self.shell().process_script(testfile)
-        if result[0] and result[1]:
-            raise self.failureException("doctest file '%s' failed"
-                                        % testfile)
-
     # validators are used to validate (XML, DTD, whatever) view's content
     # validators availables are :
     #  DTDValidator : validates XML + declared DTD
@@ -755,25 +748,35 @@
             raise AssertionError, msg, tcbk
         return self._check_html(output, view, template)
 
+    def get_validator(self, view=None, content_type=None, output=None):
+        if view is not None:
+            try:
+                return self.vid_validators[view.__regid__]()
+            except KeyError:
+                if content_type is None:
+                    content_type = view.content_type
+        if content_type is None:
+            content_type = 'text/html'
+        if content_type in ('text/html', 'application/xhtml+xml'):
+            if output and output.startswith('<?xml'):
+                default_validator = htmlparser.DTDValidator
+            else:
+                default_validator = htmlparser.HTMLValidator
+        else:
+            default_validator = None
+        validatorclass = self.content_type_validators.get(content_type,
+                                                          default_validator)
+        if validatorclass is None:
+            return
+        return validatorclass()
+
     @nocoverage
     def _check_html(self, output, view, template='main-template'):
         """raises an exception if the HTML is invalid"""
         output = output.strip()
-        try:
-            validatorclass = self.vid_validators[view.__regid__]
-        except KeyError:
-            if view.content_type in ('text/html', 'application/xhtml+xml'):
-                if output.startswith('<?xml'):
-                    default_validator = htmlparser.DTDValidator
-                else:
-                    default_validator = htmlparser.HTMLValidator
-            else:
-                default_validator = None
-            validatorclass = self.content_type_validators.get(view.content_type,
-                                                              default_validator)
-        if validatorclass is None:
+        validator = self.get_validator(view, output=output)
+        if validator is None:
             return
-        validator = validatorclass()
         if isinstance(validator, htmlparser.DTDValidator):
             # XXX remove <canvas> used in progress widget, unknown in html dtd
             output = re.sub('<canvas.*?></canvas>', '', output)
@@ -816,6 +819,13 @@
                     msg += u'\nfor content:\n%s' % content
             raise AssertionError, msg, tcbk
 
+    def assertDocTestFile(self, testfile):
+        # doctest returns tuple (failure_count, test_count)
+        result = self.shell().process_script(testfile)
+        if result[0] and result[1]:
+            raise self.failureException("doctest file '%s' failed"
+                                        % testfile)
+
     # deprecated ###############################################################
 
     @deprecated('[3.8] use self.execute(...).get_entity(0, 0)')