Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
giswqs
GitHub Repository: giswqs/geemap
Path: blob/master/tests/test_basemaps.py
2313 views
1
"""Tests for `basemaps` module."""
2
3
import os
4
import unittest
5
from unittest import mock
6
7
import folium
8
import requests
9
import xyzservices
10
11
# TODO - Why can't we just import basemaps?
12
from geemap.basemaps import (
13
custom_tiles,
14
get_qms,
15
get_xyz_dict,
16
search_qms,
17
xyz_to_folium,
18
xyz_to_leaflet,
19
xyz_to_plotly,
20
)
21
from geemap import common
22
23
24
class TestCustomTiles(unittest.TestCase):
25
26
def test_custom_tiles_types(self):
27
"""Tests that custom_tiles is a dict and contains expected keys."""
28
self.assertIsInstance(custom_tiles, dict)
29
expected_keys = ["xyz", "wms"]
30
for key in custom_tiles:
31
self.assertIn(key, expected_keys)
32
33
def test_custom_tiles_xyz(self):
34
"""Tests that custom_tiles["xyz"] is a dict w/ expected keys/values."""
35
tiles = custom_tiles["xyz"]
36
self.assertIsInstance(tiles, dict)
37
for _, value in tiles.items():
38
self.assertIn("url", value)
39
self.assertIn("attribution", value)
40
self.assertIn("name", value)
41
self.assertTrue(value["url"].startswith("http"))
42
43
def test_custom_tiles_wms(self):
44
"""Tests that custom_tiles["wms"] is a dict w/ expected keys/values."""
45
tiles = custom_tiles["wms"]
46
self.assertIsInstance(tiles, dict)
47
for _, value in tiles.items():
48
self.assertIsInstance(value["url"], str)
49
self.assertIsInstance(value["attribution"], str)
50
self.assertIsInstance(value["name"], str)
51
self.assertTrue(value["url"].startswith("http"))
52
53
54
class TestXyzToLeaflet(unittest.TestCase):
55
56
def __init__(self, *args, **kwargs):
57
super().__init__(*args, **kwargs)
58
self.tiles = xyz_to_leaflet()
59
60
def test_xyz_to_leaflet_is_dictionary(self):
61
"""Tests that xyz_to_leaflet returns a dict."""
62
self.assertIsInstance(self.tiles, dict)
63
64
def test_xyz_to_leaflet_sources(self):
65
"""Tests that xyz_to_leaflet has custom xyz, wms, and xyzservices."""
66
expected_keys = {
67
"custom_xyz": "OpenStreetMap",
68
"custom_wms": "USGS NAIP Imagery",
69
"xyzservices_xyz": "Esri.WorldTopoMap",
70
}
71
for _, expected_name in expected_keys.items():
72
self.assertIn(expected_name, self.tiles)
73
74
75
class TestXyzToFolium(unittest.TestCase):
76
77
def test_xyz_to_folium_sources(self):
78
"""Tests that xyz_to_folium has custom xyz, wms, and xyzservices."""
79
tiles = xyz_to_folium()
80
self.assertIn("OpenStreetMap", tiles) # custom xyz
81
self.assertIn("FWS NWI Wetlands", tiles) # custom wms
82
self.assertIn("CartoDB.Positron", tiles) # xyzservices
83
84
for name, tile_layer in tiles.items():
85
if name in custom_tiles["wms"]:
86
self.assertIsInstance(tile_layer, folium.WmsTileLayer)
87
else:
88
self.assertIsInstance(tile_layer, folium.TileLayer)
89
90
@mock.patch.dict(os.environ, {"PLANET_API_KEY": "fake_api_key"})
91
@mock.patch.object(common, "planet_tiles")
92
def test_xyz_to_folium_with_planet(self, mock_planet_tiles):
93
"""Tests that xyz_to_folium includes planet tiles if API key is set."""
94
mock_planet_tiles.return_value = {
95
"Planet Basemap": folium.TileLayer(
96
tiles="https://fake-planet.com/tiles/{z}/{x}/{y}",
97
attr="Planet",
98
name="Planet Basemap",
99
)
100
}
101
tiles = xyz_to_folium()
102
self.assertIn("Planet Basemap", tiles)
103
mock_planet_tiles.assert_called_once_with(tile_format="folium")
104
105
106
class FakeProvider(xyzservices.TileProvider):
107
108
def __init__(self, name: str, url: str):
109
super().__init__(
110
name=name,
111
url=url,
112
attribution="© Fake Provider",
113
accessToken="<insert your access token here>",
114
)
115
116
117
class FakeXyz(xyzservices.Bunch):
118
119
def __init__(self):
120
token = "https://fake-server.com/tiles/{z}/{x}/{y}?apikey={accessToken}"
121
no_token = "https://fake-server.com/tiles/{z}/{x}/{y}"
122
123
self.fake_tile_a = FakeProvider("a", no_token)
124
self.fake_tile_b = FakeProvider("b", token)
125
self.fake_tile_c_1 = FakeProvider("c_1", no_token)
126
self.fake_tile_c_France = FakeProvider("c_France", no_token)
127
128
self.providers = xyzservices.Bunch(
129
a=self.fake_tile_a,
130
b=self.fake_tile_b,
131
c=xyzservices.Bunch(c_1=self.fake_tile_c_1, c_2=self.fake_tile_c_France),
132
)
133
134
135
@mock.patch.object(xyzservices, "providers", FakeXyz().providers)
136
class TestGetXyzDict(unittest.TestCase):
137
138
def test_get_xyz_dict_structure(self):
139
"""Tests that get_xyz_dict returns correct object structure."""
140
xyz_dict = get_xyz_dict()
141
tile_a = xyz_dict["a"]
142
tile_a_keys = tile_a.keys()
143
144
self.assertEqual("c_1", list(xyz_dict.keys())[1])
145
self.assertIsInstance(tile_a, xyzservices.lib.TileProvider)
146
self.assertIn("name", tile_a_keys)
147
self.assertIn("url", tile_a_keys)
148
self.assertIn("attribution", tile_a_keys)
149
self.assertIn("accessToken", tile_a_keys)
150
self.assertEqual("xyz", tile_a["type"])
151
self.assertEqual("a", tile_a.name)
152
self.assertEqual(
153
"https://fake-server.com/tiles/{z}/{x}/{y}", tile_a.build_url()
154
)
155
156
def test_get_xyz_dict_free_tiles(self):
157
"""Tests that get_xyz_dict correctly filters for free tile layers."""
158
xyz_dict_free = get_xyz_dict(free_only=True)
159
xyz_dict_all = get_xyz_dict(free_only=False)
160
161
self.assertNotIn("b", xyz_dict_free.keys())
162
self.assertIn("b", xyz_dict_all.keys())
163
164
def test_get_xyz_dict_france_tiles(self):
165
"""Tests that get_xyz_dict correctly filters for France tile layers."""
166
xyz_dict_all = get_xyz_dict(france=True)
167
xyz_dict_no_france = get_xyz_dict(france=False)
168
169
self.assertNotIn("c_France", xyz_dict_no_france.keys())
170
self.assertIn("c_France", xyz_dict_all.keys())
171
172
173
class TestXyzToPlotly(unittest.TestCase):
174
175
def test_xyz_to_plotly_sources(self):
176
"""Tests that xyz_to_plotly has custom xyz and xyzservices."""
177
tiles = xyz_to_plotly()
178
self.assertIn("OpenStreetMap", tiles) # custom xyz
179
self.assertIn("CartoDB.Positron", tiles) # xyzservices
180
181
for _, tile_layer in tiles.items():
182
self.assertIn("below", tile_layer)
183
self.assertIn("sourcetype", tile_layer)
184
self.assertEqual("raster", tile_layer["sourcetype"])
185
self.assertIn("source", tile_layer)
186
self.assertIsInstance(tile_layer["source"], list)
187
188
189
class TestQms(unittest.TestCase):
190
191
@mock.patch.object(requests, "get")
192
def test_search_qms_no_results(self, mock_get):
193
"""Tests search_qms with no results."""
194
mock_response = mock_get.return_value
195
mock_response.json.return_value = {"count": 0, "results": []}
196
result = search_qms("no results")
197
self.assertIsNone(result)
198
mock_get.assert_called_once_with(
199
"https://qms.nextgis.com/api/v1/geoservices/?search=no results&type=tms&epsg=3857&limit=10"
200
)
201
202
@mock.patch.object(requests, "get")
203
def test_search_qms_with_results(self, mock_get):
204
"""Tests search_qms with results."""
205
mock_response = mock_get.return_value
206
mock_response.json.return_value = {
207
"count": 1,
208
"results": [{"id": 1, "name": "result1"}],
209
}
210
result = search_qms("results")
211
self.assertEqual(result, [{"id": 1, "name": "result1"}])
212
mock_get.assert_called_once_with(
213
"https://qms.nextgis.com/api/v1/geoservices/?search=results&type=tms&epsg=3857&limit=10"
214
)
215
216
@mock.patch.object(requests, "get")
217
def test_search_qms_with_limit(self, mock_get):
218
"""Tests search_qms with limit."""
219
mock_response = mock_get.return_value
220
mock_response.json.return_value = {
221
"count": 1,
222
"results": [{"id": 1, "name": "result1"}],
223
}
224
result = search_qms("results", limit=5)
225
self.assertEqual(result, [{"id": 1, "name": "result1"}])
226
mock_get.assert_called_once_with(
227
"https://qms.nextgis.com/api/v1/geoservices/?search=results&type=tms&epsg=3857&limit=5"
228
)
229
230
@mock.patch.object(requests, "get")
231
def test_search_qms_count_greater_than_limit(self, mock_get):
232
"""Tests search_qms with count > limit."""
233
mock_response = mock_get.return_value
234
mock_response.json.return_value = {
235
"count": 2,
236
"results": [{"id": 1, "name": "result1"}, {"id": 2, "name": "result2"}],
237
}
238
result = search_qms("results", limit=1)
239
self.assertEqual(result, [{"id": 1, "name": "result1"}])
240
mock_get.assert_called_once_with(
241
"https://qms.nextgis.com/api/v1/geoservices/?search=results&type=tms&epsg=3857&limit=1"
242
)
243
244
@mock.patch.object(requests, "get")
245
def test_get_qms(self, mock_get):
246
"""Tests get_qms."""
247
mock_response = mock_get.return_value
248
mock_response.json.return_value = {"id": 123, "name": "service1"}
249
result = get_qms("123")
250
self.assertEqual(result, {"id": 123, "name": "service1"})
251
mock_get.assert_called_once_with(
252
"https://qms.nextgis.com/api/v1/geoservices/123"
253
)
254
255
256
if __name__ == "__main__":
257
unittest.main()
258
259