Source code for geonode.maps.api.tests

#########################################################################
#
# Copyright (C) 2016 OSGeo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#########################################################################
import logging
from urllib.parse import urljoin

from django.conf import settings
from django.urls import reverse

from guardian.shortcuts import assign_perm, get_anonymous_user
from mock import patch
from rest_framework.test import APITestCase

from geonode.base.populate_test_data import create_models
from geonode.layers.models import Dataset
from geonode.maps.models import Map, MapLayer

[docs] logger = logging.getLogger(__name__)
[docs] class MapsApiTests(APITestCase):
[docs] fixtures = ["initial_data.json", "group_test_data.json", "default_oauth_apps.json"]
[docs] def setUp(self): create_models(b"document") create_models(b"map") create_models(b"dataset") first_map = Map.objects.first() first_map.blob = DUMMY_MAPDATA first_map.save() first_dataset = Dataset.objects.first() MapLayer.objects.create( map=first_map, extra_params={"foo": "bar"}, name=first_dataset.alternate, store=first_dataset.store, current_style="some-style", local=True, )
[docs] def test_maps(self): """ Ensure we can access the Maps list. """ url = reverse("maps-list") # Anonymous response = self.client.get(url, format="json") self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data), 5) self.assertEqual(response.data["total"], 9) # Check: No overfetching for maplayers self.assertTrue(any([map.get("maplayers", []) for map in response.data["maps"]])) # Pagination self.assertEqual(len(response.data["maps"]), 9) logger.debug(response.data) for _l in response.data["maps"]: self.assertTrue(_l["resource_type"], "map") # Get Layers List (backgrounds) resource = Map.objects.first() assign_perm("base.view_resourcebase", get_anonymous_user(), resource.get_self_resource()) url = urljoin(f"{reverse('maps-detail', kwargs={'pk': resource.pk})}/", "maplayers/") response = self.client.get(url, format="json") self.assertEqual(response.status_code, 200) layers_data = response.data self.assertIsNotNone(layers_data) self.assertEqual(layers_data[0]["extra_params"], {"foo": "bar"}) self.assertIsNotNone(layers_data[0]["dataset"]) # Get Local-Layers List (GeoNode) url = urljoin(f"{reverse('maps-detail', kwargs={'pk': resource.pk})}/", "datasets/") response = self.client.get(url, format="json") self.assertEqual(response.status_code, 200) layers_data = response.data self.assertIsNotNone(layers_data) if settings.GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY == "mapstore": url = reverse("maps-list") self.assertEqual(url, "/api/v2/maps") # Anonymous response = self.client.get(url, format="json") self.assertEqual(response.status_code, 200) if response.data: self.assertEqual(len(response.data), 5) # now are 5 since will read from maps # Get Full Map layer configuration url = reverse("maps-detail", kwargs={"pk": resource.pk}) response = self.client.get(f"{url}?include[]=data", format="json") self.assertEqual(response.status_code, 200) self.assertTrue(len(response.data) > 0) self.assertTrue("data" in response.data["map"]) self.assertTrue(len(response.data["map"]["data"]["map"]["layers"]) == 7) self.assertEqual(response.data["map"]["maplayers"][0]["extra_params"], {"foo": "bar"}) self.assertIsNotNone(response.data["map"]["maplayers"][0]["dataset"]) self.assertEqual(response.data["map"]["maplayers"][0]["extra_params"], {"foo": "bar"}) self.assertEqual(response.data["map"]["maplayers"][0]["visibility"], 1) self.assertEqual(response.data["map"]["maplayers"][0]["order"], 0) self.assertEqual(response.data["map"]["maplayers"][0]["opacity"], 1.0)
[docs] def test_extra_metadata_included_with_param(self): resource = Map.objects.first() url = urljoin(f"{reverse('maps-list')}/", f"{resource.pk}") data = {"include[]": "metadata"} response = self.client.get(url, format="json", data=data) self.assertIsNotNone(response.data["map"].get("metadata")) response = self.client.get(url, format="json") self.assertNotIn("map", response.data["map"])
[docs] def test_patch_map(self): """ Patch to maps/<pk>/ """ # Get Layers List (backgrounds) resource = Map.objects.first() url = reverse("maps-detail", kwargs={"pk": resource.pk}) data = { "title": f"{resource.title}-edited", "abstract": resource.abstract, "data": DUMMY_MAPDATA, "id": resource.id, "maplayers": DUMMY_MAPLAYERS_DATA, } self.client.login(username="admin", password="admin") response = self.client.patch(f"{url}?include[]=data", data=data, format="json") self.assertEqual(response.status_code, 200) self.assertTrue(len(response.data) > 0) self.assertTrue("data" in response.data["map"]) self.assertTrue(len(response.data["map"]["data"]["map"]["layers"]) == 7) response_maplayer = response.data["map"]["maplayers"][0] self.assertEqual(response_maplayer["extra_params"], {"msId": "Stamen.Watercolor__0"}) self.assertEqual(response_maplayer["current_style"], "some-style-first-layer") self.assertIsNotNone(response_maplayer["dataset"])
[docs] def test_patch_map_with_extra_maplayer_info(self): """ Patch to maps/<pk>/ """ # Get Layers List (backgrounds) resource = Map.objects.first() url = reverse("maps-detail", kwargs={"pk": resource.pk}) data = { "title": f"{resource.title}-edited", "abstract": resource.abstract, "data": DUMMY_MAPDATA, "id": resource.id, "maplayers": DUMMY_MAPLAYERS_DATA_WITH_EXTRA_INFO, } self.client.login(username="admin", password="admin") response = self.client.patch(f"{url}?include[]=data", data=data, format="json") self.assertEqual(response.status_code, 200) self.assertTrue(len(response.data) > 0) self.assertTrue("data" in response.data["map"]) self.assertTrue(len(response.data["map"]["data"]["map"]["layers"]) == 7) response_maplayer = response.data["map"]["maplayers"][0] self.assertEqual(response_maplayer["extra_params"], {"msId": "Stamen.Watercolor__0"}) self.assertEqual(response_maplayer["current_style"], "some-style-first-layer") self.assertEqual(response_maplayer["visibility"], False) self.assertEqual(response_maplayer["order"], 99) self.assertEqual(response_maplayer["opacity"], 1.3) self.assertIsNotNone(response_maplayer["dataset"])
@patch("geonode.maps.api.views.resolve_object")
[docs] def test_patch_map_raise_exception(self, mocked_obj): """ Patch to maps/<pk>/ """ # Get Layers List (backgrounds) resource = Map.objects.first() mocked_obj.return_value = Map.objects.last() url = reverse("maps-detail", kwargs={"pk": resource.pk}) data = { "title": f"{resource.title}-edited", "abstract": resource.abstract, "data": DUMMY_MAPDATA, "id": resource.id, "maplayers": DUMMY_MAPLAYERS_DATA, } self.client.login(username="admin", password="admin") response = self.client.patch(f"{url}?include[]=data", data=data, format="json") expected_error = { "success": False, "errors": ["serializer instance and object are different"], "code": "maps_exception", } self.assertEqual(response.status_code, 500) self.assertEqual(expected_error, response.json())
[docs] def test_create_map(self): """ Post to maps/ """ # Get Layers List (backgrounds) url = reverse("maps-list") data = { "title": "Some created map", "data": DUMMY_MAPDATA, "maplayers": DUMMY_MAPLAYERS_DATA, } self.client.login(username="admin", password="admin") response = self.client.post(f"{url}?include[]=data", data=data, format="json") self.assertEqual(response.status_code, 201) self.assertTrue(len(response.data) > 0) self.assertTrue("data" in response.data["map"]) self.assertTrue(len(response.data["map"]["data"]["map"]["layers"]) == 7) response_maplayer = response.data["map"]["maplayers"][0] self.assertEqual(response_maplayer["extra_params"], {"msId": "Stamen.Watercolor__0"}) self.assertEqual(response_maplayer["current_style"], "some-style-first-layer") self.assertIsNotNone(response_maplayer["dataset"]) self.assertIsNotNone(response.data["map"]["thumbnail_url"])
[docs] def test_create_map_with_extra_maplayer_info(self): """ Post to maps/ """ # Get Layers List (backgrounds) url = reverse("maps-list") data = { "title": "Some created map", "data": DUMMY_MAPDATA, "maplayers": DUMMY_MAPLAYERS_DATA_WITH_EXTRA_INFO, } self.client.login(username="admin", password="admin") response = self.client.post(f"{url}?include[]=data", data=data, format="json") self.assertEqual(response.status_code, 201) self.assertTrue(len(response.data) > 0) self.assertTrue("data" in response.data["map"]) self.assertTrue(len(response.data["map"]["data"]["map"]["layers"]) == 7) response_maplayer = response.data["map"]["maplayers"][0] self.assertEqual(response_maplayer["extra_params"], {"msId": "Stamen.Watercolor__0"}) self.assertEqual(response_maplayer["current_style"], "some-style-first-layer") self.assertIsNotNone(response_maplayer["dataset"]) self.assertEqual(response_maplayer["visibility"], False) self.assertEqual(response_maplayer["order"], 99) self.assertEqual(response_maplayer["opacity"], 1.3) self.assertIsNotNone(response.data["map"]["thumbnail_url"])
[docs] DUMMY_MAPDATA = { "map": { "zoom": 9, "units": "m", "center": {"x": 11.763505157657004, "y": 43.7880264429571, "crs": "EPSG:4326"}, "groups": [{"id": "Default", "title": "Default", "expanded": True}], "layers": [ { "id": "Stamen.Watercolor__0", "name": "Stamen.Watercolor", "type": "tileprovider", "group": "background", "title": "Stamen Watercolor", "hidden": False, "source": "Stamen", "provider": "Stamen.Watercolor", "thumbURL": "https://stamen-tiles-c.a.ssl.fastly.net/watercolor/0/0/0.jpg", "dimensions": [], "styles": ["some-style-first-layer", "some-other-style-first-layer"], "singleTile": False, "visibility": False, "extraParams": {"msId": "Stamen.Watercolor__0"}, "hideLoading": False, "useForElevation": False, "handleClickOnLayer": False, }, { "id": "Stamen.Terrain__1", "name": "Stamen.Terrain", "type": "tileprovider", "group": "background", "title": "Stamen Terrain", "hidden": False, "source": "Stamen", "provider": "Stamen.Terrain", "thumbURL": "https://stamen-tiles-d.a.ssl.fastly.net/terrain/0/0/0.png", "dimensions": [], "singleTile": False, "visibility": False, "extraParams": {"msId": "Stamen.Terrain__1"}, "hideLoading": False, "useForElevation": False, "handleClickOnLayer": False, }, { "id": "Stamen.Toner__2", "name": "Stamen.Toner", "type": "tileprovider", "group": "background", "title": "Stamen Toner", "hidden": False, "source": "Stamen", "provider": "Stamen.Toner", "thumbURL": "https://stamen-tiles-d.a.ssl.fastly.net/toner/0/0/0.png", "dimensions": [], "singleTile": False, "visibility": False, "extraParams": {"msId": "Stamen.Toner__2"}, "hideLoading": False, "useForElevation": False, "handleClickOnLayer": False, }, { "id": "mapnik__3", "name": "mapnik", "type": "osm", "group": "background", "title": "Open Street Map", "hidden": False, "source": "osm", "dimensions": [], "singleTile": False, "visibility": True, "extraParams": {"msId": "mapnik__3"}, "hideLoading": False, "useForElevation": False, "handleClickOnLayer": False, }, { "id": "OpenTopoMap__4", "name": "OpenTopoMap", "type": "tileprovider", "group": "background", "title": "OpenTopoMap", "hidden": False, "source": "OpenTopoMap", "provider": "OpenTopoMap", "dimensions": [], "singleTile": False, "visibility": False, "extraParams": {"msId": "OpenTopoMap__4"}, "hideLoading": False, "useForElevation": False, "handleClickOnLayer": False, }, { "id": "s2cloudless", "url": "https://maps.geosolutionsgroup.com.it/geoserver/wms", "name": "s2cloudless:s2cloudless", "type": "wms", "group": "background", "title": "Sentinel-2 cloudless - https://s2maps.eu", "format": "image/jpeg", "hidden": False, "thumbURL": "http://localhost:8000/static/mapstorestyle/img/s2cloudless-s2cloudless.png", "dimensions": [], "singleTile": False, "visibility": False, "extraParams": {"msId": "s2cloudless"}, "hideLoading": False, "useForElevation": False, "handleClickOnLayer": False, }, { "id": "none", "name": "empty", "type": "empty", "group": "background", "title": "Empty Background", "hidden": False, "source": "ol", "dimensions": [], "singleTile": False, "visibility": False, "extraParams": {"msId": "none"}, "hideLoading": False, "useForElevation": False, "handleClickOnLayer": False, }, ], "maxExtent": [-20037508.34, -20037508.34, 20037508.34, 20037508.34], "mapOptions": {}, "projection": "EPSG:3857", "backgrounds": [], }, "version": 2, "timelineData": {}, "dimensionData": {}, "widgetsConfig": {"layouts": {"md": [], "xxs": []}}, "catalogServices": { "services": { "GeoNode Catalogue": { "url": "http://localhost:8000/catalogue/csw", "type": "csw", "title": "GeoNode Catalogue", "autoload": True, }, }, "selectedService": "GeoNode Catalogue", }, "mapInfoConfiguration": {}, }
[docs] DUMMY_MAPLAYERS_DATA = [ { "extra_params": {"msId": "Stamen.Watercolor__0"}, "current_style": "some-style-first-layer", "name": "geonode:CA", } ]
[docs] DUMMY_MAPLAYERS_DATA_WITH_EXTRA_INFO = [ { "extra_params": {"msId": "Stamen.Watercolor__0"}, "current_style": "some-style-first-layer", "name": "geonode:CA", "opacity": 1.3, "visibility": False, "order": 99, } ]