]> git.openstreetmap.org Git - nominatim.git/blob - test/python/cli/test_cmd_api.py
CLI: make --entrances work for all reverse,lookup,details
[nominatim.git] / test / python / cli / test_cmd_api.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) 2025 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_api as napi
14 from nominatim_api.types import EntranceDetails
15
16
17 @pytest.mark.parametrize('call', ['search', 'reverse', 'lookup', 'details', 'status'])
18 def test_list_format(cli_call, call):
19     assert 0 == cli_call(call, '--list-formats')
20
21
22 @pytest.mark.parametrize('call', ['search', 'reverse', 'lookup', 'details', 'status'])
23 def test_bad_format(cli_call, call):
24     assert 1 == cli_call(call, '--format', 'rsdfsdfsdfsaefsdfsd')
25
26
27 class TestCliStatusCall:
28
29     @pytest.fixture(autouse=True)
30     def setup_status_mock(self, monkeypatch):
31         monkeypatch.setattr(napi.NominatimAPI, 'status',
32                             lambda self: napi.StatusResult(200, 'OK'))
33
34     def test_status_simple(self, cli_call, tmp_path):
35         result = cli_call('status', '--project-dir', str(tmp_path))
36
37         assert result == 0
38
39     def test_status_json_format(self, cli_call, tmp_path, capsys):
40         result = cli_call('status', '--project-dir', str(tmp_path),
41                           '--format', 'json')
42
43         assert result == 0
44
45         json.loads(capsys.readouterr().out)
46
47
48 class TestCliDetailsCall:
49
50     @pytest.fixture(autouse=True)
51     def setup_status_mock(self, monkeypatch):
52         result = napi.DetailedResult(napi.SourceTable.PLACEX, ('place', 'thing'),
53                                      napi.Point(1.0, -3.0))
54
55         monkeypatch.setattr(napi.NominatimAPI, 'details',
56                             lambda *args, **kwargs: result)
57
58     @pytest.mark.parametrize("params", [('--node', '1'),
59                                         ('--way', '1'),
60                                         ('--relation', '1'),
61                                         ('--place_id', '10001')])
62     def test_details_json_format(self, cli_call, tmp_path, capsys, params):
63         result = cli_call('details', '--project-dir', str(tmp_path), *params)
64
65         assert result == 0
66
67         json.loads(capsys.readouterr().out)
68
69
70 class TestCliReverseCall:
71
72     @pytest.fixture(autouse=True)
73     def setup_reverse_mock(self, monkeypatch):
74         result = napi.ReverseResult(napi.SourceTable.PLACEX, ('place', 'thing'),
75                                     napi.Point(1.0, -3.0),
76                                     names={'name': 'Name', 'name:fr': 'Nom'},
77                                     extratags={'extra': 'Extra'},
78                                     locale_name='Name')
79
80         monkeypatch.setattr(napi.NominatimAPI, 'reverse',
81                             lambda *args, **kwargs: result)
82
83     def test_reverse_simple(self, cli_call, tmp_path, capsys):
84         result = cli_call('reverse', '--project-dir', str(tmp_path),
85                           '--lat', '34', '--lon', '34')
86
87         assert result == 0
88
89         out = json.loads(capsys.readouterr().out)
90         assert out['name'] == 'Name'
91         assert 'address' not in out
92         assert 'extratags' not in out
93         assert 'namedetails' not in out
94
95     @pytest.mark.parametrize('param,field', [('--addressdetails', 'address'),
96                                              ('--extratags', 'extratags'),
97                                              ('--namedetails', 'namedetails')])
98     def test_reverse_extra_stuff(self, cli_call, tmp_path, capsys, param, field):
99         result = cli_call('reverse', '--project-dir', str(tmp_path),
100                           '--lat', '34', '--lon', '34', param)
101
102         assert result == 0
103
104         out = json.loads(capsys.readouterr().out)
105         assert field in out
106
107     def test_reverse_format(self, cli_call, tmp_path, capsys):
108         result = cli_call('reverse', '--project-dir', str(tmp_path),
109                           '--lat', '34', '--lon', '34', '--format', 'geojson')
110
111         assert result == 0
112
113         out = json.loads(capsys.readouterr().out)
114         assert out['type'] == 'FeatureCollection'
115
116
117 class TestCliLookupCall:
118
119     @pytest.fixture(autouse=True)
120     def setup_lookup_mock(self, monkeypatch):
121         result = napi.SearchResult(napi.SourceTable.PLACEX, ('place', 'thing'),
122                                    napi.Point(1.0, -3.0),
123                                    names={'name': 'Name', 'name:fr': 'Nom'},
124                                    extratags={'extra': 'Extra'},
125                                    locale_name='Name')
126
127         monkeypatch.setattr(napi.NominatimAPI, 'lookup',
128                             lambda *args, **kwargs: napi.SearchResults([result]))
129
130     def test_lookup_simple(self, cli_call, tmp_path, capsys):
131         result = cli_call('lookup', '--project-dir', str(tmp_path),
132                           '--id', 'N34')
133
134         assert result == 0
135
136         out = json.loads(capsys.readouterr().out)
137         assert len(out) == 1
138         assert out[0]['name'] == 'Name'
139         assert 'address' not in out[0]
140         assert 'extratags' not in out[0]
141         assert 'namedetails' not in out[0]
142
143
144 @pytest.mark.parametrize('endpoint, params', [('search', ('--query', 'Berlin')),
145                                               ('search_address', ('--city', 'Berlin'))
146                                               ])
147 def test_search(cli_call, tmp_path, capsys, monkeypatch, endpoint, params):
148     result = napi.SearchResult(napi.SourceTable.PLACEX, ('place', 'thing'),
149                                napi.Point(1.0, -3.0),
150                                names={'name': 'Name', 'name:fr': 'Nom'},
151                                extratags={'extra': 'Extra'},
152                                locale_name='Name')
153
154     monkeypatch.setattr(napi.NominatimAPI, endpoint,
155                         lambda *args, **kwargs: napi.SearchResults([result]))
156
157     result = cli_call('search', '--project-dir', str(tmp_path), *params)
158
159     assert result == 0
160
161     out = json.loads(capsys.readouterr().out)
162     assert len(out) == 1
163     assert out[0]['name'] == 'Name'
164     assert 'address' not in out[0]
165     assert 'extratags' not in out[0]
166     assert 'namedetails' not in out[0]
167
168
169 @pytest.mark.parametrize('call, params, rtype',
170                          [('search', ('--query', 'Berlin'), napi.SearchResult),
171                           ('reverse', ('--lat', '34', '--lon', '34'), napi.ReverseResult),
172                           ('lookup', ('--id', 'N34'), napi.SearchResult),
173                           ('details', ('--node', '34'), napi.DetailedResult)])
174 def test_entrances_parameter(cli_call, tmp_path, capsys, monkeypatch, call, params, rtype):
175     result = rtype(napi.SourceTable.PLACEX, ('place', 'thing'), napi.Point(1.0, -3.0))
176
177     def _api_call(*args, entrances=False, **kwargs):
178         # Like the real API, only add entrances when they were requested.
179         if entrances:
180             result.entrances = [EntranceDetails(45, 'main', napi.Point(1.0, -3.0), {})]
181         return napi.SearchResults([result]) if rtype is napi.SearchResult else result
182
183     monkeypatch.setattr(napi.NominatimAPI, call, _api_call)
184
185     assert cli_call(call, '--project-dir', str(tmp_path), *params, '--entrances') == 0
186     assert '"osm_id": 45' in capsys.readouterr().out