umap/umap/tests/test_map_views.py

542 lines
19 KiB
Python
Raw Normal View History

2018-05-19 04:54:08 -05:00
import json
import pytest
from django.contrib.auth import get_user_model
from django.urls import reverse
from django.core.signing import Signer
2018-05-19 04:54:08 -05:00
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
assert created_map.center.x == 13.447265624999998
assert created_map.center.y == 48.94415123418794
assert j['permissions'] == {
'edit_status': 3,
'share_status': 1,
'owner': {
'id': user.pk,
'name': 'Joe',
'url': '/en/user/Joe/'
},
'editors': [],
'anonymous_edit_url': ('http://umap.org'
+ created_map.get_anonymous_edit_url())
}
2018-05-19 04:54:08 -05:00
def test_map_create_permissions(client, settings):
settings.UMAP_ALLOW_ANONYMOUS = False
2018-05-19 04:54:08 -05:00
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_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.UMAP_ALLOW_ANONYMOUS = False
2018-05-19 04:54:08 -05:00
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
2019-04-07 04:12:38 -05:00
def test_anonymous_cannot_access_map_with_share_status_blocked(client, map):
url = reverse('map', args=(map.slug, map.pk))
map.share_status = map.BLOCKED
map.save()
response = client.get(url)
assert response.status_code == 403
def test_owner_cannot_access_map_with_share_status_blocked(client, map):
url = reverse('map', args=(map.slug, map.pk))
map.share_status = map.BLOCKED
map.save()
client.login(username=map.owner.username, password="123123")
response = client.get(url)
assert response.status_code == 403
2018-05-19 04:54:08 -05:00
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())
2018-07-14 16:55:21 -05:00
assert 'json' in response['content-type']
2018-05-19 04:54:08 -05:00
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.get_anonymous_edit_url()
in j['permissions']['anonymous_edit_url'])
2018-05-19 04:54:08 -05:00
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_sha1_anonymous_edit_url(cookieclient, anonymap):
signer = Signer(algorithm='sha1')
signature = signer.sign(anonymap.pk)
url = reverse('map_anonymous_edit_url', kwargs={'signature': signature})
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
2018-05-19 04:54:08 -05:00
@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_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
@pytest.mark.usefixtures('allow_anonymous')
def test_map_attach_owner(cookieclient, anonymap, user):
url = reverse('map_attach_owner', kwargs={'map_id': anonymap.pk})
cookieclient.login(username=user.username, password="123123")
assert anonymap.owner is None
response = cookieclient.post(url)
assert response.status_code == 200
map = Map.objects.get(pk=anonymap.pk)
assert map.owner == user
@pytest.mark.usefixtures('allow_anonymous')
def test_map_attach_owner_not_logged_in(cookieclient, anonymap, user):
url = reverse('map_attach_owner', kwargs={'map_id': anonymap.pk})
assert anonymap.owner is None
response = cookieclient.post(url)
assert response.status_code == 403
@pytest.mark.usefixtures('allow_anonymous')
def test_map_attach_owner_with_already_an_owner(cookieclient, map, user):
url = reverse('map_attach_owner', kwargs={'map_id': map.pk})
cookieclient.login(username=user.username, password="123123")
assert map.owner
assert map.owner != user
response = cookieclient.post(url)
assert response.status_code == 403
def test_map_attach_owner_anonymous_not_allowed(cookieclient, anonymap, user):
url = reverse('map_attach_owner', kwargs={'map_id': anonymap.pk})
cookieclient.login(username=user.username, password="123123")
assert anonymap.owner is None
response = cookieclient.post(url)
assert response.status_code == 403
# # 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_create_readonly(client, user, post_data, settings):
settings.UMAP_READONLY = True
url = reverse('map_create')
client.login(username=user.username, password="123123")
response = client.post(url, post_data)
assert response.status_code == 403
assert response.content == b'Site is readonly for maintenance'
def test_search(client, map):
# Very basic search, that do not deal with accent nor case.
# See install.md for how to have a smarter dict + index.
map.name = "Blé dur"
map.save()
url = reverse("search")
response = client.get(url + "?q=Blé")
assert "Blé dur" in response.content.decode()