1 # SPDX-License-Identifier: GPL-3.0-or-later
 
   3 # This file is part of Nominatim. (https://nominatim.org)
 
   5 # Copyright (C) 2023 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 @pytest.fixture(autouse=True)
 
  23 def setup_icu_tokenizer(apiobj):
 
  24     """ Setup the propoerties needed for using the ICU tokenizer.
 
  26     apiobj.add_data('properties',
 
  27                     [{'property': 'tokenizer', 'value': 'icu'},
 
  28                      {'property': 'tokenizer_import_normalisation', 'value': ':: lower();'},
 
  29                      {'property': 'tokenizer_import_transliteration', 'value': "'1' > '/1/'; 'ä' > 'ä '"},
 
  33 def test_search_no_content(apiobj, table_factory):
 
  35                   definition='word_id INT, word_token TEXT, type TEXT, word TEXT, info JSONB')
 
  37     assert apiobj.api.search('foo') == []
 
  40 def test_search_simple_word(apiobj, table_factory):
 
  42                   definition='word_id INT, word_token TEXT, type TEXT, word TEXT, info JSONB',
 
  43                   content=[(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     results = apiobj.api.search('TEST')
 
  52     assert [r.place_id for r in results] == [444]
 
  55 @pytest.mark.parametrize('logtype', ['text', 'html'])
 
  56 def test_search_with_debug(apiobj, table_factory, logtype):
 
  58                   definition='word_id INT, word_token TEXT, type TEXT, word TEXT, info JSONB',
 
  59                   content=[(55, 'test', 'W', 'test', None),
 
  60                            (2, 'test', 'w', 'test', None)])
 
  62     apiobj.add_placex(place_id=444, class_='place', type='village',
 
  64     apiobj.add_search_name(444, names=[2, 55])
 
  66     loglib.set_log_output(logtype)
 
  67     results = apiobj.api.search('TEST')
 
  69     assert loglib.get_and_disable()
 
  72 def test_address_no_content(apiobj, table_factory):
 
  74                   definition='word_id INT, word_token TEXT, type TEXT, word TEXT, info JSONB')
 
  76     assert apiobj.api.search_address(amenity='hotel',
 
  85 @pytest.mark.parametrize('atype,address,search', [('street', 26, 26),
 
  89 def test_address_simple_places(apiobj, table_factory, atype, address, search):
 
  91                   definition='word_id INT, word_token TEXT, type TEXT, word TEXT, info JSONB',
 
  92                   content=[(55, 'test', 'W', 'test', None),
 
  93                            (2, 'test', 'w', 'test', None)])
 
  95     apiobj.add_placex(place_id=444,
 
  96                       rank_address=address, rank_search=search,
 
  98     apiobj.add_search_name(444, names=[2, 55], address_rank=address, search_rank=search)
 
 100     results = apiobj.api.search_address(**{atype: 'TEST'})
 
 102     assert [r.place_id for r in results] == [444]
 
 105 def test_address_country(apiobj, table_factory):
 
 106     table_factory('word',
 
 107                   definition='word_id INT, word_token TEXT, type TEXT, word TEXT, info JSONB',
 
 108                   content=[(None, 'ro', 'C', 'ro', None)])
 
 109     apiobj.add_country('ro', 'POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')
 
 110     apiobj.add_country_name('ro', {'name': 'România'})
 
 112     assert len(apiobj.api.search_address(country='ro')) == 1
 
 115 def test_category_no_categories(apiobj, table_factory):
 
 116     table_factory('word',
 
 117                   definition='word_id INT, word_token TEXT, type TEXT, word TEXT, info JSONB')
 
 119     assert apiobj.api.search_category([], near_query='Berlin') == []
 
 122 def test_category_no_content(apiobj, table_factory):
 
 123     table_factory('word',
 
 124                   definition='word_id INT, word_token TEXT, type TEXT, word TEXT, info JSONB')
 
 126     assert apiobj.api.search_category([('amenity', 'restaurant')]) == []
 
 129 def test_category_simple_restaurant(apiobj, table_factory):
 
 130     table_factory('word',
 
 131                   definition='word_id INT, word_token TEXT, type TEXT, word TEXT, info JSONB')
 
 133     apiobj.add_placex(place_id=444, class_='amenity', type='restaurant',
 
 135     apiobj.add_search_name(444, names=[2, 55], address_rank=16, search_rank=18)
 
 137     results = apiobj.api.search_category([('amenity', 'restaurant')],
 
 138                                          near=(1.3, 0.701), near_radius=0.015)
 
 140     assert [r.place_id for r in results] == [444]
 
 143 def test_category_with_search_phrase(apiobj, table_factory):
 
 144     table_factory('word',
 
 145                   definition='word_id INT, word_token TEXT, type TEXT, word TEXT, info JSONB',
 
 146                   content=[(55, 'test', 'W', 'test', None),
 
 147                            (2, 'test', 'w', 'test', None)])
 
 149     apiobj.add_placex(place_id=444, class_='place', type='village',
 
 150                       rank_address=16, rank_search=18,
 
 152     apiobj.add_search_name(444, names=[2, 55], address_rank=16, search_rank=18)
 
 153     apiobj.add_placex(place_id=95, class_='amenity', type='restaurant',
 
 154                       centroid=(1.3, 0.7003))
 
 156     results = apiobj.api.search_category([('amenity', 'restaurant')],
 
 159     assert [r.place_id for r in results] == [95]