]> git.openstreetmap.org Git - nominatim.git/blob - test/python/cli/test_cmd_api.py
add timestamps to HTML debug output
[nominatim.git] / test / python / cli / test_cmd_api.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 API access commands of command-line interface wrapper.
9 """
10 import json
11 import pytest
12
13 import nominatim.clicmd.api
14 import nominatim.api as napi
15
16
17 class TestCliStatusCall:
18
19     @pytest.fixture(autouse=True)
20     def setup_status_mock(self, monkeypatch):
21         monkeypatch.setattr(napi.NominatimAPI, 'status',
22                             lambda self: napi.StatusResult(200, 'OK'))
23
24
25     def test_status_simple(self, cli_call, tmp_path):
26         result = cli_call('status', '--project-dir', str(tmp_path))
27
28         assert result == 0
29
30
31     def test_status_json_format(self, cli_call, tmp_path, capsys):
32         result = cli_call('status', '--project-dir', str(tmp_path),
33                           '--format', 'json')
34
35         assert result == 0
36
37         json.loads(capsys.readouterr().out)
38
39
40 class TestCliDetailsCall:
41
42     @pytest.fixture(autouse=True)
43     def setup_status_mock(self, monkeypatch):
44         result = napi.DetailedResult(napi.SourceTable.PLACEX, ('place', 'thing'),
45                                      napi.Point(1.0, -3.0))
46
47         monkeypatch.setattr(napi.NominatimAPI, 'details',
48                             lambda *args, **kwargs: result)
49
50     @pytest.mark.parametrize("params", [('--node', '1'),
51                                         ('--way', '1'),
52                                         ('--relation', '1'),
53                                         ('--place_id', '10001')])
54
55     def test_details_json_format(self, cli_call, tmp_path, capsys, params):
56         result = cli_call('details', '--project-dir', str(tmp_path), *params)
57
58         assert result == 0
59
60         json.loads(capsys.readouterr().out)
61
62
63 class TestCliReverseCall:
64
65     @pytest.fixture(autouse=True)
66     def setup_reverse_mock(self, monkeypatch):
67         result = napi.ReverseResult(napi.SourceTable.PLACEX, ('place', 'thing'),
68                                     napi.Point(1.0, -3.0),
69                                     names={'name':'Name', 'name:fr': 'Nom'},
70                                     extratags={'extra':'Extra'})
71
72         monkeypatch.setattr(napi.NominatimAPI, 'reverse',
73                             lambda *args, **kwargs: result)
74
75
76     def test_reverse_simple(self, cli_call, tmp_path, capsys):
77         result = cli_call('reverse', '--project-dir', str(tmp_path),
78                           '--lat', '34', '--lon', '34')
79
80         assert result == 0
81
82         out = json.loads(capsys.readouterr().out)
83         assert out['name'] == 'Name'
84         assert 'address' not in out
85         assert 'extratags' not in out
86         assert 'namedetails' not in out
87
88
89     @pytest.mark.parametrize('param,field', [('--addressdetails', 'address'),
90                                              ('--extratags', 'extratags'),
91                                              ('--namedetails', 'namedetails')])
92     def test_reverse_extra_stuff(self, cli_call, tmp_path, capsys, param, field):
93         result = cli_call('reverse', '--project-dir', str(tmp_path),
94                           '--lat', '34', '--lon', '34', param)
95
96         assert result == 0
97
98         out = json.loads(capsys.readouterr().out)
99         assert field in out
100
101
102     def test_reverse_format(self, cli_call, tmp_path, capsys):
103         result = cli_call('reverse', '--project-dir', str(tmp_path),
104                           '--lat', '34', '--lon', '34', '--format', 'geojson')
105
106         assert result == 0
107
108         out = json.loads(capsys.readouterr().out)
109         assert out['type'] == 'FeatureCollection'
110
111
112     def test_reverse_language(self, cli_call, tmp_path, capsys):
113         result = cli_call('reverse', '--project-dir', str(tmp_path),
114                           '--lat', '34', '--lon', '34', '--lang', 'fr')
115
116         assert result == 0
117
118         out = json.loads(capsys.readouterr().out)
119         assert out['name'] == 'Nom'
120
121
122 class TestCliLookupCall:
123
124     @pytest.fixture(autouse=True)
125     def setup_lookup_mock(self, monkeypatch):
126         result = napi.SearchResult(napi.SourceTable.PLACEX, ('place', 'thing'),
127                                     napi.Point(1.0, -3.0),
128                                     names={'name':'Name', 'name:fr': 'Nom'},
129                                     extratags={'extra':'Extra'})
130
131         monkeypatch.setattr(napi.NominatimAPI, 'lookup',
132                             lambda *args, **kwargs: napi.SearchResults([result]))
133
134     def test_lookup_simple(self, cli_call, tmp_path, capsys):
135         result = cli_call('lookup', '--project-dir', str(tmp_path),
136                           '--id', 'N34')
137
138         assert result == 0
139
140         out = json.loads(capsys.readouterr().out)
141         assert len(out) == 1
142         assert out[0]['name'] == 'Name'
143         assert 'address' not in out[0]
144         assert 'extratags' not in out[0]
145         assert 'namedetails' not in out[0]
146
147
148 @pytest.mark.parametrize('endpoint, params', [('search', ('--query', 'Berlin')),
149                                               ('search_address', ('--city', 'Berlin'))
150                                              ])
151 def test_search(cli_call, tmp_path, capsys, monkeypatch, endpoint, params):
152     result = napi.SearchResult(napi.SourceTable.PLACEX, ('place', 'thing'),
153                                 napi.Point(1.0, -3.0),
154                                 names={'name':'Name', 'name:fr': 'Nom'},
155                                 extratags={'extra':'Extra'})
156
157     monkeypatch.setattr(napi.NominatimAPI, endpoint,
158                         lambda *args, **kwargs: napi.SearchResults([result]))
159
160
161     result = cli_call('search', '--project-dir', str(tmp_path), *params)
162
163     assert result == 0
164
165     out = json.loads(capsys.readouterr().out)
166     assert len(out) == 1
167     assert out[0]['name'] == 'Name'
168     assert 'address' not in out[0]
169     assert 'extratags' not in out[0]
170     assert 'namedetails' not in out[0]
171
172
173 class TestCliApiCommonParameters:
174
175     @pytest.fixture(autouse=True)
176     def setup_website_dir(self, cli_call, project_env):
177         self.cli_call = cli_call
178         self.project_dir = project_env.project_dir
179         (self.project_dir / 'website').mkdir()
180
181
182     def expect_param(self, param, expected):
183         (self.project_dir / 'website' / ('search.php')).write_text(f"""<?php
184         exit($_GET['{param}']  == '{expected}' ? 0 : 10);
185         """)
186
187
188     def call_nominatim(self, *params):
189         return self.cli_call('search', '--query', 'somewhere',
190                              '--project-dir', str(self.project_dir), *params)
191
192
193     def test_param_output(self):
194         self.expect_param('format', 'xml')
195         assert self.call_nominatim('--format', 'xml') == 0
196
197
198     def test_param_lang(self):
199         self.expect_param('accept-language', 'de')
200         assert self.call_nominatim('--lang', 'de') == 0
201         assert self.call_nominatim('--accept-language', 'de') == 0
202
203
204     @pytest.mark.parametrize("param", ('addressdetails', 'extratags', 'namedetails'))
205     def test_param_extradata(self, param):
206         self.expect_param(param, '1')
207
208         assert self.call_nominatim('--' + param) == 0
209
210     def test_param_polygon_output(self):
211         self.expect_param('polygon_geojson', '1')
212
213         assert self.call_nominatim('--polygon-output', 'geojson') == 0
214
215
216     def test_param_polygon_threshold(self):
217         self.expect_param('polygon_threshold', '0.3452')
218
219         assert self.call_nominatim('--polygon-threshold', '0.3452') == 0
220
221
222 def test_cli_search_param_bounded(cli_call, project_env):
223     webdir = project_env.project_dir / 'website'
224     webdir.mkdir()
225     (webdir / 'search.php').write_text(f"""<?php
226         exit($_GET['bounded']  == '1' ? 0 : 10);
227         """)
228
229     assert cli_call('search', '--query', 'somewhere', '--project-dir', str(project_env.project_dir),
230                     '--bounded') == 0
231
232
233 def test_cli_search_param_dedupe(cli_call, project_env):
234     webdir = project_env.project_dir / 'website'
235     webdir.mkdir()
236     (webdir / 'search.php').write_text(f"""<?php
237         exit($_GET['dedupe']  == '0' ? 0 : 10);
238         """)
239
240     assert cli_call('search', '--query', 'somewhere', '--project-dir', str(project_env.project_dir),
241                     '--no-dedupe') == 0