Skip to content

Commit

Permalink
tests for facility with no or duplicate search parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
hiddewie committed Jul 21, 2024
1 parent 0b0e8e9 commit fb2d76f
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 44 deletions.
58 changes: 21 additions & 37 deletions api/openrailwaymap_api/facility_api.py
Original file line number Diff line number Diff line change
@@ -1,71 +1,55 @@
from fastapi import HTTPException
from starlette.status import HTTP_400_BAD_REQUEST

# from api import MAX_LIMIT
from starlette.status import HTTP_400_BAD_REQUEST, HTTP_422_UNPROCESSABLE_ENTITY

QUERY_PARAMETERS = ['q', 'name', 'ref', 'uic_ref']

class FacilityAPI:
def __init__(self, database):
self.database = database

def eliminate_duplicates(self, data):
def eliminate_duplicates(self, data, limit):
data.sort(key=lambda k: k['osm_id'])
i = 1
while i < len(data):
if data[i]['osm_id'] == data[i - 1]['osm_id']:
data.pop(i)
i += 1
if len(data) > self.limit:
return data[:self.limit]
if len(data) > limit:
return data[:limit]
return data

async def __call__(self, *, q, name, ref, uic_ref, limit):
# Validate search arguments
search_args_count = 0
for search_arg in [q, name, ref, uic_ref]:
if search_arg:
search_args_count += 1
search_args_count = sum(1 for search_arg in [q, name, ref, uic_ref] if search_arg)

if search_args_count > 1:
args = ', '.join(QUERY_PARAMETERS)
raise HTTPException(
HTTP_400_BAD_REQUEST,
HTTP_422_UNPROCESSABLE_ENTITY,
{'type': 'multiple_query_args', 'error': 'More than one argument with a search term provided.', 'detail': f'Provide only one of the following query parameters: {args}'}
)
elif search_args_count == 0:
args = ', '.join(QUERY_PARAMETERS)
raise HTTPException(
HTTP_400_BAD_REQUEST,
HTTP_422_UNPROCESSABLE_ENTITY,
{'type': 'no_query_arg', 'error': 'No argument with a search term provided.', 'detail': f'Provide one of the following query parameters: {args}'}
)
if limit is not None:
try:
self.limit = int(limit)
except ValueError:
raise HTTPException(
HTTP_400_BAD_REQUEST,
{'type': 'limit_not_integer', 'error': 'Invalid parameter value provided for parameter "limit".', 'detail': 'The provided limit cannot be parsed as an integer value.'}
)
# if self.limit > MAX_LIMIT:
# raise HTTPException(
# HTTP_400_BAD_REQUEST,
# {'type': 'limit_too_high', 'error': 'Invalid parameter value provided for parameter "limit".', 'detail': 'Limit is too high. Please set up your own instance to query everything.'}
# )

if name:
return await self.search_by_name(name)
return await self.search_by_name(name, limit)
if ref:
return await self.search_by_ref(ref)
return await self.search_by_ref(ref, limit)
if uic_ref:
return await self.search_by_uic_ref(uic_ref)
return await self.search_by_uic_ref(uic_ref, limit)
if q:
return self.eliminate_duplicates((await self.search_by_name(q)) + (await self.search_by_ref(q)) + (await self.search_by_uic_ref(q)))
return self.eliminate_duplicates((await self.search_by_name(q, limit)) + (await self.search_by_ref(q, limit)) + (await self.search_by_uic_ref(q, limit)), limit)

def query_has_no_wildcards(self, q):
if '%' in q or '_' in q:
return False
return True

async def search_by_name(self, q):
async def search_by_name(self, q, limit):
if not self.query_has_no_wildcards(q):
raise HTTPException(
HTTP_400_BAD_REQUEST,
Expand Down Expand Up @@ -94,11 +78,11 @@ async def search_by_name(self, q):
statement = await connection.prepare(sql_query)
async with connection.transaction():
data = []
async for record in statement.cursor(q, self.limit):
async for record in statement.cursor(q, limit):
data.append(dict(record))
return data

async def _search_by_ref(self, search_key, ref):
async def _search_by_ref(self, search_key, ref, limit):
# We do not sort the result, although we use DISTINCT ON because osm_id is sufficient to sort out duplicates.
fields = self.sql_select_fieldlist()
sql_query = f"""SELECT DISTINCT ON (osm_id)
Expand All @@ -111,15 +95,15 @@ async def _search_by_ref(self, search_key, ref):
statement = await connection.prepare(sql_query)
async with connection.transaction():
data = []
async for record in statement.cursor(ref, self.limit):
async for record in statement.cursor(ref, limit):
data.append(dict(record))
return data

async def search_by_ref(self, ref):
return await self._search_by_ref("railway_ref", ref)
async def search_by_ref(self, ref, limit):
return await self._search_by_ref("railway_ref", ref, limit)

async def search_by_uic_ref(self, ref):
return await self._search_by_ref("uic_ref", ref)
async def search_by_uic_ref(self, ref, limit):
return await self._search_by_ref("uic_ref", ref, limit)

def sql_select_fieldlist(self):
return "osm_id, name, railway, railway_ref"
8 changes: 1 addition & 7 deletions api/openrailwaymap_api/milestone_api.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
class MilestoneAPI:
def __init__(self, database):
self.database = database
self.route_ref = None
self.position = None
self.data = []
self.status_code = 200
self.limit = 2

async def __call__(self, *, ref, position, limit):
self.data = await self.get_milestones(position, ref, limit)
return self.data
return await self.get_milestones(position, ref, limit)

async def get_milestones(self, position, route_ref, limit):
# We do not sort the result, although we use DISTINCT ON because osm_id is sufficient to sort out duplicates.
Expand Down
58 changes: 58 additions & 0 deletions api/tests/api.hurl
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,64 @@ jsonpath "$" count == 2
jsonpath "$[0].name" == "Ostkreuz"
jsonpath "$[1].name" == "Ostkreuz (Ringbahn)"

# Facility request missing required parameter
GET {{base_url}}/facility
HTTP 422
[Asserts]
jsonpath "$.detail.error" == "No argument with a search term provided."
jsonpath "$.detail.detail" == "Provide one of the following query parameters: q, name, ref, uic_ref"

# Facility request duplicated search parameters (1)
GET {{base_url}}/facility
[QueryStringParams]
q: 8089028
ref: test
HTTP 422
[Asserts]
jsonpath "$.detail.error" == "More than one argument with a search term provided."
jsonpath "$.detail.detail" == "Provide only one of the following query parameters: q, name, ref, uic_ref"

# Facility request duplicated search parameters (2)
GET {{base_url}}/facility
[QueryStringParams]
q: 8089028
uic_ref: test
HTTP 422
[Asserts]
jsonpath "$.detail.error" == "More than one argument with a search term provided."
jsonpath "$.detail.detail" == "Provide only one of the following query parameters: q, name, ref, uic_ref"

# Facility request duplicated search parameters (3)
GET {{base_url}}/facility
[QueryStringParams]
name: 8089028
uic_ref: test
HTTP 422
[Asserts]
jsonpath "$.detail.error" == "More than one argument with a search term provided."
jsonpath "$.detail.detail" == "Provide only one of the following query parameters: q, name, ref, uic_ref"

# Facility request duplicated search parameters (4)
GET {{base_url}}/facility
[QueryStringParams]
q: test
name: test
ref: test
uic_ref: test
HTTP 422
[Asserts]
jsonpath "$.detail.error" == "More than one argument with a search term provided."
jsonpath "$.detail.detail" == "Provide only one of the following query parameters: q, name, ref, uic_ref"

# Facility request limit is not numeric
GET {{base_url}}/facility
[QueryStringParams]
limit: blabla
HTTP 422
[Asserts]
jsonpath "$.detail" count == 1
jsonpath "$.detail[0].msg" == "Input should be a valid integer, unable to parse string as an integer"

# Milestone request for line 6020 milestone 22.7
GET {{base_url}}/milestone
[QueryStringParams]
Expand Down

0 comments on commit fb2d76f

Please sign in to comment.