From 0757cd7fca1b5e4700d692c26c5b03d075f57502 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Fri, 3 Apr 2020 11:08:40 +0200
Subject: [PATCH] maps: geojson url per geojson layer (#40742)

---
 combo/apps/maps/models.py                    |  39 +++---
 combo/apps/maps/static/js/combo.map.js       |  94 +++++++-------
 combo/apps/maps/templates/maps/map_cell.html |   9 +-
 combo/apps/maps/urls.py                      |   2 +-
 combo/apps/maps/views.py                     |  24 ++--
 tests/test_maps_cells.py                     | 121 +++++++++++--------
 tests/test_maps_manager.py                   |   4 +-
 7 files changed, 162 insertions(+), 131 deletions(-)

diff --git a/combo/apps/maps/models.py b/combo/apps/maps/models.py
index 7f33ad9..b296147 100644
--- a/combo/apps/maps/models.py
+++ b/combo/apps/maps/models.py
@@ -178,14 +178,15 @@ class MapLayer(models.Model):
         layer = next(serializers.deserialize('json', json.dumps([json_layer]), ignorenonexistent=True))
         layer.save()
 
-    def get_geojson(self, request=None, multiple_layers=False):
+    def get_geojson(self, request):
         geojson_url = get_templated_url(self.geojson_url)
-        response = requests.get(geojson_url,
-                            remote_service='auto',
-                            cache_duration=self.cache_duration,
-                            user=request.user if (request and self.include_user_identifier) else None,
-                            without_user=not(self.include_user_identifier),
-                            headers={'accept': 'application/json'})
+        response = requests.get(
+            geojson_url,
+            remote_service='auto',
+            cache_duration=self.cache_duration,
+            user=request.user if (request and self.include_user_identifier) else None,
+            without_user=not(self.include_user_identifier),
+            headers={'accept': 'application/json'})
         if not response.ok:
             return []
         data = response.json()
@@ -230,13 +231,9 @@ class MapLayer(models.Model):
             # all words must match
             query_words = [slugify(x) for x in request.GET['q'].split()]
 
-            additional_strings = []
-            if multiple_layers:  # also match on layer name
-                additional_strings = [self.label]
-
             def match(feature):
                 matching_query_words = set()
-                feature_words = additional_strings[:]
+                feature_words = [self.label]
 
                 def get_feature_words(properties):
                     for property in properties.values():
@@ -266,7 +263,7 @@ class MapLayer(models.Model):
                 'identifier': self.slug,
                 'properties': properties,
             }
-        return features
+        return {'type': 'FeatureCollection', 'features': features}
 
 
 @register_cell_class
@@ -319,14 +316,6 @@ class Map(CellBase):
                   'max_zoom', 'group_markers', 'marker_behaviour_onclick')
         return forms.models.modelform_factory(self.__class__, fields=fields)
 
-    def get_geojson(self, request):
-        geojson = {'type': 'FeatureCollection', 'features': []}
-        layers = self.layers.filter(kind='geojson')
-        for layer in layers:
-            geojson['features'] += layer.get_geojson(request,
-                    multiple_layers=bool(len(layers) > 1))
-        return geojson
-
     @classmethod
     def is_enabled(cls):
         return MapLayer.objects.exists()
@@ -363,6 +352,12 @@ class Map(CellBase):
             })
         return tiles_layers
 
+    def get_geojson_layers(self):
+        if not self.pk:
+            return []
+        return [{'url': reverse_lazy('mapcell-geojson', kwargs={'cell_id': self.pk, 'layer_slug': l.slug}),
+                 'slug': l.slug} for l in self.layers.filter(kind='geojson')]
+
     def get_cell_extra_context(self, context):
         ctx = super(Map, self).get_cell_extra_context(context)
         ctx['title'] = self.title
@@ -373,7 +368,7 @@ class Map(CellBase):
         ctx['initial_zoom'] = self.initial_zoom
         ctx['min_zoom'] = self.min_zoom
         ctx['max_zoom'] = self.max_zoom
-        ctx['geojson_url'] = reverse_lazy('mapcell-geojson', kwargs={'cell_id': self.pk})
+        ctx['geojson_layers'] = self.get_geojson_layers()
         ctx['tiles_layers'] = self.get_tiles_layers()
         ctx['max_bounds'] = settings.COMBO_MAP_MAX_BOUNDS
         ctx['group_markers'] = self.group_markers
diff --git a/combo/apps/maps/static/js/combo.map.js b/combo/apps/maps/static/js/combo.map.js
index 1283e8d..3c60e4e 100644
--- a/combo/apps/maps/static/js/combo.map.js
+++ b/combo/apps/maps/static/js/combo.map.js
@@ -1,18 +1,13 @@
 $(function() {
     L.Map.include(
       {
-        add_geojson_layer: function(callback) {
+        add_geojson_layer: function(callback, geojson_data) {
           var map = this;
           var $map_widget = $(map.getContainer());
           var cell = $map_widget.parents('div.cell')[0];
-          var geojson_url = $map_widget.data('geojson-url');
-          if (!geojson_url) return;
+          var geojson_url = geojson_data.url;
 
-          if (map.geojson_retrieval) {
-             map.geojson_retrieval.abort();
-          }
-
-          map.geojson_retrieval = $.getJSON(geojson_url, function(data) {
+          $.getJSON(geojson_url, function(data) {
               var geo_json = L.geoJson(data, {
                   onEachFeature: function(feature, layer) {
                       $(cell).trigger('combo:map-feature-prepare', {'feature': feature, 'layer': layer});
@@ -63,38 +58,18 @@ $(function() {
                       return L.marker(latlng, {icon: marker});
                   }
               });
-              if (map.geo_json) map.geo_json.remove();
-              map.geo_json = geo_json;
               if ($map_widget.data('group-markers')) {
-                  if (! map.clustered_markers) {
-                    map.clustered_markers = L.markerClusterGroup({showCoverageOnHover: false,
-                                          zoomToBoundsOnClick: true,
-                                          removeOutsideVisibleBounds: true,
-                                          iconCreateFunction: function (cluster) {
-                                              var icon_size = 60;
-                                              var childCount = cluster.getChildCount();
-                                              var icon_html = '<div><span>' + childCount + '</span></div>';
-                                              var c = ' marker-cluster-';
-                                              if (childCount < 10) {
-                                                  c += 'small';
-                                              } else if (childCount < 100) {
-                                                  c += 'medium';
-                                              } else {
-                                                  c += 'large';
-                                              }
-                                              return new L.DivIcon({html: icon_html, className: 'marker-cluster' + c, iconSize: new L.Point(icon_size, icon_size)});
-                                              }});
-                    map.addLayer(map.clustered_markers);
+                  if (map.geojson_layers[geojson_data.slug]) {
+                      map.clustered_markers.removeLayer(map.geojson_layers[geojson_data.slug]);
                   }
-                  map.clustered_markers.eachLayer(
-                    function(layer) {
-                       map.clustered_markers.removeLayer(layer);
-                    }
-                  );
                   map.clustered_markers.addLayer(geo_json);
               } else {
+                  if (map.geojson_layers[geojson_data.slug]) {
+                      map.geojson_layers[geojson_data.slug].remove();
+                  }
                   geo_json.addTo(map);
               }
+              map.geojson_layers[geojson_data.slug] = geo_json;
               if (callback) {
                   callback(geo_json);
               }
@@ -123,7 +98,6 @@ $(function() {
         if (!isNaN(min_zoom)) map_options.minZoom = min_zoom;
         map_options.zoomControl = false;
         var latlng = [$map_widget.data('init-lat'), $map_widget.data('init-lng')];
-        var geojson_url = $map_widget.data('geojson-url');
         if ($map_widget.data('max-bounds-lat1')) {
           map_options.maxBounds = L.latLngBounds(
                   L.latLng($map_widget.data('max-bounds-lat1'), $map_widget.data('max-bounds-lng1')),
@@ -131,6 +105,29 @@ $(function() {
         }
         map_options.gestureHandling = true;
         var map = L.map($map_widget[0], map_options);
+        if ($map_widget.data('group-markers')) {
+            map.clustered_markers = L.markerClusterGroup({
+                showCoverageOnHover: false,
+                zoomToBoundsOnClick: true,
+                removeOutsideVisibleBounds: true,
+                iconCreateFunction: function (cluster) {
+                    var icon_size = 60;
+                    var childCount = cluster.getChildCount();
+                    var icon_html = '<div><span>' + childCount + '</span></div>';
+                    var c = ' marker-cluster-';
+                    if (childCount < 10) {
+                        c += 'small';
+                    } else if (childCount < 100) {
+                        c += 'medium';
+                    } else {
+                        c += 'large';
+                    }
+                    return new L.DivIcon({html: icon_html, className: 'marker-cluster' + c, iconSize: new L.Point(icon_size, icon_size)});
+                }
+            });
+            map.addLayer(map.clustered_markers);
+        }
+        map.geojson_layers = Object();
         if ($map_widget.data('draggable') === false) {
           map.dragging.disable();
         }
@@ -185,15 +182,28 @@ $(function() {
                 }
             ).addTo(map);
         });
-        if (geojson_url) {
-            map.add_geojson_layer(function(geo_json) {
-                var bounds = geo_json.getBounds();
-                if (bounds.isValid()) {
-                    if (init_state == 'fit-markers') {
-                        map.fitBounds(bounds);
+        map.bounds = null;
+        map.geojson_layers_loaded = 0;
+        var geojson_layers = window['geojson_'+map_id];
+        if (geojson_layers.length) {
+            $.each(geojson_layers, function(idx, geojson_data) {
+                map.add_geojson_layer(function(geo_json) {
+                    var bounds = geo_json.getBounds();
+                    if (bounds.isValid()) {
+                        if (!map.bounds) {
+                            map.bounds = L.latLngBounds(bounds);
+                        } else {
+                            map.bounds.extend(bounds);
+                        }
+                        if (init_state == 'fit-markers') {
+                            map.fitBounds(map.bounds);
+                        }
                     }
+                }, geojson_data);
+                map.geojson_layers_loaded += 1;
+                if (map.geojson_layers_loaded == geojson_layers.length) {
+                    $(cell).trigger('combo:map-ready');
                 }
-                $(cell).trigger('combo:map-ready');
             });
         } else {
             $(cell).trigger('combo:map-ready');
diff --git a/combo/apps/maps/templates/maps/map_cell.html b/combo/apps/maps/templates/maps/map_cell.html
index d16af41..76e154d 100644
--- a/combo/apps/maps/templates/maps/map_cell.html
+++ b/combo/apps/maps/templates/maps/map_cell.html
@@ -5,7 +5,7 @@
 <div class="combo-cell-map" data-init-state="{{ initial_state }}"
         data-init-zoom="{{ initial_zoom }}" data-min-zoom="{{ min_zoom }}"
         data-max-zoom="{{ max_zoom }}" data-init-lat="{{ init_lat }}"
-        data-init-lng="{{ init_lng }}" data-geojson-url="{{ geojson_url }}"
+        data-init-lng="{{ init_lng }}"
         data-include-geoloc-button="true"
         {% if group_markers %}data-group-markers="1"{% endif %}
         data-marker-behaviour-onclick="{{ cell.marker_behaviour_onclick }}"
@@ -27,6 +27,13 @@
       opacity: {{ layer.opacity|as_json|safe }}
     });
   {% endfor %}
+  var geojson_{{ cell.pk }} = [];
+  {% for layer in geojson_layers %}
+  geojson_{{ cell.pk }}.push({
+    url: '{{ layer.url }}',
+    slug: '{{ layer.slug }}'
+  });
+  {% endfor %}
 </script>
 </div>
 {% endblock %}
diff --git a/combo/apps/maps/urls.py b/combo/apps/maps/urls.py
index a24d083..68a3b2f 100644
--- a/combo/apps/maps/urls.py
+++ b/combo/apps/maps/urls.py
@@ -43,6 +43,6 @@ maps_manager_urls = [
 urlpatterns = [
     url(r'^manage/maps/', decorated_includes(manager_required,
         include(maps_manager_urls))),
-    url(r'^ajax/mapcell/geojson/(?P<cell_id>\w+)/$', GeojsonView.as_view(),
+    url(r'^ajax/mapcell/geojson/(?P<cell_id>\d+)/(?P<layer_slug>[\w-]+)/$', GeojsonView.as_view(),
         name='mapcell-geojson'),
 ]
diff --git a/combo/apps/maps/views.py b/combo/apps/maps/views.py
index 7a26078..36b3e37 100644
--- a/combo/apps/maps/views.py
+++ b/combo/apps/maps/views.py
@@ -16,8 +16,9 @@
 
 import json
 
+from django.http import HttpResponse, HttpResponseForbidden
+from django.shortcuts import get_object_or_404
 from django.views.generic.base import View
-from django.http import HttpResponse, Http404, HttpResponseForbidden
 
 from .models import Map
 
@@ -25,12 +26,15 @@ from .models import Map
 class GeojsonView(View):
 
     def get(self, request, *args, **kwargs):
-        try:
-            cell = Map.objects.get(pk=kwargs['cell_id'])
-        except Map.DoesNotExist:
-            raise Http404()
-        if cell.page.is_visible(request.user) and cell.is_visible(user=request.user):
-            geojson = cell.get_geojson(request)
-            content_type = 'application/json'
-            return HttpResponse(json.dumps(geojson), content_type=content_type)
-        return HttpResponseForbidden()
+        cell = get_object_or_404(
+            Map,
+            pk=kwargs['cell_id'])
+        layer = get_object_or_404(
+            cell.layers.all(),
+            kind='geojson',
+            slug=kwargs['layer_slug'])
+        if not cell.page.is_visible(request.user) or not cell.is_visible(user=request.user):
+            return HttpResponseForbidden()
+        geojson = layer.get_geojson(request)
+        content_type = 'application/json'
+        return HttpResponse(json.dumps(geojson), content_type=content_type)
diff --git a/tests/test_maps_cells.py b/tests/test_maps_cells.py
index 16b4949..c66d13e 100644
--- a/tests/test_maps_cells.py
+++ b/tests/test_maps_cells.py
@@ -129,15 +129,17 @@ def test_cell_disabled():
     MapLayer.objects.all().delete()
     assert Map.is_enabled() is False
 
+
 def test_cell_enabled(layer):
     assert Map.is_enabled() is True
 
+
 def test_cell_rendering(app, layer, tiles_layer):
     page = Page(title='xxx', slug='test_map_cell', template_name='standard')
     page.save()
     cell = Map(page=page, placeholder='content', order=0, title='Map with points')
     cell.save()
-    options = MapLayerOptions.objects.create(map_cell=cell, map_layer=layer)
+    MapLayerOptions.objects.create(map_cell=cell, map_layer=layer)
     context = {'request': RequestFactory().get('/')}
     rendered = cell.render(context)
     assert 'data-init-zoom="13"' in rendered
@@ -145,7 +147,7 @@ def test_cell_rendering(app, layer, tiles_layer):
     assert 'data-max-zoom="19"' in rendered
     assert 'data-init-lat="48.83369263315934"' in rendered
     assert 'data-init-lng="2.3233688436448574"' in rendered
-    assert 'data-geojson-url="/ajax/mapcell/geojson/1/"' in rendered
+    assert '/ajax/mapcell/geojson/1/%s/' % layer.slug in rendered
     assert 'data-group-markers="1"' not in rendered
     resp = app.get('/test_map_cell/')
     assert 'xstatic/leaflet.js' in resp.text
@@ -214,36 +216,38 @@ def test_cell_tiles_layers(tiles_layer):
     }]
 
 
+def test_get_geojson_not_found(app, layer):
+    page = Page.objects.create(title='xxx', slug='new', template_name='standard')
+    cell = Map.objects.create(page=page, placeholder='content', order=0, title='Map with points')
+    MapLayerOptions.objects.create(map_cell=cell, map_layer=layer)
+
+    app.get(reverse('mapcell-geojson', kwargs={'cell_id': 0, 'layer_slug': layer.slug}), status=404)
+    app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.pk, 'layer_slug': 'foo'}), status=404)
+
+
 def test_get_geojson_on_non_public_page(app, layer):
-    page = Page(title='xxx', slug='new', template_name='standard',
-                public=False)
-    page.save()
-    cell = Map(page=page, placeholder='content', order=0,
-                   title='Map with points')
-    cell.save()
+    page = Page.objects.create(title='xxx', slug='new', template_name='standard', public=False)
+    cell = Map.objects.create(page=page, placeholder='content', order=0, title='Map with points')
     MapLayerOptions.objects.create(map_cell=cell, map_layer=layer)
-    app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}), status=403)
+    app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id, 'layer_slug': layer.slug}), status=403)
+
 
 def test_get_geojson_on_non_publik_cell(app, layer):
-    page = Page(title='xxx', slug='new', template_name='standard')
-    page.save()
-    cell = Map(page=page, placeholder='content', order=0, public=False,
-                   title='Map with points')
-    cell.save()
+    page = Page.objects.create(title='xxx', slug='new', template_name='standard')
+    cell = Map.objects.create(page=page, placeholder='content', order=0, title='Map with points', public=False)
     MapLayerOptions.objects.create(map_cell=cell, map_layer=layer)
-    app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}), status=403)
+    app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id, 'layer_slug': layer.slug}), status=403)
+
 
 def test_geojson_on_restricted_cell(app, layer, user):
-    page = Page(title='xxx', slug='new', template_name='standard')
-    page.save()
+    page = Page.objects.create(title='xxx', slug='new', template_name='standard')
     group = Group.objects.create(name='map tester')
     cell = Map(page=page, placeholder='content', order=0, public=False)
-    cell.title = 'Map with points'
-    cell.save()
+    cell = Map.objects.create(page=page, placeholder='content', order=0, title='Map with points', public=False)
     MapLayerOptions.objects.create(map_cell=cell, map_layer=layer)
     cell.groups.add(group)
     login(app)
-    app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}), status=403)
+    app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id, 'layer_slug': layer.slug}), status=403)
     user.groups.add(group)
     user.save()
 
@@ -252,7 +256,8 @@ def test_geojson_on_restricted_cell(app, layer, user):
                 content=SAMPLE_GEOJSON_CONTENT,
                 json=lambda: json.loads(SAMPLE_GEOJSON_CONTENT),
                 status_code=200)
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}))
+        app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id, 'layer_slug': layer.slug}))
+
 
 def test_get_geojson(app, layer, user):
     page = Page(title='xxx', slug='new', template_name='standard')
@@ -264,21 +269,23 @@ def test_get_geojson(app, layer, user):
     layer.save()
     MapLayerOptions.objects.create(map_cell=cell, map_layer=layer)
 
+    geojson_url = reverse('mapcell-geojson', kwargs={'cell_id': cell.id, 'layer_slug': layer.slug})
+
     # check cache duration
     with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as requests_get:
         requests_get.return_value = mock.Mock(
                 content=SAMPLE_GEOJSON_CONTENT,
                 json=lambda: json.loads(SAMPLE_GEOJSON_CONTENT),
                 status_code=200)
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}))
+        resp = app.get(geojson_url)
         assert len(json.loads(resp.text)['features']) == 2
         assert requests_get.call_count == 1
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}))
-        assert requests_get.call_count == 1 # cache was used
+        resp = app.get(geojson_url)
+        assert requests_get.call_count == 1  # cache was used
         layer.cache_duration = 0
         layer.save()
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}))
-        assert requests_get.call_count == 2 # cache was not used
+        resp = app.get(geojson_url)
+        assert requests_get.call_count == 2  # cache was not used
 
     # check user params
     layer.geojson_url = 'http://example.org/geojson?t2'
@@ -288,7 +295,7 @@ def test_get_geojson(app, layer, user):
                 content=SAMPLE_GEOJSON_CONTENT,
                 json=lambda: json.loads(SAMPLE_GEOJSON_CONTENT),
                 status_code=200)
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}))
+        resp = app.get(geojson_url)
         assert 'orig=combo' in requests_get.call_args[0][1]
         assert 'email=&' in requests_get.call_args[0][1]
 
@@ -300,7 +307,7 @@ def test_get_geojson(app, layer, user):
                 content=SAMPLE_GEOJSON_CONTENT,
                 json=lambda: json.loads(SAMPLE_GEOJSON_CONTENT),
                 status_code=200)
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}))
+        resp = app.get(geojson_url)
         assert 'orig=combo' in requests_get.call_args[0][1]
         assert 'email=admin%40localhost&' in requests_get.call_args[0][1]
 
@@ -312,9 +319,9 @@ def test_get_geojson(app, layer, user):
                 content=SAMPLE_GEOJSON_CONTENT,
                 json=lambda: json.loads(SAMPLE_GEOJSON_CONTENT),
                 status_code=200)
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}))
+        resp = app.get(geojson_url)
         assert 'orig=combo' in requests_get.call_args[0][1]
-        assert not 'email=admin%40localhost&' in requests_get.call_args[0][1]
+        assert 'email=admin%40localhost&' not in requests_get.call_args[0][1]
 
     # check query on geojson
     layer.geojson_url = 'http://example.org/geojson?t5'
@@ -325,17 +332,17 @@ def test_get_geojson(app, layer, user):
                 content=SAMPLE_GEOJSON_CONTENT,
                 json=lambda: json.loads(SAMPLE_GEOJSON_CONTENT),
                 status_code=200)
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?q=bar')
+        resp = app.get(geojson_url + '?q=bar')
         assert len(json.loads(resp.text)['features']) == 1
         assert 'orig=combo' in requests_get.call_args[0][1]
-        assert not 'email=admin%40localhost&' in requests_get.call_args[0][1]
+        assert 'email=admin%40localhost&' not in requests_get.call_args[0][1]
 
         # query against layer name
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?q=bicycle')
-        assert len(json.loads(resp.text)['features']) == 0
+        resp = app.get(geojson_url + '?q=bicycle')
+        assert len(json.loads(resp.text)['features']) == 2
 
         # query against subproperty
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?q=whatever')
+        resp = app.get(geojson_url + '?q=whatever')
         assert len(json.loads(resp.text)['features']) == 1
 
     # check distance query on geojson
@@ -347,13 +354,13 @@ def test_get_geojson(app, layer, user):
                 content=SAMPLE_GEOJSON_CONTENT,
                 json=lambda: json.loads(SAMPLE_GEOJSON_CONTENT),
                 status_code=200)
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?lng=2.54&lat=48.84&distance=2000')
+        resp = app.get(geojson_url + '?lng=2.54&lat=48.84&distance=2000')
         assert len(json.loads(resp.text)['features']) == 2
 
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?lng=2.54&lat=48.84&distance=1000')
+        resp = app.get(geojson_url + '?lng=2.54&lat=48.84&distance=1000')
         assert len(json.loads(resp.text)['features']) == 1
 
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?lng=2.54&lat=48.84&distance=100')
+        resp = app.get(geojson_url + '?lng=2.54&lat=48.84&distance=100')
         assert len(json.loads(resp.text)['features']) == 0
 
     # check on multiple words
@@ -362,10 +369,10 @@ def test_get_geojson(app, layer, user):
                 content=SAMPLE_GEOJSON_CONTENT,
                 json=lambda: json.loads(SAMPLE_GEOJSON_CONTENT),
                 status_code=200)
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?q=bar baz')
+        resp = app.get(geojson_url + '?q=bar baz')
         assert len(json.loads(resp.text)['features']) == 1
 
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?q=quux baz')
+        resp = app.get(geojson_url + '?q=quux baz')
         assert len(json.loads(resp.text)['features']) == 0
 
     # add a second layer
@@ -377,26 +384,34 @@ def test_get_geojson(app, layer, user):
     layer2.icon_colour = '0000FF'
     layer2.save()
     MapLayerOptions.objects.create(map_cell=cell, map_layer=layer2)
+    geojson_url2 = reverse('mapcell-geojson', kwargs={'cell_id': cell.id, 'layer_slug': layer2.slug})
 
     with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as requests_get:
         requests_get.return_value = mock.Mock(
                 content=SAMPLE_GEOJSON_CONTENT,
                 json=lambda: json.loads(SAMPLE_GEOJSON_CONTENT),
                 status_code=200)
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?q=bar')
-        assert len(json.loads(resp.text)['features']) == 2
-
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?q=xyz')
+        resp = app.get(geojson_url + '?q=bar')
+        assert len(json.loads(resp.text)['features']) == 1
+        resp = app.get(geojson_url2 + '?q=bar')
+        assert len(json.loads(resp.text)['features']) == 1
+        resp = app.get(geojson_url + '?q=xyz')
+        assert len(json.loads(resp.text)['features']) == 0
+        resp = app.get(geojson_url2 + '?q=xyz')
         assert len(json.loads(resp.text)['features']) == 0
-
         # query against layer name, it should get results
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?q=bicycle')
+        resp = app.get(geojson_url + '?q=bicycle')
         assert len(json.loads(resp.text)['features']) == 2
-
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?q=bar bicycle')
+        resp = app.get(geojson_url2 + '?q=bicycle')
+        assert len(json.loads(resp.text)['features']) == 0
+        resp = app.get(geojson_url + '?q=bar bicycle')
         assert len(json.loads(resp.text)['features']) == 1
+        resp = app.get(geojson_url2 + '?q=bar bicycle')
+        assert len(json.loads(resp.text)['features']) == 0
 
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?q=quux bicycle')
+        resp = app.get(geojson_url + '?q=quux bicycle')
+        assert len(json.loads(resp.text)['features']) == 0
+        resp = app.get(geojson_url2 + '?q=quux bicycle')
         assert len(json.loads(resp.text)['features']) == 0
 
 
@@ -416,7 +431,7 @@ def test_get_geojson_properties(app, layer, user):
                 content=SAMPLE_GEOJSON_CONTENT,
                 json=lambda: json.loads(SAMPLE_GEOJSON_CONTENT),
                 status_code=200)
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}))
+        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id, 'layer_slug': layer.slug}))
         features = json.loads(resp.text)['features']
         assert 'name' in features[0]['properties']
         assert 'extra' in features[0]['properties']
@@ -430,7 +445,7 @@ def test_get_geojson_properties(app, layer, user):
                 content=SAMPLE_GEOJSON_CONTENT,
                 json=lambda: json.loads(SAMPLE_GEOJSON_CONTENT),
                 status_code=200)
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}))
+        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id, 'layer_slug': layer.slug}))
         features = json.loads(resp.text)['features']
         assert 'name' in features[0]['properties']
         assert 'extra' not in features[0]['properties']
@@ -444,7 +459,7 @@ def test_get_geojson_properties(app, layer, user):
                 content=SAMPLE_WCS_GEOJSON_CONTENT,
                 json=lambda: json.loads(SAMPLE_WCS_GEOJSON_CONTENT),
                 status_code=200)
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}))
+        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id, 'layer_slug': layer.slug}))
         features = json.loads(resp.text)['features']
         assert len(features[0]['properties']['display_fields']) == 2
         assert features[0]['properties']['layer']['properties'] == []
@@ -457,7 +472,7 @@ def test_get_geojson_properties(app, layer, user):
                 content=SAMPLE_WCS_GEOJSON_CONTENT,
                 json=lambda: json.loads(SAMPLE_WCS_GEOJSON_CONTENT),
                 status_code=200)
-        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}))
+        resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id, 'layer_slug': layer.slug}))
         features = json.loads(resp.text)['features']
         assert len(features[0]['properties']['display_fields']) == 1
         assert features[0]['properties']['layer']['properties'] == ['id']
diff --git a/tests/test_maps_manager.py b/tests/test_maps_manager.py
index 769c0fe..f8d4db3 100644
--- a/tests/test_maps_manager.py
+++ b/tests/test_maps_manager.py
@@ -186,7 +186,7 @@ def test_download_geojson(mock_request, app, admin_user, layer):
                         'properties': {'property': 'property value'}}]
     mocked_response.ok.return_value = True
     mock_request.return_value = mocked_response
-    geojson = layer.get_geojson(mock_request)
+    geojson = layer.get_geojson(mock_request)['features']
     assert len(geojson) > 0
     for item in geojson:
         assert item['type'] == 'Feature'
@@ -207,7 +207,7 @@ def test_download_geojson(mock_request, app, admin_user, layer):
     }
     mocked_response.ok.return_value = True
     mock_request.return_value = mocked_response
-    geojson = layer.get_geojson(mock_request)
+    geojson = layer.get_geojson(mock_request)['features']
     assert len(geojson) > 0
     for item in geojson:
         assert item['geometry']['type'] == 'Point'
-- 
2.20.1

