umap/umap/tests/test_datalayer_views.py
Yohan Boniface fa090b89df Store DataLayer's settings in DB
This allows to known the full datalayer behaviour without needing
to load all the data, including the zoom from and to (new settings),
but also the color for example.

This will help also understanding datalayers usage and making
stats.

But no data migration is provided, it's retrocompatible (data
migration in OSM FR servers would be huge, so let's see if it's
really needed).
2023-08-20 09:48:01 +02:00

187 lines
7.7 KiB
Python

import json
from pathlib import Path
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,
"settings": '{"displayOnLoad": true, "browsable": true, "name": "name"}',
"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":{"_umap_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":{"_umap_options":{},"name":"Light line"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[0.63720703125,51.15178610143037]},"properties":{"_umap_options":{},"name":"marker he"}}],"_umap_options":{"displayOnLoad":true,"name":"new name","id":1668,"remoteData":{},"color":"LightSeaGreen","description":"test"}}',
}
def test_get(client, settings, datalayer):
url = reverse("datalayer_view", args=(datalayer.pk,))
response = client.get(url)
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 "_umap_options" in j
assert "features" in j
assert j["type"] == "FeatureCollection"
def test_gzip_should_be_created_if_accepted(client, datalayer, map, post_data):
url = reverse("datalayer_view", args=(datalayer.pk,))
response = client.get(url, headers={"ACCEPT_ENCODING": "gzip"})
assert response.status_code == 200
flat = datalayer.geojson.path
gzipped = datalayer.geojson.path + ".gz"
assert Path(flat).exists()
assert Path(gzipped).exists()
assert Path(flat).stat().st_mtime_ns == Path(gzipped).stat().st_mtime_ns
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"]
assert j["browsable"] is True
assert Path(modified_datalayer.geojson.path).exists()
def test_should_not_be_possible_to_update_with_wrong_map_id_in_url(
client, datalayer, map, post_data
):
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
):
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_optimistic_concurrency_control_with_good_last_modified(
client, datalayer, map, post_data
):
# Get Last-Modified
url = reverse("datalayer_view", args=(datalayer.pk,))
response = client.get(url)
last_modified = response["Last-Modified"]
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_UNMODIFIED_SINCE=last_modified
)
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_last_modified(
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"
post_data["name"] = name
response = client.post(url, post_data, follow=True, HTTP_IF_UNMODIFIED_SINCE="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_last_modified(
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"
post_data["name"] = name
response = client.post(url, post_data, follow=True, HTTP_IF_UNMODIFIED_SINCE=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() == "{}"
def test_update_readonly(client, datalayer, map, post_data, settings):
settings.UMAP_READONLY = True
url = reverse("datalayer_update", args=(map.pk, datalayer.pk))
client.login(username=map.owner.username, password="123123")
response = client.post(url, post_data, follow=True)
assert response.status_code == 403