1 # SPDX-License-Identifier: GPL-3.0-or-later
 
   3 # This file is part of Nominatim. (https://nominatim.org)
 
   5 # Copyright (C) 2024 by the Nominatim developer community.
 
   6 # For a full list of authors see the git log.
 
   8 Tests for search API calls.
 
  10 These tests make sure that all Python code is correct and executable.
 
  11 Functional tests can be found in the BDD test suite.
 
  17 import sqlalchemy as sa
 
  19 import nominatim_api as napi
 
  20 import nominatim_api.logging as loglib
 
  22 API_OPTIONS = {'search'}
 
  24 @pytest.fixture(autouse=True)
 
  25 def setup_icu_tokenizer(apiobj):
 
  26     """ Setup the properties needed for using the ICU tokenizer.
 
  28     apiobj.add_data('properties',
 
  29                     [{'property': 'tokenizer', 'value': 'icu'},
 
  30                      {'property': 'tokenizer_import_normalisation', 'value': ':: lower();'},
 
  31                      {'property': 'tokenizer_import_transliteration', 'value': "'1' > '/1/'; 'ä' > 'ä '"},
 
  35 def test_search_no_content(apiobj, frontend):
 
  36     apiobj.add_word_table([])
 
  38     api = frontend(apiobj, options=API_OPTIONS)
 
  39     assert api.search('foo') == []
 
  42 def test_search_simple_word(apiobj, frontend):
 
  43     apiobj.add_word_table([(55, 'test', 'W', 'test', None),
 
  44                            (2, 'test', 'w', 'test', None)])
 
  46     apiobj.add_placex(place_id=444, class_='place', type='village',
 
  48     apiobj.add_search_name(444, names=[2, 55])
 
  50     api = frontend(apiobj, options=API_OPTIONS)
 
  51     results = api.search('TEST')
 
  53     assert [r.place_id for r in results] == [444]
 
  56 @pytest.mark.parametrize('logtype', ['text', 'html'])
 
  57 def test_search_with_debug(apiobj, frontend, logtype):
 
  58     apiobj.add_word_table([(55, 'test', 'W', 'test', None),
 
  59                            (2, 'test', 'w', 'test', None)])
 
  61     apiobj.add_placex(place_id=444, class_='place', type='village',
 
  63     apiobj.add_search_name(444, names=[2, 55])
 
  65     api = frontend(apiobj, options=API_OPTIONS)
 
  66     loglib.set_log_output(logtype)
 
  67     results = api.search('TEST')
 
  69     assert loglib.get_and_disable()
 
  72 def test_address_no_content(apiobj, frontend):
 
  73     apiobj.add_word_table([])
 
  75     api = frontend(apiobj, options=API_OPTIONS)
 
  76     assert api.search_address(amenity='hotel',
 
  85 @pytest.mark.parametrize('atype,address,search', [('street', 26, 26),
 
  89 def test_address_simple_places(apiobj, frontend, atype, address, search):
 
  90     apiobj.add_word_table([(55, 'test', 'W', 'test', None),
 
  91                            (2, 'test', 'w', 'test', None)])
 
  93     apiobj.add_placex(place_id=444,
 
  94                       rank_address=address, rank_search=search,
 
  96     apiobj.add_search_name(444, names=[2, 55], address_rank=address, search_rank=search)
 
  98     api = frontend(apiobj, options=API_OPTIONS)
 
  99     results = api.search_address(**{atype: 'TEST'})
 
 101     assert [r.place_id for r in results] == [444]
 
 104 def test_address_country(apiobj, frontend):
 
 105     apiobj.add_word_table([(None, 'ro', 'C', 'ro', None)])
 
 106     apiobj.add_country('ro', 'POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')
 
 107     apiobj.add_country_name('ro', {'name': 'România'})
 
 109     api = frontend(apiobj, options=API_OPTIONS)
 
 110     assert len(api.search_address(country='ro')) == 1
 
 113 def test_category_no_categories(apiobj, frontend):
 
 114     apiobj.add_word_table([])
 
 116     api = frontend(apiobj, options=API_OPTIONS)
 
 117     assert api.search_category([], near_query='Berlin') == []
 
 120 def test_category_no_content(apiobj, frontend):
 
 121     apiobj.add_word_table([])
 
 123     api = frontend(apiobj, options=API_OPTIONS)
 
 124     assert api.search_category([('amenity', 'restaurant')]) == []
 
 127 def test_category_simple_restaurant(apiobj, frontend):
 
 128     apiobj.add_word_table([])
 
 130     apiobj.add_placex(place_id=444, class_='amenity', type='restaurant',
 
 132     apiobj.add_search_name(444, names=[2, 55], address_rank=16, search_rank=18)
 
 134     api = frontend(apiobj, options=API_OPTIONS)
 
 135     results = api.search_category([('amenity', 'restaurant')],
 
 136                                   near=(1.3, 0.701), near_radius=0.015)
 
 138     assert [r.place_id for r in results] == [444]
 
 141 def test_category_with_search_phrase(apiobj, frontend):
 
 142     apiobj.add_word_table([(55, 'test', 'W', 'test', None),
 
 143                            (2, 'test', 'w', 'test', None)])
 
 145     apiobj.add_placex(place_id=444, class_='place', type='village',
 
 146                       rank_address=16, rank_search=18,
 
 148     apiobj.add_search_name(444, names=[2, 55], address_rank=16, search_rank=18)
 
 149     apiobj.add_placex(place_id=95, class_='amenity', type='restaurant',
 
 150                       centroid=(1.3, 0.7003))
 
 152     api = frontend(apiobj, options=API_OPTIONS)
 
 153     results = api.search_category([('amenity', 'restaurant')], near_query='TEST')
 
 155     assert [r.place_id for r in results] == [95]