]> git.openstreetmap.org Git - nominatim.git/blobdiff - test/bdd/steps/http_responses.py
bdd: more format checks for reverse XML
[nominatim.git] / test / bdd / steps / http_responses.py
index a3493b975790441881f8b76115d7567edd9535dd..0a3bd3045762ce2c64ffc767d5f24974d6b7d497 100644 (file)
@@ -87,25 +87,6 @@ class GenericResponse:
                 r |= r.pop('geocoding')
 
 
-    def assert_subfield(self, idx, path, value):
-        assert path
-
-        field = self.result[idx]
-        for p in path:
-            assert isinstance(field, dict)
-            assert p in field
-            field = field[p]
-
-        if isinstance(value, float):
-            assert Almost(value) == float(field)
-        elif value.startswith("^"):
-            assert re.fullmatch(value, field)
-        elif isinstance(field, dict):
-            assert field, eval('{' + value + '}')
-        else:
-            assert str(field) == str(value)
-
-
     def assert_address_field(self, idx, field, value):
         """ Check that result rows`idx` has a field `field` with value `value`
             in its address. If idx is None, then all results are checked.
@@ -122,7 +103,7 @@ class GenericResponse:
             self.check_row_field(idx, field, value, base=address)
 
 
-    def match_row(self, row, context=None):
+    def match_row(self, row, context=None, field=None):
         """ Match the result fields against the given behave table row.
         """
         if 'ID' in row.headings:
@@ -131,12 +112,20 @@ class GenericResponse:
             todo = range(len(self.result))
 
         for i in todo:
+            subdict = self.result[i]
+            if field is not None:
+                for key in field.split('.'):
+                    self.check_row(i, key in subdict, f"Missing subfield {key}")
+                    subdict = subdict[key]
+                    self.check_row(i, isinstance(subdict, dict),
+                                   f"Subfield {key} not a dict")
+
             for name, value in zip(row.headings, row.cells):
                 if name == 'ID':
                     pass
                 elif name == 'osm':
-                    self.check_row_field(i, 'osm_type', OsmType(value[0]))
-                    self.check_row_field(i, 'osm_id', Field(value[1:]))
+                    self.check_row_field(i, 'osm_type', OsmType(value[0]), base=subdict)
+                    self.check_row_field(i, 'osm_id', Field(value[1:]), base=subdict)
                 elif name == 'centroid':
                     if ' ' in value:
                         lon, lat = value.split(' ')
@@ -144,16 +133,10 @@ class GenericResponse:
                         lon, lat = context.osm.grid_node(int(value))
                     else:
                         raise RuntimeError("Context needed when using grid coordinates")
-                    self.check_row_field(i, 'lat', Field(float(lat)))
-                    self.check_row_field(i, 'lon', Field(float(lon)))
-                elif '+' in name:
-                    self.assert_subfield(i, name.split('+'), value)
+                    self.check_row_field(i, 'lat', Field(float(lat)), base=subdict)
+                    self.check_row_field(i, 'lon', Field(float(lon)), base=subdict)
                 else:
-                    self.check_row_field(i, name, Field(value))
-
-
-    def property_list(self, prop):
-        return [x[prop] for x in self.result]
+                    self.check_row_field(i, name, Field(value), base=subdict)
 
 
     def check_row(self, idx, check, msg):
@@ -237,24 +220,33 @@ class ReverseResponse(GenericResponse):
             if child.tag == 'result':
                 assert not self.result, "More than one result in reverse result"
                 self.result.append(dict(child.attrib))
+                check_for_attributes(self.result[0], 'display_name', 'absent')
+                self.result[0]['display_name'] = child.text
             elif child.tag == 'addressparts':
+                assert 'address' not in self.result[0], "More than one address in result"
                 address = {}
                 for sub in child:
+                    assert len(sub) == 0, f"Address element '{sub.tag}' has subelements"
                     address[sub.tag] = sub.text
                 self.result[0]['address'] = address
             elif child.tag == 'extratags':
+                assert 'extratags' not in self.result[0], "More than one extratags in result"
                 self.result[0]['extratags'] = {}
                 for tag in child:
+                    assert len(tag) == 0, f"Extratags element '{tag.attrib['key']}' has subelements"
                     self.result[0]['extratags'][tag.attrib['key']] = tag.attrib['value']
             elif child.tag == 'namedetails':
+                assert 'namedetails' not in self.result[0], "More than one namedetails in result"
                 self.result[0]['namedetails'] = {}
                 for tag in child:
+                    assert len(tag) == 0, f"Namedetails element '{tag.attrib['desc']}' has subelements"
                     self.result[0]['namedetails'][tag.attrib['desc']] = tag.text
             elif child.tag == 'geokml':
-                self.result[0][child.tag] = True
+                assert 'geokml' not in self.result[0], "More than one geokml in result"
+                self.result[0]['geokml'] = ET.tostring(child, encoding='unicode')
             else:
                 assert child.tag == 'error', \
-                       "Unknown XML tag {} on page: {}".format(child.tag, self.page)
+                       f"Unknown XML tag {child.tag} on page: {self.page}"
 
 
 class StatusResponse(GenericResponse):