X-Git-Url: https://git.openstreetmap.org./nominatim.git/blobdiff_plain/c3788d765ed4e7ddf00794085af757714bc102cf..d17ec56e5462dd00cefcbd9537195f9b67ee11eb:/test/bdd/steps/http_responses.py diff --git a/test/bdd/steps/http_responses.py b/test/bdd/steps/http_responses.py index fa6ab7fb..dcce1b58 100644 --- a/test/bdd/steps/http_responses.py +++ b/test/bdd/steps/http_responses.py @@ -2,12 +2,11 @@ # # This file is part of Nominatim. (https://nominatim.org) # -# Copyright (C) 2022 by the Nominatim developer community. +# Copyright (C) 2023 by the Nominatim developer community. # For a full list of authors see the git log. """ Classes wrapping HTTP responses from the Nominatim API. """ -from collections import OrderedDict import re import json import xml.etree.ElementTree as ET @@ -70,15 +69,16 @@ class GenericResponse: else: code = m.group(2) self.header['json_func'] = m.group(1) - self.result = json.JSONDecoder(object_pairs_hook=OrderedDict).decode(code) - if isinstance(self.result, OrderedDict): - self.result = [self.result] + self.result = json.JSONDecoder().decode(code) + if isinstance(self.result, dict): + if 'error' in self.result: + self.result = [] + else: + self.result = [self.result] def _parse_geojson(self): self._parse_json() - if 'error' in self.result[0]: - self.result = [] - else: + if self.result: self.result = list(map(_geojson_result_to_json_result, self.result[0]['features'])) def _parse_geocodejson(self): @@ -101,10 +101,33 @@ class GenericResponse: elif value.startswith("^"): assert re.fullmatch(value, self.result[idx][field]), \ BadRowValueAssert(self, idx, field, value) + elif isinstance(self.result[idx][field], dict): + assert self.result[idx][field] == eval('{' + value + '}'), \ + BadRowValueAssert(self, idx, field, value) else: assert str(self.result[idx][field]) == str(value), \ BadRowValueAssert(self, idx, field, value) + + 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. @@ -128,7 +151,7 @@ class GenericResponse: "\nBad value for row {} field '{}' in address. Expected: {}, got: {}.\nFull address: {}"""\ .format(idx, field, value, address[field], json.dumps(address, indent=4)) - def match_row(self, row): + def match_row(self, row, context=None): """ Match the result fields against the given behave table row. """ if 'ID' in row.headings: @@ -151,9 +174,16 @@ class GenericResponse: assert self.result[i]['osm_type'] in (OSM_TYPE[value[0]], value[0]), \ BadRowValueAssert(self, i, 'osm_type', value) elif name == 'centroid': - lon, lat = value.split(' ') + if ' ' in value: + lon, lat = value.split(' ') + elif context is not None: + lon, lat = context.osm.grid_node(int(value)) + else: + raise RuntimeError("Context needed when using grid coordinates") self.assert_field(i, 'lat', float(lat)) self.assert_field(i, 'lon', float(lon)) + elif '+' in name: + self.assert_subfield(i, name.split('+'), value) else: self.assert_field(i, name, value)