import re
import logging
import asyncio
+import xml.etree.ElementTree as ET
from urllib.parse import urlencode
from utils import run_script
def send_api_query(endpoint, params, fmt, context):
- if fmt is not None and fmt.strip() != 'debug':
- params['format'] = fmt.strip()
+ if fmt is not None:
+ if fmt.strip() == 'debug':
+ params['debug'] = '1'
+ else:
+ params['format'] = fmt.strip()
+
if context.table:
if context.table.headings[0] == 'param':
for line in context.table:
LOG.debug("Environment:" + json.dumps(env, sort_keys=True, indent=2))
if hasattr(context, 'http_headers'):
- env.update(context.http_headers)
+ for k, v in context.http_headers.items():
+ env['HTTP_' + k.upper().replace('-', '_')] = v
cmd = ['/usr/bin/env', 'php-cgi', '-f']
if context.nominatim.code_coverage_path:
context.http_headers = {}
for h in context.table.headings:
- envvar = 'HTTP_' + h.upper().replace('-', '_')
- context.http_headers[envvar] = context.table[0][h]
+ context.http_headers[h] = context.table[0][h]
@when(u'sending (?P<fmt>\S+ )?search query "(?P<query>.*)"(?P<addr> with address)?')
params['q'] = query
if addr is not None:
params['addressdetails'] = '1'
- if fmt and fmt.strip() == 'debug':
- params['debug'] = '1'
outp, status = send_api_query('search', params, fmt, context)
context.response = SearchResponse(outp, fmt or 'json', status)
-@when(u'sending (?P<fmt>\S+ )?reverse coordinates (?P<lat>.+)?,(?P<lon>.+)?')
-def website_reverse_request(context, fmt, lat, lon):
+
+@when('sending v1/reverse at (?P<lat>[\d.-]*),(?P<lon>[\d.-]*)(?: with format (?P<fmt>.+))?')
+def api_endpoint_v1_reverse(context, lat, lon, fmt):
params = {}
if lat is not None:
params['lat'] = lat
if lon is not None:
params['lon'] = lon
- if fmt and fmt.strip() == 'debug':
- params['debug'] = '1'
+ if fmt is None:
+ fmt = 'jsonv2'
+ elif fmt == "''":
+ fmt = None
outp, status = send_api_query('reverse', params, fmt, context)
-
context.response = ReverseResponse(outp, fmt or 'xml', status)
-@when(u'sending (?P<fmt>\S+ )?reverse point (?P<nodeid>.+)')
-def website_reverse_request(context, fmt, nodeid):
+
+@when('sending v1/reverse N(?P<nodeid>\d+)(?: with format (?P<fmt>.+))?')
+def api_endpoint_v1_reverse_from_node(context, nodeid, fmt):
params = {}
- if fmt and fmt.strip() == 'debug':
- params['debug'] = '1'
params['lon'], params['lat'] = (f'{c:f}' for c in context.osm.grid_node(int(nodeid)))
-
outp, status = send_api_query('reverse', params, fmt, context)
-
context.response = ReverseResponse(outp, fmt or 'xml', status)
-
@when(u'sending (?P<fmt>\S+ )?details query for (?P<query>.*)')
def website_details_request(context, fmt, query):
params = {}
@step(u'(?P<operator>less than|more than|exactly|at least|at most) (?P<number>\d+) results? (?:is|are) returned')
def validate_result_number(context, operator, number):
- assert context.response.errorcode == 200
+ context.execute_steps("Then a HTTP 200 is returned")
numres = len(context.response.result)
assert compare(operator, numres, int(number)), \
f"Bad number of results: expected {operator} {number}, got {numres}."
@then(u'a HTTP (?P<status>\d+) is returned')
def check_http_return_status(context, status):
assert context.response.errorcode == int(status), \
- f"Return HTTP status is {context.response.errorcode}."
+ f"Return HTTP status is {context.response.errorcode}."\
+ f" Full response:\n{context.response.page}"
@then(u'the page contents equals "(?P<text>.+)"')
def check_page_content_equals(context, text):
@then(u'the result is valid (?P<fmt>\w+)')
def step_impl(context, fmt):
context.execute_steps("Then a HTTP 200 is returned")
- assert context.response.format == fmt
+ if fmt.strip() == 'html':
+ try:
+ tree = ET.fromstring(context.response.page)
+ except Exception as ex:
+ assert False, f"Could not parse page:\n{context.response.page}"
+
+ assert tree.tag == 'html'
+ body = tree.find('./body')
+ assert body is not None
+ assert body.find('.//script') is None
+ else:
+ assert context.response.format == fmt
+
@then(u'a (?P<fmt>\w+) user error is returned')
def check_page_error(context, fmt):
@then(u'result header contains')
def check_header_attr(context):
+ context.execute_steps("Then a HTTP 200 is returned")
for line in context.table:
+ assert line['attr'] in context.response.header, \
+ f"Field '{line['attr']}' missing in header. Full header:\n{context.response.header}"
value = context.response.header[line['attr']]
assert re.fullmatch(line['value'], value) is not None, \
f"Attribute '{line['attr']}': expected: '{line['value']}', got '{value}'"