combo/tests/test_maps_cells.py

473 lines
18 KiB
Python

# -*- coding: utf-8 -*-
import json
import mock
import pytest
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth.models import Group
from django.core.urlresolvers import reverse
from django.test.client import RequestFactory
from django.utils.html import escape
from combo.data.models import Page
from combo.apps.maps.models import MapLayer, Map, MapLayerOptions
from .test_manager import login
pytestmark = pytest.mark.django_db
SAMPLE_GEOJSON_CONTENT = '''{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "Foo",
"extra": "Baz"
},
"geometry": {
"type": "Point",
"coordinates": [
2.548828125,
48.83579746243093
]
}
},
{
"type": "Feature",
"properties": {
"name": "Bar",
"extra": "Baz",
"subdict": {
"plop": "Whatever"
}
},
"geometry": {
"type": "Point",
"coordinates": [
2.558828125,
48.84579746243093
]
}
}
]
}'''
SAMPLE_WCS_GEOJSON_CONTENT = '''{
"type": "FeatureCollection",
"features": [
{
"type" : "Feature",
"geometry" : {
"type" : "Point",
"coordinates" : [
6.175303,
48.684512
]
},
"properties" : {
"name" : "Test - n°144-4",
"view_label" : "Voir",
"status_name" : "Foo",
"display_fields" : [
{
"varname" : "id",
"html_value" : "144-4",
"value" : "144-4",
"label" : "Numéro"
},
{
"varname" : null,
"html_value" : "toto",
"value" : "toto",
"label" : "toto"
}
]
}
}
]
}'''
@pytest.fixture
def user():
try:
user = User.objects.get(username='admin')
except User.DoesNotExist:
user = User.objects.create_user('admin', email='admin@localhost', password='admin')
return user
@pytest.fixture
def layer():
try:
layer = MapLayer.objects.get()
except MapLayer.DoesNotExist:
layer = MapLayer()
layer.label = 'bicycles'
layer.geojson_url = 'http://example.org/geojson'
layer.marker_colour = 'FF0000'
layer.icon = 'fa-bicycle'
layer.icon_colour = '0000FF'
layer.save()
return layer
@pytest.fixture
def tiles_layer():
return MapLayer.objects.create(
label='Test2',
kind='tiles',
tiles_template_url='http://somedomain.com/blabla/{z}/{x}/{y}{r}.png',
tiles_attribution='Foo bar',
tiles_default=True,
)
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)
context = {'request': RequestFactory().get('/')}
rendered = cell.render(context)
assert 'data-init-zoom="13"' in rendered
assert 'data-min-zoom="0"' in rendered
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 'data-group-markers="1"' not in rendered
resp = app.get('/test_map_cell/')
assert 'xstatic/leaflet.js' in resp.text
assert 'js/combo.map.js' in resp.text
assert 'xstatic/leaflet.css' in resp.text
assert 'css/combo.map.css' in resp.text
cell.group_markers = True
cell.save()
rendered = cell.render(context)
assert 'data-group-markers="1"' in rendered
def test_cell_tiles_layers(tiles_layer):
page = Page.objects.create(title='xxx', slug='test_map_cell', template_name='standard')
cell = Map.objects.create(page=page, placeholder='content', order=0, title='Map with points')
# no tiles layer for this map, take default tiles layers, tiles_layer
assert cell.get_tiles_layers() == [{
'tile_urltemplate': tiles_layer.tiles_template_url,
'map_attribution': tiles_layer.tiles_attribution,
'opacity': 1,
}]
# tiles_layer is not set as default, fallback on settings
tiles_layer.tiles_default = False
tiles_layer.save()
assert cell.get_tiles_layers() == [{
'tile_urltemplate': settings.COMBO_MAP_TILE_URLTEMPLATE,
'map_attribution': settings.COMBO_MAP_ATTRIBUTION,
'opacity': 1,
}]
# add a tile layer to the map, with opacity 1
options = MapLayerOptions.objects.create(map_cell=cell, map_layer=tiles_layer, opacity=1)
assert cell.get_tiles_layers() == [{
'tile_urltemplate': tiles_layer.tiles_template_url,
'map_attribution': tiles_layer.tiles_attribution,
'opacity': 1,
}]
# opacity is less than 1 => add default tiles layer, defined in settings
options.opacity = 0.5
options.save()
assert cell.get_tiles_layers() == [{
'tile_urltemplate': settings.COMBO_MAP_TILE_URLTEMPLATE,
'map_attribution': settings.COMBO_MAP_ATTRIBUTION,
'opacity': 1,
}, {
'tile_urltemplate': tiles_layer.tiles_template_url,
'map_attribution': tiles_layer.tiles_attribution,
'opacity': 0.5,
}]
# set tiles_layer as default => add tiles_layer
tiles_layer.tiles_default = True
tiles_layer.save()
assert cell.get_tiles_layers() == [{
'tile_urltemplate': tiles_layer.tiles_template_url,
'map_attribution': tiles_layer.tiles_attribution,
'opacity': 1,
}, {
'tile_urltemplate': tiles_layer.tiles_template_url,
'map_attribution': tiles_layer.tiles_attribution,
'opacity': 0.5,
}]
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()
MapLayerOptions.objects.create(map_cell=cell, map_layer=layer)
app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}), 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()
MapLayerOptions.objects.create(map_cell=cell, map_layer=layer)
app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}), status=403)
def test_geojson_on_restricted_cell(app, layer, user):
page = Page(title='xxx', slug='new', template_name='standard')
page.save()
group = Group.objects.create(name='map tester')
cell = Map(page=page, placeholder='content', order=0, public=False)
cell.title = 'Map with points'
cell.save()
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)
user.groups.add(group)
user.save()
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}))
def test_get_geojson(app, layer, user):
page = Page(title='xxx', slug='new', template_name='standard')
page.save()
cell = Map(page=page, placeholder='content', order=0, public=True)
cell.title = 'Map'
cell.save()
layer.geojson_url = 'http://example.org/geojson?t1'
layer.save()
MapLayerOptions.objects.create(map_cell=cell, map_layer=layer)
# 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}))
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
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
# check user params
layer.geojson_url = 'http://example.org/geojson?t2'
layer.save()
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}))
assert 'orig=combo' in requests_get.call_args[0][1]
assert 'email=&' in requests_get.call_args[0][1]
login(app)
layer.geojson_url = 'http://example.org/geojson?t3'
layer.save()
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}))
assert 'orig=combo' in requests_get.call_args[0][1]
assert 'email=admin%40localhost&' in requests_get.call_args[0][1]
layer.geojson_url = 'http://example.org/geojson?t4'
layer.include_user_identifier = False
layer.save()
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}))
assert 'orig=combo' in requests_get.call_args[0][1]
assert not 'email=admin%40localhost&' in requests_get.call_args[0][1]
# check query on geojson
layer.geojson_url = 'http://example.org/geojson?t5'
layer.include_user_identifier = False
layer.save()
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']) == 1
assert 'orig=combo' in requests_get.call_args[0][1]
assert not 'email=admin%40localhost&' 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
# query against subproperty
resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?q=whatever')
assert len(json.loads(resp.text)['features']) == 1
# check distance query on geojson
layer.geojson_url = 'http://example.org/geojson?t6'
layer.include_user_identifier = False
layer.save()
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}) + '?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')
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')
assert len(json.loads(resp.text)['features']) == 0
# check on multiple words
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 baz')
assert len(json.loads(resp.text)['features']) == 1
resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?q=quux baz')
assert len(json.loads(resp.text)['features']) == 0
# add a second layer
layer2 = MapLayer()
layer2.label = 'xxx'
layer2.geojson_url = 'http://example.org/geojson'
layer2.marker_colour = 'FF0000'
layer2.icon = 'fa-bicycle'
layer2.icon_colour = '0000FF'
layer2.save()
MapLayerOptions.objects.create(map_cell=cell, map_layer=layer2)
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')
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')
assert len(json.loads(resp.text)['features']) == 2
resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?q=bar bicycle')
assert len(json.loads(resp.text)['features']) == 1
resp = app.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?q=quux bicycle')
assert len(json.loads(resp.text)['features']) == 0
def test_get_geojson_properties(app, layer, user):
page = Page(title='xxx', slug='new', template_name='standard')
page.save()
cell = Map(page=page, placeholder='content', order=0, public=True)
cell.title = 'Map'
cell.save()
layer.save()
MapLayerOptions.objects.create(map_cell=cell, map_layer=layer)
with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as requests_get:
layer.geojson_url = 'http://example.org/geojson?t1'
layer.save()
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}))
features = json.loads(resp.text)['features']
assert 'name' in features[0]['properties']
assert 'extra' in features[0]['properties']
assert features[0]['properties']['layer']['properties'] == []
with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as requests_get:
layer.geojson_url = 'http://example.org/geojson?t2'
layer.properties = 'name, hop'
layer.save()
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}))
features = json.loads(resp.text)['features']
assert 'name' in features[0]['properties']
assert 'extra' not in features[0]['properties']
assert features[0]['properties']['layer']['properties'] == ['name', 'hop']
with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as requests_get:
layer.geojson_url = 'http://example.org/geojson?t3'
layer.properties = ''
layer.save()
requests_get.return_value = mock.Mock(
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}))
features = json.loads(resp.text)['features']
assert len(features[0]['properties']['display_fields']) == 2
assert features[0]['properties']['layer']['properties'] == []
with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as requests_get:
layer.geojson_url = 'http://example.org/geojson?t4'
layer.properties = 'id'
layer.save()
requests_get.return_value = mock.Mock(
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}))
features = json.loads(resp.text)['features']
assert len(features[0]['properties']['display_fields']) == 1
assert features[0]['properties']['layer']['properties'] == ['id']
def test_duplicate(layer):
page = Page.objects.create(title='xxx', slug='new', template_name='standard')
cell = Map.objects.create(page=page, placeholder='content', order=0, public=True, title='Map')
MapLayerOptions.objects.create(map_cell=cell, map_layer=layer)
new_cell = cell.duplicate()
assert list(new_cell.layers.all()) == [layer]