]> git.openstreetmap.org Git - nominatim.git/blob - test/python/api/test_api_search.py
work around strange query planning behaviour
[nominatim.git] / test / python / api / test_api_search.py
1 # SPDX-License-Identifier: GPL-3.0-or-later
2 #
3 # This file is part of Nominatim. (https://nominatim.org)
4 #
5 # Copyright (C) 2023 by the Nominatim developer community.
6 # For a full list of authors see the git log.
7 """
8 Tests for search API calls.
9
10 These tests make sure that all Python code is correct and executable.
11 Functional tests can be found in the BDD test suite.
12 """
13 import json
14
15 import pytest
16
17 import sqlalchemy as sa
18
19 import nominatim.api as napi
20 import nominatim.api.logging as loglib
21
22 API_OPTIONS = {'search'}
23
24 @pytest.fixture(autouse=True)
25 def setup_icu_tokenizer(apiobj):
26     """ Setup the properties needed for using the ICU tokenizer.
27     """
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/'; 'ä' > 'ä '"},
32                     ])
33
34
35 def test_search_no_content(apiobj, frontend):
36     apiobj.add_word_table([])
37
38     api = frontend(apiobj, options=API_OPTIONS)
39     assert api.search('foo') == []
40
41
42 def test_search_simple_word(apiobj, frontend):
43     apiobj.add_word_table([(55, 'test', 'W', 'test', None),
44                            (2, 'test', 'w', 'test', None)])
45
46     apiobj.add_placex(place_id=444, class_='place', type='village',
47                       centroid=(1.3, 0.7))
48     apiobj.add_search_name(444, names=[2, 55])
49
50     api = frontend(apiobj, options=API_OPTIONS)
51     results = api.search('TEST')
52
53     assert [r.place_id for r in results] == [444]
54
55
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)])
60
61     apiobj.add_placex(place_id=444, class_='place', type='village',
62                       centroid=(1.3, 0.7))
63     apiobj.add_search_name(444, names=[2, 55])
64
65     api = frontend(apiobj, options=API_OPTIONS)
66     loglib.set_log_output(logtype)
67     results = api.search('TEST')
68
69     assert loglib.get_and_disable()
70
71
72 def test_address_no_content(apiobj, frontend):
73     apiobj.add_word_table([])
74
75     api = frontend(apiobj, options=API_OPTIONS)
76     assert api.search_address(amenity='hotel',
77                               street='Main St 34',
78                               city='Happyville',
79                               county='Wideland',
80                               state='Praerie',
81                               postalcode='55648',
82                               country='xx') == []
83
84
85 @pytest.mark.parametrize('atype,address,search', [('street', 26, 26),
86                                                   ('city', 16, 18),
87                                                   ('county', 12, 12),
88                                                   ('state', 8, 8)])
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)])
92
93     apiobj.add_placex(place_id=444,
94                       rank_address=address, rank_search=search,
95                       centroid=(1.3, 0.7))
96     apiobj.add_search_name(444, names=[2, 55], address_rank=address, search_rank=search)
97
98     api = frontend(apiobj, options=API_OPTIONS)
99     results = api.search_address(**{atype: 'TEST'})
100
101     assert [r.place_id for r in results] == [444]
102
103
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'})
108
109     api = frontend(apiobj, options=API_OPTIONS)
110     assert len(api.search_address(country='ro')) == 1
111
112
113 def test_category_no_categories(apiobj, frontend):
114     apiobj.add_word_table([])
115
116     api = frontend(apiobj, options=API_OPTIONS)
117     assert api.search_category([], near_query='Berlin') == []
118
119
120 def test_category_no_content(apiobj, frontend):
121     apiobj.add_word_table([])
122
123     api = frontend(apiobj, options=API_OPTIONS)
124     assert api.search_category([('amenity', 'restaurant')]) == []
125
126
127 def test_category_simple_restaurant(apiobj, frontend):
128     apiobj.add_word_table([])
129
130     apiobj.add_placex(place_id=444, class_='amenity', type='restaurant',
131                       centroid=(1.3, 0.7))
132     apiobj.add_search_name(444, names=[2, 55], address_rank=16, search_rank=18)
133
134     api = frontend(apiobj, options=API_OPTIONS)
135     results = api.search_category([('amenity', 'restaurant')],
136                                   near=(1.3, 0.701), near_radius=0.015)
137
138     assert [r.place_id for r in results] == [444]
139
140
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)])
144
145     apiobj.add_placex(place_id=444, class_='place', type='village',
146                       rank_address=16, rank_search=18,
147                       centroid=(1.3, 0.7))
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))
151
152     api = frontend(apiobj, options=API_OPTIONS)
153     results = api.search_category([('amenity', 'restaurant')], near_query='TEST')
154
155     assert [r.place_id for r in results] == [95]