]> git.openstreetmap.org Git - nominatim.git/blob - test/python/api/test_result_formatting_v1.py
properly encode special HTML characters in debug mode
[nominatim.git] / test / python / api / test_result_formatting_v1.py
1 # SPDX-License-Identifier: GPL-2.0-only
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 formatting results for the V1 API.
9 """
10 import datetime as dt
11 import json
12
13 import pytest
14
15 import nominatim.api.v1 as api_impl
16 import nominatim.api as napi
17 from nominatim.version import NOMINATIM_VERSION
18
19 STATUS_FORMATS = {'text', 'json'}
20
21 # StatusResult
22
23 def test_status_format_list():
24     assert set(api_impl.list_formats(napi.StatusResult)) == STATUS_FORMATS
25
26
27 @pytest.mark.parametrize('fmt', list(STATUS_FORMATS))
28 def test_status_supported(fmt):
29     assert api_impl.supports_format(napi.StatusResult, fmt)
30
31
32 def test_status_unsupported():
33     assert not api_impl.supports_format(napi.StatusResult, 'gagaga')
34
35
36 def test_status_format_text():
37     assert api_impl.format_result(napi.StatusResult(0, 'message here'), 'text', {}) == 'OK'
38
39
40 def test_status_format_text():
41     assert api_impl.format_result(napi.StatusResult(500, 'message here'), 'text', {}) == 'ERROR: message here'
42
43
44 def test_status_format_json_minimal():
45     status = napi.StatusResult(700, 'Bad format.')
46
47     result = api_impl.format_result(status, 'json', {})
48
49     assert result == '{"status":700,"message":"Bad format.","software_version":"%s"}' % (NOMINATIM_VERSION, )
50
51
52 def test_status_format_json_full():
53     status = napi.StatusResult(0, 'OK')
54     status.data_updated = dt.datetime(2010, 2, 7, 20, 20, 3, 0, tzinfo=dt.timezone.utc)
55     status.database_version = '5.6'
56
57     result = api_impl.format_result(status, 'json', {})
58
59     assert result == '{"status":0,"message":"OK","data_updated":"2010-02-07T20:20:03+00:00","software_version":"%s","database_version":"5.6"}' % (NOMINATIM_VERSION, )
60
61
62 # SearchResult
63
64 def test_search_details_minimal():
65     search = napi.SearchResult(napi.SourceTable.PLACEX,
66                                ('place', 'thing'),
67                                napi.Point(1.0, 2.0))
68
69     result = api_impl.format_result(search, 'details-json', {})
70
71     assert json.loads(result) == \
72            {'category': 'place',
73             'type': 'thing',
74             'admin_level': 15,
75             'localname': '',
76             'calculated_importance': pytest.approx(0.0000001),
77             'rank_address': 30,
78             'rank_search': 30,
79             'isarea': False,
80             'centroid': {'type': 'Point', 'coordinates': [1.0, 2.0]},
81             'geometry': {'type': 'Point', 'coordinates': [1.0, 2.0]},
82            }
83
84
85 def test_search_details_full():
86     import_date = dt.datetime(2010, 2, 7, 20, 20, 3, 0)
87     search = napi.SearchResult(
88                   source_table=napi.SourceTable.PLACEX,
89                   category=('amenity', 'bank'),
90                   centroid=napi.Point(56.947, -87.44),
91                   place_id=37563,
92                   parent_place_id=114,
93                   linked_place_id=55693,
94                   osm_object=('W', 442100),
95                   admin_level=14,
96                   names={'name': 'Bank', 'name:fr': 'Banque'},
97                   address={'city': 'Niento', 'housenumber': '  3'},
98                   extratags={'atm': 'yes'},
99                   housenumber='3',
100                   postcode='556 X23',
101                   wikipedia='en:Bank',
102                   rank_address=29,
103                   rank_search=28,
104                   importance=0.0443,
105                   country_code='ll',
106                   indexed_date = import_date
107                   )
108
109     result = api_impl.format_result(search, 'details-json', {})
110
111     assert json.loads(result) == \
112            {'place_id': 37563,
113             'parent_place_id': 114,
114             'osm_type': 'W',
115             'osm_id': 442100,
116             'category': 'amenity',
117             'type': 'bank',
118             'admin_level': 14,
119             'localname': 'Bank',
120             'names': {'name': 'Bank', 'name:fr': 'Banque'},
121             'addresstags': {'city': 'Niento', 'housenumber': '  3'},
122             'housenumber': '3',
123             'calculated_postcode': '556 X23',
124             'country_code': 'll',
125             'indexed_date': '2010-02-07T20:20:03+00:00',
126             'importance': pytest.approx(0.0443),
127             'calculated_importance': pytest.approx(0.0443),
128             'extratags': {'atm': 'yes'},
129             'calculated_wikipedia': 'en:Bank',
130             'rank_address': 29,
131             'rank_search': 28,
132             'isarea': False,
133             'centroid': {'type': 'Point', 'coordinates': [56.947, -87.44]},
134             'geometry': {'type': 'Point', 'coordinates': [56.947, -87.44]},
135            }
136
137
138 @pytest.mark.parametrize('gtype,isarea', [('ST_Point', False),
139                                           ('ST_LineString', False),
140                                           ('ST_Polygon', True),
141                                           ('ST_MultiPolygon', True)])
142 def test_search_details_no_geometry(gtype, isarea):
143     search = napi.SearchResult(napi.SourceTable.PLACEX,
144                                ('place', 'thing'),
145                                napi.Point(1.0, 2.0),
146                                geometry={'type': gtype})
147
148     result = api_impl.format_result(search, 'details-json', {})
149     js = json.loads(result)
150
151     assert js['geometry'] == {'type': 'Point', 'coordinates': [1.0, 2.0]}
152     assert js['isarea'] == isarea
153
154
155 def test_search_details_with_geometry():
156     search = napi.SearchResult(napi.SourceTable.PLACEX,
157                                ('place', 'thing'),
158                                napi.Point(1.0, 2.0),
159                                geometry={'geojson': '{"type":"Point","coordinates":[56.947,-87.44]}'})
160
161     result = api_impl.format_result(search, 'details-json', {})
162     js = json.loads(result)
163
164     assert js['geometry'] == {'type': 'Point', 'coordinates': [56.947, -87.44]}
165     assert js['isarea'] == False
166
167
168 def test_search_details_with_address_minimal():
169     search = napi.SearchResult(napi.SourceTable.PLACEX,
170                                ('place', 'thing'),
171                                napi.Point(1.0, 2.0),
172                                address_rows=[
173                                    napi.AddressLine(place_id=None,
174                                                     osm_object=None,
175                                                     category=('bnd', 'note'),
176                                                     names={},
177                                                     extratags=None,
178                                                     admin_level=None,
179                                                     fromarea=False,
180                                                     isaddress=False,
181                                                     rank_address=10,
182                                                     distance=0.0)
183                                ])
184
185     result = api_impl.format_result(search, 'details-json', {})
186     js = json.loads(result)
187
188     assert js['address'] == [{'localname': '',
189                               'class': 'bnd',
190                               'type': 'note',
191                               'rank_address': 10,
192                               'distance': 0.0,
193                               'isaddress': False}]
194
195
196 def test_search_details_with_address_full():
197     search = napi.SearchResult(napi.SourceTable.PLACEX,
198                                ('place', 'thing'),
199                                napi.Point(1.0, 2.0),
200                                address_rows=[
201                                    napi.AddressLine(place_id=3498,
202                                                     osm_object=('R', 442),
203                                                     category=('bnd', 'note'),
204                                                     names={'name': 'Trespass'},
205                                                     extratags={'access': 'no',
206                                                                'place_type': 'spec'},
207                                                     admin_level=4,
208                                                     fromarea=True,
209                                                     isaddress=True,
210                                                     rank_address=10,
211                                                     distance=0.034)
212                                ])
213
214     result = api_impl.format_result(search, 'details-json', {})
215     js = json.loads(result)
216
217     assert js['address'] == [{'localname': 'Trespass',
218                               'place_id': 3498,
219                               'osm_id': 442,
220                               'osm_type': 'R',
221                               'place_type': 'spec',
222                               'class': 'bnd',
223                               'type': 'note',
224                               'admin_level': 4,
225                               'rank_address': 10,
226                               'distance': 0.034,
227                               'isaddress': True}]