Merge leaflet_storage tests
This commit is contained in:
parent
65e939c4ee
commit
53c738abaf
19 changed files with 1519 additions and 2 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -53,6 +53,7 @@ nosetests.xml
|
|||
coverage.xml
|
||||
*,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,5 +1,5 @@
|
|||
test:
|
||||
py.test
|
||||
py.test -xv
|
||||
develop:
|
||||
python setup.py develop
|
||||
compilemessages:
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
from .test_views import *
|
96
umap/tests/base.py
Normal file
96
umap/tests/base.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
import json
|
||||
|
||||
import factory
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.urls import reverse
|
||||
|
||||
from umap.forms import DEFAULT_CENTER
|
||||
from umap.models import DataLayer, Licence, Map, TileLayer
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class LicenceFactory(factory.DjangoModelFactory):
|
||||
name = "WTFPL"
|
||||
|
||||
class Meta:
|
||||
model = Licence
|
||||
|
||||
|
||||
class TileLayerFactory(factory.DjangoModelFactory):
|
||||
name = "Test zoom layer"
|
||||
url_template = "http://{s}.test.org/{z}/{x}/{y}.png"
|
||||
attribution = "Test layer attribution"
|
||||
|
||||
class Meta:
|
||||
model = TileLayer
|
||||
|
||||
|
||||
class UserFactory(factory.DjangoModelFactory):
|
||||
username = 'Joe'
|
||||
email = factory.LazyAttribute(
|
||||
lambda a: '{0}@example.com'.format(a.username).lower())
|
||||
password = factory.PostGenerationMethodCall('set_password', '123123')
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
|
||||
|
||||
class MapFactory(factory.DjangoModelFactory):
|
||||
name = "test map"
|
||||
slug = "test-map"
|
||||
center = DEFAULT_CENTER
|
||||
settings = {
|
||||
'geometry': {
|
||||
'coordinates': [13.447265624999998, 48.94415123418794],
|
||||
'type': 'Point'
|
||||
},
|
||||
'properties': {
|
||||
'datalayersControl': True,
|
||||
'description': 'Which is just the Danube, at the end',
|
||||
'displayCaptionOnLoad': False,
|
||||
'displayDataBrowserOnLoad': False,
|
||||
'displayPopupFooter': False,
|
||||
'licence': '',
|
||||
'miniMap': False,
|
||||
'moreControl': True,
|
||||
'name': 'Cruising on the Donau',
|
||||
'scaleControl': True,
|
||||
'tilelayer': {
|
||||
'attribution': u'\xa9 OSM Contributors',
|
||||
'maxZoom': 18,
|
||||
'minZoom': 0,
|
||||
'url_template': 'http://{s}.osm.fr/{z}/{x}/{y}.png'
|
||||
},
|
||||
'tilelayersControl': True,
|
||||
'zoom': 7,
|
||||
'zoomControl': True
|
||||
},
|
||||
'type': 'Feature'
|
||||
}
|
||||
|
||||
licence = factory.SubFactory(LicenceFactory)
|
||||
owner = factory.SubFactory(UserFactory)
|
||||
|
||||
class Meta:
|
||||
model = Map
|
||||
|
||||
|
||||
class DataLayerFactory(factory.DjangoModelFactory):
|
||||
map = factory.SubFactory(MapFactory)
|
||||
name = "test datalayer"
|
||||
description = "test description"
|
||||
display_on_load = True
|
||||
geojson = factory.django.FileField(data="""{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[13.68896484375,48.55297816440071]},"properties":{"_storage_options":{"color":"DarkCyan","iconClass":"Ball"},"name":"Here","description":"Da place anonymous again 755"}}],"_storage":{"displayOnLoad":true,"name":"Donau","id":926}}""") # noqa
|
||||
|
||||
class Meta:
|
||||
model = DataLayer
|
||||
|
||||
|
||||
def login_required(response):
|
||||
assert response.status_code == 200
|
||||
j = json.loads(response.content.decode())
|
||||
assert 'login_required' in j
|
||||
redirect_url = reverse('login')
|
||||
assert j['login_required'] == redirect_url
|
||||
return True
|
64
umap/tests/conftest.py
Normal file
64
umap/tests/conftest.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
import shutil
|
||||
import tempfile
|
||||
|
||||
import pytest
|
||||
from django.core.signing import get_cookie_signer
|
||||
|
||||
from .base import (DataLayerFactory, LicenceFactory, MapFactory,
|
||||
TileLayerFactory, UserFactory)
|
||||
|
||||
TMP_ROOT = tempfile.mkdtemp()
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
from django.conf import settings
|
||||
settings.MEDIA_ROOT = TMP_ROOT
|
||||
|
||||
|
||||
def pytest_unconfigure(config):
|
||||
shutil.rmtree(TMP_ROOT, ignore_errors=True)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user():
|
||||
return UserFactory(password="123123")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def licence():
|
||||
return LicenceFactory()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def map(licence, tilelayer):
|
||||
user = UserFactory(username="Gabriel", password="123123")
|
||||
return MapFactory(owner=user, licence=licence)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def anonymap(map):
|
||||
map.owner = None
|
||||
map.save()
|
||||
return map
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def cookieclient(client, anonymap):
|
||||
key, value = anonymap.signed_cookie_elements
|
||||
client.cookies[key] = get_cookie_signer(salt=key).sign(value)
|
||||
return client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def allow_anonymous(settings):
|
||||
settings.LEAFLET_STORAGE_ALLOW_ANONYMOUS = True
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def datalayer(map):
|
||||
return DataLayerFactory(map=map, name="Default Datalayer")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def tilelayer():
|
||||
return TileLayerFactory()
|
2
umap/tests/fixtures/test_upload_data.csv
vendored
Normal file
2
umap/tests/fixtures/test_upload_data.csv
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
Foo,Latitude,geo_Longitude,title,description
|
||||
bar,41.34,122.86,a point somewhere,the description of this point
|
|
17
umap/tests/fixtures/test_upload_data.gpx
vendored
Normal file
17
umap/tests/fixtures/test_upload_data.gpx
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
<gpx
|
||||
version="1.1"
|
||||
creator="GPSBabel - http://www.gpsbabel.org"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.topografix.com/GPX/1/1"
|
||||
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
|
||||
<wpt lat="45.44283" lon="-121.72904"><ele>1374</ele><name>Simple Point</name><desc>Simple description</desc></wpt>
|
||||
<trk>
|
||||
<name>Simple path</name>
|
||||
<desc>Simple description</desc>
|
||||
<trkseg>
|
||||
<trkpt lat="45.4431641" lon="-121.7295456"></trkpt>
|
||||
<trkpt lat="45.4428615" lon="-121.7290800"></trkpt>
|
||||
<trkpt lat="45.4425697" lon="-121.7279085"></trkpt>
|
||||
</trkseg>
|
||||
</trk>
|
||||
</gpx>
|
188
umap/tests/fixtures/test_upload_data.json
vendored
Normal file
188
umap/tests/fixtures/test_upload_data.json
vendored
Normal file
|
@ -0,0 +1,188 @@
|
|||
{
|
||||
"crs": null,
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
-0.1318359375,
|
||||
51.474540439419755
|
||||
]
|
||||
},
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"name": "London",
|
||||
"description": "London description",
|
||||
"color": "Pink"
|
||||
}
|
||||
},
|
||||
{
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
4.350585937499999,
|
||||
51.26878915771344
|
||||
]
|
||||
},
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"name": "Antwerpen",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"geometry": {
|
||||
"type": "LineString",
|
||||
"coordinates": [
|
||||
[
|
||||
2.4005126953125,
|
||||
48.81228985866255
|
||||
],
|
||||
[
|
||||
2.78228759765625,
|
||||
48.89903236496008
|
||||
],
|
||||
[
|
||||
2.845458984375,
|
||||
48.89903236496008
|
||||
],
|
||||
[
|
||||
2.86468505859375,
|
||||
48.96218736991556
|
||||
],
|
||||
[
|
||||
2.9278564453125,
|
||||
48.93693495409401
|
||||
],
|
||||
[
|
||||
2.93060302734375,
|
||||
48.99283383694349
|
||||
],
|
||||
[
|
||||
3.04046630859375,
|
||||
49.01085236926211
|
||||
],
|
||||
[
|
||||
3.0157470703125,
|
||||
48.96038404976431
|
||||
],
|
||||
[
|
||||
3.12286376953125,
|
||||
48.94415123418794
|
||||
],
|
||||
[
|
||||
3.1805419921874996,
|
||||
48.99824008113872
|
||||
],
|
||||
[
|
||||
3.2684326171875,
|
||||
48.95497369808868
|
||||
],
|
||||
[
|
||||
3.53759765625,
|
||||
49.0900564769189
|
||||
],
|
||||
[
|
||||
3.57330322265625,
|
||||
49.057670047140604
|
||||
],
|
||||
[
|
||||
3.72161865234375,
|
||||
49.095452162534826
|
||||
],
|
||||
[
|
||||
3.9578247070312496,
|
||||
49.06486885623368
|
||||
]
|
||||
]
|
||||
},
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"name": "2011"
|
||||
}
|
||||
},
|
||||
{
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
10.04150390625,
|
||||
52.70967533219883
|
||||
],
|
||||
[
|
||||
8.800048828125,
|
||||
51.80182150078305
|
||||
],
|
||||
[
|
||||
11.271972656249998,
|
||||
51.12421275782688
|
||||
],
|
||||
[
|
||||
12.689208984375,
|
||||
52.214338608258196
|
||||
],
|
||||
[
|
||||
10.04150390625,
|
||||
52.70967533219883
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"name": "test"
|
||||
}
|
||||
},
|
||||
{
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
7.327880859374999,
|
||||
50.52041218671901
|
||||
],
|
||||
[
|
||||
6.064453125,
|
||||
49.6462914122132
|
||||
],
|
||||
[
|
||||
7.503662109375,
|
||||
49.54659778073743
|
||||
],
|
||||
[
|
||||
6.8115234375,
|
||||
49.167338606291075
|
||||
],
|
||||
[
|
||||
9.635009765625,
|
||||
48.99463598353408
|
||||
],
|
||||
[
|
||||
10.557861328125,
|
||||
49.937079756975294
|
||||
],
|
||||
[
|
||||
8.4814453125,
|
||||
49.688954878870305
|
||||
],
|
||||
[
|
||||
9.173583984375,
|
||||
51.04830113331224
|
||||
],
|
||||
[
|
||||
7.327880859374999,
|
||||
50.52041218671901
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"name": "test polygon 2"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
33
umap/tests/fixtures/test_upload_data.kml
vendored
Normal file
33
umap/tests/fixtures/test_upload_data.kml
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kml xmlns="http://www.opengis.net/kml/2.2">
|
||||
<Placemark>
|
||||
<name>Simple point</name>
|
||||
<description>Here is a simple description.</description>
|
||||
<Point>
|
||||
<coordinates>-122.0822035425683,37.42228990140251,0</coordinates>
|
||||
</Point>
|
||||
</Placemark>
|
||||
<Placemark>
|
||||
<name>Simple path</name>
|
||||
<description>Simple description</description>
|
||||
<LineString>
|
||||
<coordinates>-112.2550785337791,36.07954952145647,2357 -112.2549277039738,36.08117083492122,2357 -112.2552505069063,36.08260761307279,2357</coordinates>
|
||||
</LineString>
|
||||
</Placemark>
|
||||
<Placemark>
|
||||
<name>Simple polygon</name>
|
||||
<description>A description.</description>
|
||||
<Polygon>
|
||||
<outerBoundaryIs>
|
||||
<LinearRing>
|
||||
<coordinates>
|
||||
-77.05788457660967,38.87253259892824,100
|
||||
-77.05465973756702,38.87291016281703,100
|
||||
-77.05315536854791,38.87053267794386,100
|
||||
-77.05788457660967,38.87253259892824,100
|
||||
</coordinates>
|
||||
</LinearRing>
|
||||
</outerBoundaryIs>
|
||||
</Polygon>
|
||||
</Placemark>
|
||||
</kml>
|
36
umap/tests/fixtures/test_upload_empty_coordinates.json
vendored
Normal file
36
umap/tests/fixtures/test_upload_empty_coordinates.json
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"crs": null,
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": []
|
||||
},
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"name": "London"
|
||||
}
|
||||
},
|
||||
{
|
||||
"geometry": {
|
||||
"type": "LineString",
|
||||
"coordinates": []
|
||||
},
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"name": "2011"
|
||||
}
|
||||
},
|
||||
{
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [[]]
|
||||
},
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"name": "test"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
153
umap/tests/fixtures/test_upload_missing_name.json
vendored
Normal file
153
umap/tests/fixtures/test_upload_missing_name.json
vendored
Normal file
|
@ -0,0 +1,153 @@
|
|||
{
|
||||
"crs": null,
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
-0.1318359375,
|
||||
51.474540439419755
|
||||
]
|
||||
},
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"name": "London"
|
||||
}
|
||||
},
|
||||
{
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
4.350585937499999,
|
||||
51.26878915771344
|
||||
]
|
||||
},
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"noname": "this feature is missing a name",
|
||||
"name": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"geometry": {
|
||||
"type": "LineString",
|
||||
"coordinates": [
|
||||
[
|
||||
2.4005126953125,
|
||||
48.81228985866255
|
||||
],
|
||||
[
|
||||
2.78228759765625,
|
||||
48.89903236496008
|
||||
],
|
||||
[
|
||||
2.845458984375,
|
||||
48.89903236496008
|
||||
],
|
||||
[
|
||||
2.86468505859375,
|
||||
48.96218736991556
|
||||
],
|
||||
[
|
||||
2.9278564453125,
|
||||
48.93693495409401
|
||||
],
|
||||
[
|
||||
2.93060302734375,
|
||||
48.99283383694349
|
||||
],
|
||||
[
|
||||
3.04046630859375,
|
||||
49.01085236926211
|
||||
],
|
||||
[
|
||||
3.0157470703125,
|
||||
48.96038404976431
|
||||
],
|
||||
[
|
||||
3.12286376953125,
|
||||
48.94415123418794
|
||||
],
|
||||
[
|
||||
3.1805419921874996,
|
||||
48.99824008113872
|
||||
],
|
||||
[
|
||||
3.2684326171875,
|
||||
48.95497369808868
|
||||
],
|
||||
[
|
||||
3.53759765625,
|
||||
49.0900564769189
|
||||
],
|
||||
[
|
||||
3.57330322265625,
|
||||
49.057670047140604
|
||||
],
|
||||
[
|
||||
3.72161865234375,
|
||||
49.095452162534826
|
||||
],
|
||||
[
|
||||
3.9578247070312496,
|
||||
49.06486885623368
|
||||
]
|
||||
]
|
||||
},
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"name": "2011"
|
||||
}
|
||||
},
|
||||
{
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
7.327880859374999,
|
||||
50.52041218671901
|
||||
],
|
||||
[
|
||||
6.064453125,
|
||||
49.6462914122132
|
||||
],
|
||||
[
|
||||
7.503662109375,
|
||||
49.54659778073743
|
||||
],
|
||||
[
|
||||
6.8115234375,
|
||||
49.167338606291075
|
||||
],
|
||||
[
|
||||
9.635009765625,
|
||||
48.99463598353408
|
||||
],
|
||||
[
|
||||
10.557861328125,
|
||||
49.937079756975294
|
||||
],
|
||||
[
|
||||
8.4814453125,
|
||||
49.688954878870305
|
||||
],
|
||||
[
|
||||
9.173583984375,
|
||||
51.04830113331224
|
||||
],
|
||||
[
|
||||
7.327880859374999,
|
||||
50.52041218671901
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"name": "test polygon 2"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
51
umap/tests/fixtures/test_upload_non_linear_ring.json
vendored
Normal file
51
umap/tests/fixtures/test_upload_non_linear_ring.json
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"crs": null,
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
7.327880859374999,
|
||||
50.52041218671901
|
||||
],
|
||||
[
|
||||
6.064453125,
|
||||
49.6462914122132
|
||||
],
|
||||
[
|
||||
7.503662109375,
|
||||
49.54659778073743
|
||||
],
|
||||
[
|
||||
6.8115234375,
|
||||
49.167338606291075
|
||||
],
|
||||
[
|
||||
9.635009765625,
|
||||
48.99463598353408
|
||||
],
|
||||
[
|
||||
10.557861328125,
|
||||
49.937079756975294
|
||||
],
|
||||
[
|
||||
8.4814453125,
|
||||
49.688954878870305
|
||||
],
|
||||
[
|
||||
9.173583984375,
|
||||
51.04830113331224
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"name": "non linear ring"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
81
umap/tests/test_datalayer.py
Normal file
81
umap/tests/test_datalayer.py
Normal file
|
@ -0,0 +1,81 @@
|
|||
import os
|
||||
|
||||
import pytest
|
||||
from django.core.files.base import ContentFile
|
||||
|
||||
from .base import DataLayerFactory, MapFactory
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
def test_datalayers_should_be_ordered_by_rank(map, datalayer):
|
||||
datalayer.rank = 5
|
||||
datalayer.save()
|
||||
c4 = DataLayerFactory(map=map, rank=4)
|
||||
c1 = DataLayerFactory(map=map, rank=1)
|
||||
c3 = DataLayerFactory(map=map, rank=3)
|
||||
c2 = DataLayerFactory(map=map, rank=2)
|
||||
assert list(map.datalayer_set.all()) == [c1, c2, c3, c4, datalayer]
|
||||
|
||||
|
||||
def test_upload_to(map, datalayer):
|
||||
map.pk = 302
|
||||
datalayer.pk = 17
|
||||
assert datalayer.upload_to().startswith('datalayer/2/0/302/17_')
|
||||
|
||||
|
||||
def test_save_should_use_pk_as_name(map, datalayer):
|
||||
assert "/{}_".format(datalayer.pk) in datalayer.geojson.name
|
||||
|
||||
|
||||
def test_same_geojson_file_name_will_be_suffixed(map, datalayer):
|
||||
before = datalayer.geojson.name
|
||||
datalayer.geojson.save(before, ContentFile("{}"))
|
||||
assert datalayer.geojson.name != before
|
||||
assert "/{}_".format(datalayer.pk) in datalayer.geojson.name
|
||||
|
||||
|
||||
def test_clone_should_return_new_instance(map, datalayer):
|
||||
clone = datalayer.clone()
|
||||
assert datalayer.pk != clone.pk
|
||||
assert datalayer.name == clone.name
|
||||
assert datalayer.map == clone.map
|
||||
|
||||
|
||||
def test_clone_should_update_map_if_passed(datalayer, user, licence):
|
||||
map = MapFactory(owner=user, licence=licence)
|
||||
clone = datalayer.clone(map_inst=map)
|
||||
assert datalayer.pk != clone.pk
|
||||
assert datalayer.name == clone.name
|
||||
assert datalayer.map != clone.map
|
||||
assert map == clone.map
|
||||
|
||||
|
||||
def test_clone_should_clone_geojson_too(datalayer):
|
||||
clone = datalayer.clone()
|
||||
assert datalayer.pk != clone.pk
|
||||
assert clone.geojson is not None
|
||||
assert clone.geojson.path != datalayer.geojson.path
|
||||
|
||||
|
||||
def test_should_remove_old_versions_on_save(datalayer, map, settings):
|
||||
settings.LEAFLET_STORAGE_KEEP_VERSIONS = 3
|
||||
root = datalayer.storage_root()
|
||||
before = len(datalayer.geojson.storage.listdir(root)[1])
|
||||
newer = '%s/%s_1440924889.geojson' % (root, datalayer.pk)
|
||||
medium = '%s/%s_1440923687.geojson' % (root, datalayer.pk)
|
||||
older = '%s/%s_1440918637.geojson' % (root, datalayer.pk)
|
||||
for path in [medium, newer, older]:
|
||||
datalayer.geojson.storage.save(path, ContentFile("{}"))
|
||||
datalayer.geojson.storage.save(path + '.gz', ContentFile("{}"))
|
||||
assert len(datalayer.geojson.storage.listdir(root)[1]) == 6 + before
|
||||
datalayer.save()
|
||||
files = datalayer.geojson.storage.listdir(root)[1]
|
||||
assert len(files) == 5
|
||||
assert os.path.basename(newer) in files
|
||||
assert os.path.basename(newer + '.gz') in files
|
||||
assert os.path.basename(medium) in files
|
||||
assert os.path.basename(medium + '.gz') in files
|
||||
assert os.path.basename(datalayer.geojson.path) in files
|
||||
assert os.path.basename(older) not in files
|
||||
assert os.path.basename(older + '.gz') not in files
|
162
umap/tests/test_datalayer_views.py
Normal file
162
umap/tests/test_datalayer_views.py
Normal file
|
@ -0,0 +1,162 @@
|
|||
import json
|
||||
|
||||
import pytest
|
||||
from django.core.files.base import ContentFile
|
||||
from django.urls import reverse
|
||||
|
||||
from umap.models import DataLayer, Map
|
||||
|
||||
from .base import MapFactory
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def post_data():
|
||||
return {
|
||||
"name": 'name',
|
||||
"display_on_load": True,
|
||||
"rank": 0,
|
||||
"geojson": '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-3.1640625,53.014783245859235],[-3.1640625,51.86292391360244],[-0.50537109375,51.385495069223204],[1.16455078125,52.38901106223456],[-0.41748046875,53.91728101547621],[-2.109375,53.85252660044951],[-3.1640625,53.014783245859235]]]},"properties":{"_storage_options":{},"name":"Ho god, sounds like a polygouine"}},{"type":"Feature","geometry":{"type":"LineString","coordinates":[[1.8017578124999998,51.16556659836182],[-0.48339843749999994,49.710272582105695],[-3.1640625,50.0923932109388],[-5.60302734375,51.998410382390325]]},"properties":{"_storage_options":{},"name":"Light line"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[0.63720703125,51.15178610143037]},"properties":{"_storage_options":{},"name":"marker he"}}],"_storage":{"displayOnLoad":true,"name":"new name","id":1668,"remoteData":{},"color":"LightSeaGreen","description":"test"}}' # noqa
|
||||
}
|
||||
|
||||
|
||||
def test_get(client, settings, datalayer):
|
||||
url = reverse('datalayer_view', args=(datalayer.pk, ))
|
||||
response = client.get(url)
|
||||
if getattr(settings, 'LEAFLET_STORAGE_XSENDFILE_HEADER', None):
|
||||
assert response['ETag'] is not None
|
||||
assert response['Last-Modified'] is not None
|
||||
assert response['Cache-Control'] is not None
|
||||
assert 'Content-Encoding' not in response
|
||||
j = json.loads(response.content.decode())
|
||||
assert '_storage' in j
|
||||
assert 'features' in j
|
||||
assert j['type'] == 'FeatureCollection'
|
||||
|
||||
|
||||
def test_update(client, datalayer, map, post_data):
|
||||
url = reverse('datalayer_update', args=(map.pk, datalayer.pk))
|
||||
client.login(username=map.owner.username, password="123123")
|
||||
name = 'new name'
|
||||
rank = 2
|
||||
post_data['name'] = name
|
||||
post_data['rank'] = rank
|
||||
response = client.post(url, post_data, follow=True)
|
||||
assert response.status_code == 200
|
||||
modified_datalayer = DataLayer.objects.get(pk=datalayer.pk)
|
||||
assert modified_datalayer.name == name
|
||||
assert modified_datalayer.rank == rank
|
||||
# Test response is a json
|
||||
j = json.loads(response.content.decode())
|
||||
assert "id" in j
|
||||
assert datalayer.pk == j['id']
|
||||
|
||||
|
||||
def test_should_not_be_possible_to_update_with_wrong_map_id_in_url(client, datalayer, map, post_data): # noqa
|
||||
other_map = MapFactory(owner=map.owner)
|
||||
url = reverse('datalayer_update', args=(other_map.pk, datalayer.pk))
|
||||
client.login(username=map.owner.username, password="123123")
|
||||
name = 'new name'
|
||||
post_data['name'] = name
|
||||
response = client.post(url, post_data, follow=True)
|
||||
assert response.status_code == 403
|
||||
modified_datalayer = DataLayer.objects.get(pk=datalayer.pk)
|
||||
assert modified_datalayer.name == datalayer.name
|
||||
|
||||
|
||||
def test_delete(client, datalayer, map):
|
||||
url = reverse('datalayer_delete', args=(map.pk, datalayer.pk))
|
||||
client.login(username=map.owner.username, password='123123')
|
||||
response = client.post(url, {}, follow=True)
|
||||
assert response.status_code == 200
|
||||
assert not DataLayer.objects.filter(pk=datalayer.pk).count()
|
||||
# Check that map has not been impacted
|
||||
assert Map.objects.filter(pk=map.pk).exists()
|
||||
# Test response is a json
|
||||
j = json.loads(response.content.decode())
|
||||
assert 'info' in j
|
||||
|
||||
|
||||
def test_should_not_be_possible_to_delete_with_wrong_map_id_in_url(client, datalayer, map): # noqa
|
||||
other_map = MapFactory(owner=map.owner)
|
||||
url = reverse('datalayer_delete', args=(other_map.pk, datalayer.pk))
|
||||
client.login(username=map.owner.username, password='123123')
|
||||
response = client.post(url, {}, follow=True)
|
||||
assert response.status_code == 403
|
||||
assert DataLayer.objects.filter(pk=datalayer.pk).exists()
|
||||
|
||||
|
||||
def test_get_gzipped(client, datalayer, settings):
|
||||
url = reverse('datalayer_view', args=(datalayer.pk, ))
|
||||
response = client.get(url, HTTP_ACCEPT_ENCODING='gzip')
|
||||
if getattr(settings, 'LEAFLET_STORAGE_XSENDFILE_HEADER', None):
|
||||
assert response['ETag'] is not None
|
||||
assert response['Last-Modified'] is not None
|
||||
assert response['Cache-Control'] is not None
|
||||
assert response['Content-Encoding'] == 'gzip'
|
||||
|
||||
|
||||
def test_optimistic_concurrency_control_with_good_etag(client, datalayer, map, post_data): # noqa
|
||||
# Get Etag
|
||||
url = reverse('datalayer_view', args=(datalayer.pk, ))
|
||||
response = client.get(url)
|
||||
etag = response['ETag']
|
||||
url = reverse('datalayer_update',
|
||||
args=(map.pk, datalayer.pk))
|
||||
client.login(username=map.owner.username, password="123123")
|
||||
name = 'new name'
|
||||
post_data['name'] = 'new name'
|
||||
response = client.post(url, post_data, follow=True, HTTP_IF_MATCH=etag)
|
||||
assert response.status_code == 200
|
||||
modified_datalayer = DataLayer.objects.get(pk=datalayer.pk)
|
||||
assert modified_datalayer.name == name
|
||||
|
||||
|
||||
def test_optimistic_concurrency_control_with_bad_etag(client, datalayer, map, post_data): # noqa
|
||||
url = reverse('datalayer_update', args=(map.pk, datalayer.pk))
|
||||
client.login(username=map.owner.username, password='123123')
|
||||
name = 'new name'
|
||||
post_data['name'] = name
|
||||
response = client.post(url, post_data, follow=True, HTTP_IF_MATCH='xxx')
|
||||
assert response.status_code == 412
|
||||
modified_datalayer = DataLayer.objects.get(pk=datalayer.pk)
|
||||
assert modified_datalayer.name != name
|
||||
|
||||
|
||||
def test_optimistic_concurrency_control_with_empty_etag(client, datalayer, map, post_data): # noqa
|
||||
url = reverse('datalayer_update', args=(map.pk, datalayer.pk))
|
||||
client.login(username=map.owner.username, password='123123')
|
||||
name = 'new name'
|
||||
post_data['name'] = name
|
||||
response = client.post(url, post_data, follow=True, HTTP_IF_MATCH=None)
|
||||
assert response.status_code == 200
|
||||
modified_datalayer = DataLayer.objects.get(pk=datalayer.pk)
|
||||
assert modified_datalayer.name == name
|
||||
|
||||
|
||||
def test_versions_should_return_versions(client, datalayer, map, settings):
|
||||
root = datalayer.storage_root()
|
||||
datalayer.geojson.storage.save(
|
||||
'%s/%s_1440924889.geojson' % (root, datalayer.pk),
|
||||
ContentFile("{}"))
|
||||
datalayer.geojson.storage.save(
|
||||
'%s/%s_1440923687.geojson' % (root, datalayer.pk),
|
||||
ContentFile("{}"))
|
||||
datalayer.geojson.storage.save(
|
||||
'%s/%s_1440918637.geojson' % (root, datalayer.pk),
|
||||
ContentFile("{}"))
|
||||
url = reverse('datalayer_versions', args=(datalayer.pk, ))
|
||||
versions = json.loads(client.get(url).content.decode())
|
||||
assert len(versions['versions']) == 4
|
||||
version = {'name': '%s_1440918637.geojson' % datalayer.pk, 'size': 2,
|
||||
'at': '1440918637'}
|
||||
assert version in versions['versions']
|
||||
|
||||
|
||||
def test_version_should_return_one_version_geojson(client, datalayer, map):
|
||||
root = datalayer.storage_root()
|
||||
name = '%s_1440924889.geojson' % datalayer.pk
|
||||
datalayer.geojson.storage.save('%s/%s' % (root, name), ContentFile("{}"))
|
||||
url = reverse('datalayer_version', args=(datalayer.pk, name))
|
||||
assert client.get(url).content.decode() == "{}"
|
43
umap/tests/test_fields.py
Normal file
43
umap/tests/test_fields.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from umap.models import Map
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
def test_can_use_dict(map):
|
||||
d = {'locateControl': True}
|
||||
map.settings = d
|
||||
map.save()
|
||||
assert Map.objects.get(pk=map.pk).settings == d
|
||||
|
||||
|
||||
def test_can_set_item(map):
|
||||
d = {'locateControl': True}
|
||||
map.settings = d
|
||||
map.save()
|
||||
map_inst = Map.objects.get(pk=map.pk)
|
||||
map_inst.settings['color'] = 'DarkGreen'
|
||||
assert map_inst.settings['locateControl'] is True
|
||||
|
||||
|
||||
def test_should_return_a_dict_if_none(map):
|
||||
map.settings = None
|
||||
map.save()
|
||||
assert Map.objects.get(pk=map.pk).settings == {}
|
||||
|
||||
|
||||
def test_should_not_double_dumps(map):
|
||||
map.settings = '{"locate": true}'
|
||||
map.save()
|
||||
assert Map.objects.get(pk=map.pk).settings == {'locate': True}
|
||||
|
||||
|
||||
def test_value_to_string(map):
|
||||
d = {'locateControl': True}
|
||||
map.settings = d
|
||||
map.save()
|
||||
field = Map._meta.get_field('settings')
|
||||
assert json.loads(field.value_to_string(map)) == d
|
12
umap/tests/test_licence.py
Normal file
12
umap/tests/test_licence.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
import pytest
|
||||
|
||||
from umap.models import DataLayer, Map
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
def test_licence_delete_should_not_remove_linked_maps(map, licence, datalayer):
|
||||
assert map.licence == licence
|
||||
licence.delete()
|
||||
assert Map.objects.filter(pk=map.pk).exists()
|
||||
assert DataLayer.objects.filter(pk=datalayer.pk).exists()
|
109
umap/tests/test_map.py
Normal file
109
umap/tests/test_map.py
Normal file
|
@ -0,0 +1,109 @@
|
|||
import pytest
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.urls import reverse
|
||||
|
||||
from umap.models import Map
|
||||
|
||||
from .base import MapFactory
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
def test_anonymous_can_edit_if_status_anonymous(map):
|
||||
anonymous = AnonymousUser()
|
||||
map.edit_status = map.ANONYMOUS
|
||||
map.save()
|
||||
assert map.can_edit(anonymous)
|
||||
|
||||
|
||||
def test_anonymous_cannot_edit_if_not_status_anonymous(map):
|
||||
anonymous = AnonymousUser()
|
||||
map.edit_status = map.OWNER
|
||||
map.save()
|
||||
assert not map.can_edit(anonymous)
|
||||
|
||||
|
||||
def test_non_editors_can_edit_if_status_anonymous(map, user):
|
||||
assert map.owner != user
|
||||
map.edit_status = map.ANONYMOUS
|
||||
map.save()
|
||||
assert map.can_edit(user)
|
||||
|
||||
|
||||
def test_non_editors_cannot_edit_if_not_status_anonymous(map, user):
|
||||
map.edit_status = map.OWNER
|
||||
map.save()
|
||||
assert not map.can_edit(user)
|
||||
|
||||
|
||||
def test_editors_cannot_edit_if_status_owner(map, user):
|
||||
map.edit_status = map.OWNER
|
||||
map.editors.add(user)
|
||||
map.save()
|
||||
assert not map.can_edit(user)
|
||||
|
||||
|
||||
def test_editors_can_edit_if_status_editors(map, user):
|
||||
map.edit_status = map.EDITORS
|
||||
map.editors.add(user)
|
||||
map.save()
|
||||
assert map.can_edit(user)
|
||||
|
||||
|
||||
def test_logged_in_user_should_be_allowed_for_anonymous_map_with_anonymous_edit_status(map, user, rf): # noqa
|
||||
map.owner = None
|
||||
map.edit_status = map.ANONYMOUS
|
||||
map.save()
|
||||
url = reverse('map_update', kwargs={'map_id': map.pk})
|
||||
request = rf.get(url)
|
||||
request.user = user
|
||||
assert map.can_edit(user, request)
|
||||
|
||||
|
||||
def test_clone_should_return_new_instance(map, user):
|
||||
clone = map.clone()
|
||||
assert map.pk != clone.pk
|
||||
assert u"Clone of " + map.name == clone.name
|
||||
assert map.settings == clone.settings
|
||||
assert map.center == clone.center
|
||||
assert map.zoom == clone.zoom
|
||||
assert map.licence == clone.licence
|
||||
assert map.tilelayer == clone.tilelayer
|
||||
|
||||
|
||||
def test_clone_should_keep_editors(map, user):
|
||||
map.editors.add(user)
|
||||
clone = map.clone()
|
||||
assert map.pk != clone.pk
|
||||
assert user in map.editors.all()
|
||||
assert user in clone.editors.all()
|
||||
|
||||
|
||||
def test_clone_should_update_owner_if_passed(map, user):
|
||||
clone = map.clone(owner=user)
|
||||
assert map.pk != clone.pk
|
||||
assert map.owner != clone.owner
|
||||
assert user == clone.owner
|
||||
|
||||
|
||||
def test_clone_should_clone_datalayers_and_features_too(map, user, datalayer):
|
||||
clone = map.clone()
|
||||
assert map.pk != clone.pk
|
||||
assert map.datalayer_set.count() == 1
|
||||
assert clone.datalayer_set.count() == 1
|
||||
other = clone.datalayer_set.all()[0]
|
||||
assert datalayer in map.datalayer_set.all()
|
||||
assert other.pk != datalayer.pk
|
||||
assert other.name == datalayer.name
|
||||
assert other.geojson is not None
|
||||
assert other.geojson.path != datalayer.geojson.path
|
||||
|
||||
|
||||
def test_publicmanager_should_get_only_public_maps(map, user, licence):
|
||||
map.share_status = map.PUBLIC
|
||||
open_map = MapFactory(owner=user, licence=licence, share_status=Map.OPEN)
|
||||
private_map = MapFactory(owner=user, licence=licence,
|
||||
share_status=Map.PRIVATE)
|
||||
assert map in Map.public.all()
|
||||
assert open_map not in Map.public.all()
|
||||
assert private_map not in Map.public.all()
|
449
umap/tests/test_map_views.py
Normal file
449
umap/tests/test_map_views.py
Normal file
|
@ -0,0 +1,449 @@
|
|||
import json
|
||||
|
||||
import pytest
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.urls import reverse
|
||||
|
||||
from umap.models import DataLayer, Map
|
||||
|
||||
from .base import login_required
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def post_data():
|
||||
return {
|
||||
'name': 'name',
|
||||
'center': '{"type":"Point","coordinates":[13.447265624999998,48.94415123418794]}', # noqa
|
||||
'settings': '{"type":"Feature","geometry":{"type":"Point","coordinates":[5.0592041015625,52.05924589011585]},"properties":{"tilelayer":{"maxZoom":20,"url_template":"http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png","minZoom":0,"attribution":"HOT and friends"},"licence":"","description":"","name":"test enrhûmé","tilelayersControl":true,"displayDataBrowserOnLoad":false,"displayPopupFooter":true,"displayCaptionOnLoad":false,"miniMap":true,"moreControl":true,"scaleControl":true,"zoomControl":true,"datalayersControl":true,"zoom":8}}' # noqa
|
||||
}
|
||||
|
||||
|
||||
def test_create(client, user, post_data):
|
||||
url = reverse('map_create')
|
||||
# POST only mendatory fields
|
||||
name = 'test-map-with-new-name'
|
||||
post_data['name'] = name
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.post(url, post_data)
|
||||
assert response.status_code == 200
|
||||
j = json.loads(response.content.decode())
|
||||
created_map = Map.objects.latest('pk')
|
||||
assert j['id'] == created_map.pk
|
||||
assert created_map.name == name
|
||||
|
||||
|
||||
def test_map_create_permissions(client, settings):
|
||||
settings.LEAFLET_STORAGE_ALLOW_ANONYMOUS = False
|
||||
url = reverse('map_create')
|
||||
# POST anonymous
|
||||
response = client.post(url, {})
|
||||
assert login_required(response)
|
||||
|
||||
|
||||
def test_map_update_access(client, map, user):
|
||||
url = reverse('map_update', kwargs={'map_id': map.pk})
|
||||
# GET anonymous
|
||||
response = client.get(url)
|
||||
assert login_required(response)
|
||||
# POST anonymous
|
||||
response = client.post(url, {})
|
||||
assert login_required(response)
|
||||
# GET with wrong permissions
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.get(url)
|
||||
assert response.status_code == 403
|
||||
# POST with wrong permissions
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.post(url, {})
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
def test_map_update_permissions_access(client, map, user):
|
||||
url = reverse('map_update_permissions', kwargs={'map_id': map.pk})
|
||||
# GET anonymous
|
||||
response = client.get(url)
|
||||
assert login_required(response)
|
||||
# POST anonymous
|
||||
response = client.post(url, {})
|
||||
assert login_required(response)
|
||||
# GET with wrong permissions
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.get(url)
|
||||
assert response.status_code == 403
|
||||
# POST with wrong permissions
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.post(url, {})
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
def test_update(client, map, post_data):
|
||||
url = reverse('map_update', kwargs={'map_id': map.pk})
|
||||
# POST only mendatory fields
|
||||
name = 'new map name'
|
||||
post_data['name'] = name
|
||||
client.login(username=map.owner.username, password="123123")
|
||||
response = client.post(url, post_data)
|
||||
assert response.status_code == 200
|
||||
j = json.loads(response.content.decode())
|
||||
assert 'html' not in j
|
||||
updated_map = Map.objects.get(pk=map.pk)
|
||||
assert j['id'] == updated_map.pk
|
||||
assert updated_map.name == name
|
||||
|
||||
|
||||
def test_delete(client, map, datalayer):
|
||||
url = reverse('map_delete', args=(map.pk, ))
|
||||
client.login(username=map.owner.username, password="123123")
|
||||
response = client.post(url, {}, follow=True)
|
||||
assert response.status_code == 200
|
||||
assert not Map.objects.filter(pk=map.pk).exists()
|
||||
assert not DataLayer.objects.filter(pk=datalayer.pk).exists()
|
||||
# Check that user has not been impacted
|
||||
assert User.objects.filter(pk=map.owner.pk).exists()
|
||||
# Test response is a json
|
||||
j = json.loads(response.content.decode())
|
||||
assert 'redirect' in j
|
||||
|
||||
|
||||
def test_wrong_slug_should_redirect_to_canonical(client, map):
|
||||
url = reverse('map', kwargs={'pk': map.pk, 'slug': 'wrong-slug'})
|
||||
canonical = reverse('map', kwargs={'pk': map.pk,
|
||||
'slug': map.slug})
|
||||
response = client.get(url)
|
||||
assert response.status_code == 301
|
||||
assert response['Location'] == canonical
|
||||
|
||||
|
||||
def test_wrong_slug_should_redirect_with_query_string(client, map):
|
||||
url = reverse('map', kwargs={'pk': map.pk, 'slug': 'wrong-slug'})
|
||||
url = "{}?allowEdit=0".format(url)
|
||||
canonical = reverse('map', kwargs={'pk': map.pk,
|
||||
'slug': map.slug})
|
||||
canonical = "{}?allowEdit=0".format(canonical)
|
||||
response = client.get(url)
|
||||
assert response.status_code == 301
|
||||
assert response['Location'] == canonical
|
||||
|
||||
|
||||
def test_should_not_consider_the_query_string_for_canonical_check(client, map):
|
||||
url = reverse('map', kwargs={'pk': map.pk, 'slug': map.slug})
|
||||
url = "{}?allowEdit=0".format(url)
|
||||
response = client.get(url)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_short_url_should_redirect_to_canonical(client, map):
|
||||
url = reverse('map_short_url', kwargs={'pk': map.pk})
|
||||
canonical = reverse('map', kwargs={'pk': map.pk,
|
||||
'slug': map.slug})
|
||||
response = client.get(url)
|
||||
assert response.status_code == 301
|
||||
assert response['Location'] == canonical
|
||||
|
||||
|
||||
def test_old_url_should_redirect_to_canonical(client, map):
|
||||
url = reverse(
|
||||
'map_old_url',
|
||||
kwargs={'username': map.owner.username, 'slug': map.slug}
|
||||
)
|
||||
canonical = reverse('map', kwargs={'pk': map.pk,
|
||||
'slug': map.slug})
|
||||
response = client.get(url)
|
||||
assert response.status_code == 301
|
||||
assert response['Location'] == canonical
|
||||
|
||||
|
||||
def test_clone_map_should_create_a_new_instance(client, map):
|
||||
assert Map.objects.count() == 1
|
||||
url = reverse('map_clone', kwargs={'map_id': map.pk})
|
||||
client.login(username=map.owner.username, password="123123")
|
||||
response = client.post(url)
|
||||
assert response.status_code == 200
|
||||
assert Map.objects.count() == 2
|
||||
clone = Map.objects.latest('pk')
|
||||
assert clone.pk != map.pk
|
||||
assert clone.name == u"Clone of " + map.name
|
||||
|
||||
|
||||
def test_user_not_allowed_should_not_clone_map(client, map, user, settings):
|
||||
settings.LEAFLET_STORAGE_ALLOW_ANONYMOUS = False
|
||||
assert Map.objects.count() == 1
|
||||
url = reverse('map_clone', kwargs={'map_id': map.pk})
|
||||
map.edit_status = map.OWNER
|
||||
map.save()
|
||||
response = client.post(url)
|
||||
assert login_required(response)
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.post(url)
|
||||
assert response.status_code == 403
|
||||
map.edit_status = map.ANONYMOUS
|
||||
map.save()
|
||||
client.logout()
|
||||
response = client.post(url)
|
||||
assert response.status_code == 403
|
||||
assert Map.objects.count() == 1
|
||||
|
||||
|
||||
def test_clone_should_set_cloner_as_owner(client, map, user):
|
||||
url = reverse('map_clone', kwargs={'map_id': map.pk})
|
||||
map.edit_status = map.EDITORS
|
||||
map.editors.add(user)
|
||||
map.save()
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.post(url)
|
||||
assert response.status_code == 200
|
||||
assert Map.objects.count() == 2
|
||||
clone = Map.objects.latest('pk')
|
||||
assert clone.pk != map.pk
|
||||
assert clone.name == u"Clone of " + map.name
|
||||
assert clone.owner == user
|
||||
|
||||
|
||||
def test_map_creation_should_allow_unicode_names(client, map, post_data):
|
||||
url = reverse('map_create')
|
||||
# POST only mendatory fields
|
||||
name = u'Академический'
|
||||
post_data['name'] = name
|
||||
client.login(username=map.owner.username, password="123123")
|
||||
response = client.post(url, post_data)
|
||||
assert response.status_code == 200
|
||||
j = json.loads(response.content.decode())
|
||||
created_map = Map.objects.latest('pk')
|
||||
assert j['id'] == created_map.pk
|
||||
assert created_map.name == name
|
||||
# Lower case of the russian original name
|
||||
# self.assertEqual(created_map.slug, u"академический")
|
||||
# for now we fallback to "map", see unicode_name branch
|
||||
assert created_map.slug == 'map'
|
||||
|
||||
|
||||
def test_anonymous_can_access_map_with_share_status_public(client, map):
|
||||
url = reverse('map', args=(map.slug, map.pk))
|
||||
map.share_status = map.PUBLIC
|
||||
map.save()
|
||||
response = client.get(url)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_anonymous_can_access_map_with_share_status_open(client, map):
|
||||
url = reverse('map', args=(map.slug, map.pk))
|
||||
map.share_status = map.OPEN
|
||||
map.save()
|
||||
response = client.get(url)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_anonymous_cannot_access_map_with_share_status_private(client, map):
|
||||
url = reverse('map', args=(map.slug, map.pk))
|
||||
map.share_status = map.PRIVATE
|
||||
map.save()
|
||||
response = client.get(url)
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
def test_owner_can_access_map_with_share_status_private(client, map):
|
||||
url = reverse('map', args=(map.slug, map.pk))
|
||||
map.share_status = map.PRIVATE
|
||||
map.save()
|
||||
client.login(username=map.owner.username, password="123123")
|
||||
response = client.get(url)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_editors_can_access_map_with_share_status_private(client, map, user):
|
||||
url = reverse('map', args=(map.slug, map.pk))
|
||||
map.share_status = map.PRIVATE
|
||||
map.editors.add(user)
|
||||
map.save()
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.get(url)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_non_editor_cannot_access_map_if_share_status_private(client, map, user): # noqa
|
||||
url = reverse('map', args=(map.slug, map.pk))
|
||||
map.share_status = map.PRIVATE
|
||||
map.save()
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.get(url)
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
def test_map_geojson_view(client, map):
|
||||
url = reverse('map_geojson', args=(map.pk, ))
|
||||
response = client.get(url)
|
||||
j = json.loads(response.content.decode())
|
||||
assert 'type' in j
|
||||
|
||||
|
||||
def test_only_owner_can_delete(client, map, user):
|
||||
map.editors.add(user)
|
||||
url = reverse('map_delete', kwargs={'map_id': map.pk})
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.post(url, {}, follow=True)
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
def test_map_editors_do_not_see_owner_change_input(client, map, user):
|
||||
map.editors.add(user)
|
||||
map.edit_status = map.EDITORS
|
||||
map.save()
|
||||
url = reverse('map_update_permissions', kwargs={'map_id': map.pk})
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.get(url)
|
||||
assert 'id_owner' not in response
|
||||
|
||||
|
||||
def test_logged_in_user_can_edit_map_editable_by_anonymous(client, map, user):
|
||||
map.owner = None
|
||||
map.edit_status = map.ANONYMOUS
|
||||
map.save()
|
||||
client.login(username=user.username, password="123123")
|
||||
url = reverse('map_update', kwargs={'map_id': map.pk})
|
||||
new_name = 'this is my new name'
|
||||
data = {
|
||||
'center': '{"type":"Point","coordinates":[13.447265624999998,48.94415123418794]}', # noqa
|
||||
'name': new_name
|
||||
}
|
||||
response = client.post(url, data)
|
||||
assert response.status_code == 200
|
||||
assert Map.objects.get(pk=map.pk).name == new_name
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('allow_anonymous')
|
||||
def test_anonymous_create(cookieclient, post_data):
|
||||
url = reverse('map_create')
|
||||
# POST only mendatory fields
|
||||
name = 'test-map-with-new-name'
|
||||
post_data['name'] = name
|
||||
response = cookieclient.post(url, post_data)
|
||||
assert response.status_code == 200
|
||||
j = json.loads(response.content.decode())
|
||||
created_map = Map.objects.latest('pk')
|
||||
assert j['id'] == created_map.pk
|
||||
assert created_map.name == name
|
||||
key, value = created_map.signed_cookie_elements
|
||||
assert key in cookieclient.cookies
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('allow_anonymous')
|
||||
def test_anonymous_update_without_cookie_fails(client, anonymap, post_data): # noqa
|
||||
url = reverse('map_update', kwargs={'map_id': anonymap.pk})
|
||||
response = client.post(url, post_data)
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('allow_anonymous')
|
||||
def test_anonymous_update_with_cookie_should_work(cookieclient, anonymap, post_data): # noqa
|
||||
url = reverse('map_update', kwargs={'map_id': anonymap.pk})
|
||||
# POST only mendatory fields
|
||||
name = 'new map name'
|
||||
post_data['name'] = name
|
||||
response = cookieclient.post(url, post_data)
|
||||
assert response.status_code == 200
|
||||
j = json.loads(response.content.decode())
|
||||
updated_map = Map.objects.get(pk=anonymap.pk)
|
||||
assert j['id'] == updated_map.pk
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('allow_anonymous')
|
||||
def test_anonymous_delete(cookieclient, anonymap):
|
||||
url = reverse('map_delete', args=(anonymap.pk, ))
|
||||
response = cookieclient.post(url, {}, follow=True)
|
||||
assert response.status_code == 200
|
||||
assert not Map.objects.filter(pk=anonymap.pk).count()
|
||||
# Test response is a json
|
||||
j = json.loads(response.content.decode())
|
||||
assert 'redirect' in j
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('allow_anonymous')
|
||||
def test_no_cookie_cant_delete(client, anonymap):
|
||||
url = reverse('map_delete', args=(anonymap.pk, ))
|
||||
response = client.post(url, {}, follow=True)
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('allow_anonymous')
|
||||
def test_anonymous_edit_url(cookieclient, anonymap):
|
||||
url = anonymap.get_anonymous_edit_url()
|
||||
canonical = reverse('map', kwargs={'pk': anonymap.pk,
|
||||
'slug': anonymap.slug})
|
||||
response = cookieclient.get(url)
|
||||
assert response.status_code == 302
|
||||
assert response['Location'] == canonical
|
||||
key, value = anonymap.signed_cookie_elements
|
||||
assert key in cookieclient.cookies
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('allow_anonymous')
|
||||
def test_bad_anonymous_edit_url_should_return_403(cookieclient, anonymap):
|
||||
url = anonymap.get_anonymous_edit_url()
|
||||
url = reverse(
|
||||
'map_anonymous_edit_url',
|
||||
kwargs={'signature': "%s:badsignature" % anonymap.pk}
|
||||
)
|
||||
response = cookieclient.get(url)
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('allow_anonymous')
|
||||
def test_authenticated_user_with_cookie_is_attached_as_owner(cookieclient, anonymap, post_data, user): # noqa
|
||||
url = reverse('map_update', kwargs={'map_id': anonymap.pk})
|
||||
cookieclient.login(username=user.username, password="123123")
|
||||
assert anonymap.owner is None
|
||||
# POST only mendatory filds
|
||||
name = 'new map name for authenticat_anonymoused user'
|
||||
post_data['name'] = name
|
||||
response = cookieclient.post(url, post_data)
|
||||
assert response.status_code == 200
|
||||
j = json.loads(response.content.decode())
|
||||
updated_map = Map.objects.get(pk=anonymap.pk)
|
||||
assert j['id'] == updated_map.pk
|
||||
assert updated_map.owner.pk, user.pk
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('allow_anonymous')
|
||||
def test_clone_anonymous_map_should_not_be_possible_if_user_is_not_allowed(client, anonymap, user): # noqa
|
||||
assert Map.objects.count() == 1
|
||||
url = reverse('map_clone', kwargs={'map_id': anonymap.pk})
|
||||
anonymap.edit_status = anonymap.OWNER
|
||||
anonymap.save()
|
||||
response = client.post(url)
|
||||
assert response.status_code == 403
|
||||
client.login(username=user.username, password="123123")
|
||||
response = client.post(url)
|
||||
assert response.status_code == 403
|
||||
assert Map.objects.count() == 1
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('allow_anonymous')
|
||||
def test_clone_map_should_be_possible_if_edit_status_is_anonymous(client, anonymap): # noqa
|
||||
assert Map.objects.count() == 1
|
||||
url = reverse('map_clone', kwargs={'map_id': anonymap.pk})
|
||||
anonymap.edit_status = anonymap.ANONYMOUS
|
||||
anonymap.save()
|
||||
response = client.post(url)
|
||||
assert response.status_code == 200
|
||||
assert Map.objects.count() == 2
|
||||
clone = Map.objects.latest('pk')
|
||||
assert clone.pk != anonymap.pk
|
||||
assert clone.name == 'Clone of ' + anonymap.name
|
||||
assert clone.owner is None
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('allow_anonymous')
|
||||
def test_anyone_can_access_anonymous_map(cookieclient, anonymap):
|
||||
url = reverse('map', args=(anonymap.slug, anonymap.pk))
|
||||
anonymap.share_status = anonymap.PUBLIC
|
||||
response = cookieclient.get(url)
|
||||
assert response.status_code == 200
|
||||
anonymap.share_status = anonymap.OPEN
|
||||
response = cookieclient.get(url)
|
||||
assert response.status_code == 200
|
||||
anonymap.share_status = anonymap.PRIVATE
|
||||
response = cookieclient.get(url)
|
||||
assert response.status_code == 200
|
21
umap/tests/test_tilelayer.py
Normal file
21
umap/tests/test_tilelayer.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
import pytest
|
||||
|
||||
from .base import TileLayerFactory
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
def test_tilelayer_json():
|
||||
tilelayer = TileLayerFactory(attribution='Attribution', maxZoom=19,
|
||||
minZoom=0, name='Name', rank=1, tms=True,
|
||||
url_template='http://{s}.x.fr/{z}/{x}/{y}')
|
||||
assert tilelayer.json == {
|
||||
'attribution': 'Attribution',
|
||||
'id': tilelayer.id,
|
||||
'maxZoom': 19,
|
||||
'minZoom': 0,
|
||||
'name': 'Name',
|
||||
'rank': 1,
|
||||
'tms': True,
|
||||
'url_template': 'http://{s}.x.fr/{z}/{x}/{y}'
|
||||
}
|
Loading…
Reference in a new issue