umap-project 2.6.3__py3-none-any.whl → 2.7.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of umap-project might be problematic. Click here for more details.
- umap/__init__.py +1 -1
- umap/admin.py +64 -1
- umap/context_processors.py +1 -0
- umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
- umap/locale/cs_CZ/LC_MESSAGES/django.po +96 -92
- umap/locale/de/LC_MESSAGES/django.mo +0 -0
- umap/locale/de/LC_MESSAGES/django.po +19 -18
- umap/locale/en/LC_MESSAGES/django.po +47 -43
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +51 -47
- umap/locale/pt/LC_MESSAGES/django.mo +0 -0
- umap/locale/pt/LC_MESSAGES/django.po +64 -60
- umap/management/commands/clean_tilelayer.py +152 -0
- umap/management/commands/purge_purgatory.py +28 -0
- umap/models.py +27 -2
- umap/settings/base.py +2 -0
- umap/static/umap/base.css +4 -4
- umap/static/umap/css/contextmenu.css +5 -0
- umap/static/umap/css/icon.css +7 -2
- umap/static/umap/img/16-white.svg +9 -2
- umap/static/umap/img/16.svg +3 -0
- umap/static/umap/img/source/16-white.svg +10 -3
- umap/static/umap/img/source/16.svg +4 -1
- umap/static/umap/js/modules/autocomplete.js +7 -3
- umap/static/umap/js/modules/browser.js +7 -1
- umap/static/umap/js/modules/caption.js +6 -1
- umap/static/umap/js/modules/data/features.js +176 -2
- umap/static/umap/js/modules/data/layer.js +31 -26
- umap/static/umap/js/modules/formatter.js +3 -2
- umap/static/umap/js/modules/global.js +2 -0
- umap/static/umap/js/modules/importers/communesfr.js +13 -1
- umap/static/umap/js/modules/permissions.js +123 -93
- umap/static/umap/js/modules/rendering/ui.js +37 -212
- umap/static/umap/js/modules/sync/engine.js +365 -14
- umap/static/umap/js/modules/sync/hlc.js +106 -0
- umap/static/umap/js/modules/sync/updaters.js +4 -4
- umap/static/umap/js/modules/sync/websocket.js +1 -1
- umap/static/umap/js/modules/ui/base.js +2 -2
- umap/static/umap/js/modules/ui/contextmenu.js +34 -17
- umap/static/umap/js/modules/urls.js +5 -1
- umap/static/umap/js/modules/utils.js +5 -1
- umap/static/umap/js/umap.controls.js +47 -47
- umap/static/umap/js/umap.core.js +3 -3
- umap/static/umap/js/umap.forms.js +3 -1
- umap/static/umap/js/umap.js +95 -112
- umap/static/umap/locale/br.js +13 -4
- umap/static/umap/locale/br.json +13 -4
- umap/static/umap/locale/ca.js +21 -12
- umap/static/umap/locale/ca.json +21 -12
- umap/static/umap/locale/cs_CZ.js +87 -78
- umap/static/umap/locale/cs_CZ.json +87 -78
- umap/static/umap/locale/de.js +17 -8
- umap/static/umap/locale/de.json +17 -8
- umap/static/umap/locale/en.js +9 -2
- umap/static/umap/locale/en.json +9 -2
- umap/static/umap/locale/eu.js +10 -3
- umap/static/umap/locale/eu.json +10 -3
- umap/static/umap/locale/fa_IR.js +11 -4
- umap/static/umap/locale/fa_IR.json +11 -4
- umap/static/umap/locale/fr.js +11 -4
- umap/static/umap/locale/fr.json +11 -4
- umap/static/umap/locale/hu.js +10 -3
- umap/static/umap/locale/hu.json +10 -3
- umap/static/umap/locale/pt.js +17 -8
- umap/static/umap/locale/pt.json +17 -8
- umap/static/umap/locale/pt_PT.js +13 -4
- umap/static/umap/locale/pt_PT.json +13 -4
- umap/static/umap/locale/zh_TW.js +13 -4
- umap/static/umap/locale/zh_TW.json +13 -4
- umap/static/umap/map.css +7 -22
- umap/static/umap/unittests/hlc.js +158 -0
- umap/static/umap/unittests/sync.js +321 -15
- umap/static/umap/unittests/utils.js +23 -0
- umap/static/umap/vendors/georsstogeojson/GeoRSSToGeoJSON.js +111 -80
- umap/templates/umap/dashboard_menu.html +4 -2
- umap/templates/umap/js.html +0 -4
- umap/tests/integration/test_anonymous_owned_map.py +1 -0
- umap/tests/integration/test_basics.py +1 -1
- umap/tests/integration/test_circles_layer.py +12 -0
- umap/tests/integration/test_datalayer.py +5 -0
- umap/tests/integration/test_draw_polygon.py +17 -9
- umap/tests/integration/test_draw_polyline.py +12 -8
- umap/tests/integration/test_edit_datalayer.py +4 -6
- umap/tests/integration/test_edit_map.py +1 -1
- umap/tests/integration/test_import.py +5 -0
- umap/tests/integration/test_map.py +5 -0
- umap/tests/integration/test_owned_map.py +1 -1
- umap/tests/integration/test_view_polygon.py +12 -12
- umap/tests/integration/test_websocket_sync.py +65 -3
- umap/tests/test_clean_tilelayer.py +83 -0
- umap/tests/test_datalayer.py +24 -0
- umap/tests/test_map_views.py +1 -0
- umap/tests/test_purge_purgatory.py +25 -0
- umap/tests/test_websocket_server.py +22 -0
- umap/urls.py +5 -1
- umap/views.py +6 -3
- umap/websocket_server.py +130 -27
- {umap_project-2.6.3.dist-info → umap_project-2.7.0b0.dist-info}/METADATA +9 -9
- {umap_project-2.6.3.dist-info → umap_project-2.7.0b0.dist-info}/RECORD +102 -97
- umap/static/umap/vendors/contextmenu/leaflet.contextmenu.min.css +0 -1
- umap/static/umap/vendors/contextmenu/leaflet.contextmenu.min.js +0 -7
- {umap_project-2.6.3.dist-info → umap_project-2.7.0b0.dist-info}/WHEEL +0 -0
- {umap_project-2.6.3.dist-info → umap_project-2.7.0b0.dist-info}/entry_points.txt +0 -0
- {umap_project-2.6.3.dist-info → umap_project-2.7.0b0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,89 +1,120 @@
|
|
|
1
|
-
|
|
1
|
+
export function parse(dom, options) {
|
|
2
|
+
const g = {
|
|
3
|
+
type: 'FeatureCollection',
|
|
4
|
+
features: [],
|
|
5
|
+
}
|
|
2
6
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
};
|
|
7
|
+
const items = get(dom, 'item')
|
|
8
|
+
for (const item of Array.from(items)) {
|
|
9
|
+
const feature = processOne(item)
|
|
10
|
+
if (feature) {
|
|
11
|
+
g.features.push(feature)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return g
|
|
15
|
+
}
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
function get(x, y) {
|
|
18
|
+
return x.getElementsByTagName(y)
|
|
19
|
+
}
|
|
20
|
+
function get1(x, y) {
|
|
21
|
+
const n = get(x, y)
|
|
22
|
+
return n.length ? n[0] : null
|
|
23
|
+
}
|
|
24
|
+
function norm(el) {
|
|
25
|
+
if (el.normalize) {
|
|
26
|
+
el.normalize()
|
|
27
|
+
}
|
|
28
|
+
return el
|
|
29
|
+
}
|
|
30
|
+
function nodeVal(x) {
|
|
31
|
+
if (x) {
|
|
32
|
+
norm(x)
|
|
33
|
+
}
|
|
34
|
+
return x?.firstChild?.nodeValue
|
|
35
|
+
}
|
|
36
|
+
function attr(x, y) {
|
|
37
|
+
return x.getAttribute(y)
|
|
38
|
+
}
|
|
15
39
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
40
|
+
function geom(node) {
|
|
41
|
+
function p(c) {
|
|
42
|
+
return parseFloat(c)
|
|
43
|
+
}
|
|
44
|
+
function r(c) {
|
|
45
|
+
return c.reverse().map(p)
|
|
46
|
+
} // we have latlon we want lonlat
|
|
47
|
+
function e(f) {
|
|
48
|
+
const _ = []
|
|
49
|
+
for (let i = 0; i < f.length; i += 2) {
|
|
50
|
+
_.push(r(f.slice(i, i + 2)))
|
|
51
|
+
}
|
|
52
|
+
return _
|
|
53
|
+
}
|
|
19
54
|
|
|
20
|
-
|
|
55
|
+
let type
|
|
56
|
+
let coordinates
|
|
21
57
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (type && coordinates) {
|
|
50
|
-
return {
|
|
51
|
-
type: type,
|
|
52
|
-
coordinates: coordinates
|
|
53
|
-
};
|
|
54
|
-
}
|
|
58
|
+
if (get1(node, 'geo:long')) {
|
|
59
|
+
type = 'Point'
|
|
60
|
+
coordinates = [
|
|
61
|
+
p(nodeVal(get1(node, 'geo:long'))),
|
|
62
|
+
p(nodeVal(get1(node, 'geo:lat'))),
|
|
63
|
+
]
|
|
64
|
+
} else if (get1(node, 'long')) {
|
|
65
|
+
type = 'Point'
|
|
66
|
+
coordinates = [p(nodeVal(get1(node, 'long'))), p(nodeVal(get1(node, 'lat')))]
|
|
67
|
+
} else if (get1(node, 'georss:point')) {
|
|
68
|
+
type = 'Point'
|
|
69
|
+
coordinates = r(nodeVal(get1(node, 'georss:point')).split(' '))
|
|
70
|
+
} else if (get1(node, 'point')) {
|
|
71
|
+
type = 'Point'
|
|
72
|
+
coordinates = r(nodeVal(get1(node, 'point')).split(' '))
|
|
73
|
+
} else {
|
|
74
|
+
const line = get1(node, 'georss:line')
|
|
75
|
+
const poly = get1(node, 'georss:polygon')
|
|
76
|
+
if (line || poly) {
|
|
77
|
+
type = line ? 'LineString' : 'Polygon'
|
|
78
|
+
const tag = line ? 'georss:line' : 'georss:polygon'
|
|
79
|
+
coordinates = nodeVal(get1(node, tag)).split(' ')
|
|
80
|
+
if (coordinates.length % 2 !== 0) return
|
|
81
|
+
coordinates = e(coordinates)
|
|
82
|
+
if (poly) {
|
|
83
|
+
coordinates = [coordinates]
|
|
84
|
+
}
|
|
55
85
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
var f = {
|
|
62
|
-
type: "Feature",
|
|
63
|
-
geometry: geometry,
|
|
64
|
-
properties: {
|
|
65
|
-
title: nodeVal(get1(node, 'title')),
|
|
66
|
-
description: nodeVal(get1(node, 'description')),
|
|
67
|
-
link: nodeVal(get1(node, 'link')),
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
var media = get1(node, 'media:content'), mime;
|
|
71
|
-
if (!media) {
|
|
72
|
-
media = get1(node, 'enclosure'), mime;
|
|
73
|
-
}
|
|
74
|
-
if (media) {
|
|
75
|
-
mime = attr(media, 'type');
|
|
76
|
-
if (mime.indexOf('image') !== -1) {
|
|
77
|
-
f.properties.img = attr(media, "url"); // How not to invent a key?
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
g.features.push(f);
|
|
86
|
+
}
|
|
87
|
+
if (type && coordinates) {
|
|
88
|
+
return {
|
|
89
|
+
type: type,
|
|
90
|
+
coordinates: coordinates,
|
|
81
91
|
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
82
94
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
95
|
+
function processOne(node) {
|
|
96
|
+
const geometry = geom(node)
|
|
97
|
+
// TODO collect and fire errors
|
|
98
|
+
if (!geometry) return
|
|
99
|
+
const f = {
|
|
100
|
+
type: 'Feature',
|
|
101
|
+
geometry: geometry,
|
|
102
|
+
properties: {
|
|
103
|
+
title: nodeVal(get1(node, 'title')),
|
|
104
|
+
description: nodeVal(get1(node, 'description')),
|
|
105
|
+
link: nodeVal(get1(node, 'link')),
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
let media = get1(node, 'media:content')
|
|
109
|
+
let mime
|
|
110
|
+
if (!media) {
|
|
111
|
+
media = get1(node, 'enclosure')
|
|
112
|
+
}
|
|
113
|
+
if (media) {
|
|
114
|
+
mime = attr(media, 'type')
|
|
115
|
+
if (mime.indexOf('image') !== -1) {
|
|
116
|
+
f.properties.img = attr(media, 'url') // How not to invent a key?
|
|
86
117
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
118
|
+
}
|
|
119
|
+
return f
|
|
120
|
+
}
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
{% else %}
|
|
8
8
|
<a href="{% url 'user_dashboard' %}">{% trans "My Maps" %}</a>
|
|
9
9
|
{% endif %}
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
{% if UMAP_ALLOW_EDIT_PROFILE %}
|
|
11
|
+
<a {% if selected == "profile" %}class="selected"{% endif %}
|
|
12
|
+
href="{% url 'user_profile' %}">{% trans "My profile" %}</a>
|
|
13
|
+
{% endif %}
|
|
12
14
|
<a {% if selected == "teams" %}class="selected"{% endif %}
|
|
13
15
|
href="{% url 'user_teams' %}">{% trans "My teams" %}</a>
|
|
14
16
|
</h2>
|
umap/templates/umap/js.html
CHANGED
|
@@ -25,11 +25,7 @@
|
|
|
25
25
|
<script src="{% static 'umap/vendors/csv2geojson/csv2geojson.js' %}" defer></script>
|
|
26
26
|
<script src="{% static 'umap/vendors/osmtogeojson/osmtogeojson.js' %}" defer></script>
|
|
27
27
|
<script src="{% static 'umap/vendors/loading/Control.Loading.js' %}" defer></script>
|
|
28
|
-
<script src="{% static 'umap/vendors/contextmenu/leaflet.contextmenu.min.js' %}"
|
|
29
|
-
defer></script>
|
|
30
28
|
<script src="{% static 'umap/vendors/photon/leaflet.photon.js' %}" defer></script>
|
|
31
|
-
<script src="{% static 'umap/vendors/georsstogeojson/GeoRSSToGeoJSON.js' %}"
|
|
32
|
-
defer></script>
|
|
33
29
|
<script src="{% static 'umap/vendors/fullscreen/Leaflet.fullscreen.min.js' %}"
|
|
34
30
|
defer></script>
|
|
35
31
|
<script src="{% static 'umap/vendors/toolbar/leaflet.toolbar.js' %}" defer></script>
|
|
@@ -156,6 +156,7 @@ def test_can_change_perms_after_create(tilelayer, live_server, page):
|
|
|
156
156
|
".datalayer-permissions select[name='edit_status'] option:checked"
|
|
157
157
|
)
|
|
158
158
|
expect(option).to_have_text("Inherit")
|
|
159
|
+
expect(page.get_by_label("Secret edit link:")).to_be_visible()
|
|
159
160
|
|
|
160
161
|
|
|
161
162
|
def test_alert_message_after_create(
|
|
@@ -94,4 +94,4 @@ def test_login_from_map_page(live_server, page, tilelayer, settings, user, conte
|
|
|
94
94
|
# Save should have proceed
|
|
95
95
|
assert Map.objects.count() == 1
|
|
96
96
|
# Use name should now appear on the header toolbar
|
|
97
|
-
expect(page.
|
|
97
|
+
expect(page.get_by_role("button", name="Joe")).to_be_visible()
|
|
@@ -67,3 +67,15 @@ def test_basic_circles_layer(map, live_server, page):
|
|
|
67
67
|
.get_attribute("d")
|
|
68
68
|
.endswith("a2,2 0 1,0 -4,0 ")
|
|
69
69
|
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_can_draw_new_circles(openmap, live_server, page):
|
|
73
|
+
path = Path(__file__).parent.parent / "fixtures/test_circles_layer.geojson"
|
|
74
|
+
data = json.loads(path.read_text())
|
|
75
|
+
DataLayerFactory(data=data, map=openmap)
|
|
76
|
+
page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit#12/47.2210/-1.5621")
|
|
77
|
+
paths = page.locator("path")
|
|
78
|
+
expect(paths).to_have_count(10)
|
|
79
|
+
page.get_by_title("Draw a marker").click()
|
|
80
|
+
page.locator("#map").click(position={"x": 200, "y": 200})
|
|
81
|
+
expect(paths).to_have_count(11)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import os
|
|
2
3
|
import re
|
|
3
4
|
|
|
4
5
|
import pytest
|
|
@@ -54,6 +55,10 @@ def test_should_honour_fromZoom(live_server, map, datalayer, page):
|
|
|
54
55
|
expect(markers).to_be_visible()
|
|
55
56
|
|
|
56
57
|
|
|
58
|
+
@pytest.mark.skipif(
|
|
59
|
+
os.environ.get("CI", "false") == "true",
|
|
60
|
+
reason="Test is failing intermittently, skipping in the CI",
|
|
61
|
+
)
|
|
57
62
|
def test_should_honour_toZoom(live_server, map, datalayer, page):
|
|
58
63
|
set_options(datalayer, displayOnLoad=True, toZoom=6)
|
|
59
64
|
page.goto(f"{live_server.url}{map.get_absolute_url()}#7/48.55/14.68")
|
|
@@ -161,8 +161,10 @@ def test_can_draw_multi(live_server, page, tilelayer):
|
|
|
161
161
|
page.keyboard.press("Escape")
|
|
162
162
|
expect(multi_button).to_be_hidden()
|
|
163
163
|
polygons.first.click(button="right", position={"x": 10, "y": 10})
|
|
164
|
-
expect(page.get_by_role("
|
|
165
|
-
expect(
|
|
164
|
+
expect(page.get_by_role("button", name="Transform to lines")).to_be_hidden()
|
|
165
|
+
expect(
|
|
166
|
+
page.get_by_role("button", name="Remove shape from the multi")
|
|
167
|
+
).to_be_visible()
|
|
166
168
|
|
|
167
169
|
|
|
168
170
|
def test_can_draw_hole(page, live_server, tilelayer):
|
|
@@ -196,7 +198,7 @@ def test_can_draw_hole(page, live_server, tilelayer):
|
|
|
196
198
|
expect(vertices).to_have_count(8)
|
|
197
199
|
# Click on the polygon but not in the hole
|
|
198
200
|
polygons.first.click(button="right", position={"x": 10, "y": 10})
|
|
199
|
-
expect(page.get_by_role("
|
|
201
|
+
expect(page.get_by_role("button", name="Transform to lines")).to_be_hidden()
|
|
200
202
|
|
|
201
203
|
|
|
202
204
|
def test_can_transfer_shape_from_simple_polygon(live_server, page, tilelayer):
|
|
@@ -228,7 +230,7 @@ def test_can_transfer_shape_from_simple_polygon(live_server, page, tilelayer):
|
|
|
228
230
|
# Now that polygon 2 is selected, right click on first one
|
|
229
231
|
# and transfer shape
|
|
230
232
|
polygons.first.click(position={"x": 20, "y": 20}, button="right")
|
|
231
|
-
page.get_by_role("
|
|
233
|
+
page.get_by_role("button", name="Transfer shape to edited feature").click()
|
|
232
234
|
expect(polygons).to_have_count(1)
|
|
233
235
|
|
|
234
236
|
|
|
@@ -246,7 +248,9 @@ def test_can_extract_shape(live_server, page, tilelayer, settings):
|
|
|
246
248
|
# Click again to finish
|
|
247
249
|
map.click(position={"x": 100, "y": 100})
|
|
248
250
|
expect(polygons).to_have_count(1)
|
|
249
|
-
extract_button = page.get_by_role(
|
|
251
|
+
extract_button = page.get_by_role(
|
|
252
|
+
"button", name="Extract shape to separate feature"
|
|
253
|
+
)
|
|
250
254
|
expect(extract_button).to_be_hidden()
|
|
251
255
|
page.get_by_title("Add a polygon to the current multi").click()
|
|
252
256
|
map.click(position={"x": 250, "y": 200})
|
|
@@ -326,7 +330,9 @@ def test_cannot_transfer_shape_to_line(live_server, page, tilelayer):
|
|
|
326
330
|
# Click again to finish
|
|
327
331
|
map.click(position={"x": 100, "y": 100})
|
|
328
332
|
expect(polygons).to_have_count(1)
|
|
329
|
-
extract_button = page.get_by_role(
|
|
333
|
+
extract_button = page.get_by_role(
|
|
334
|
+
"button", name="Extract shape to separate feature"
|
|
335
|
+
)
|
|
330
336
|
polygons.first.click(position={"x": 20, "y": 20}, button="right")
|
|
331
337
|
expect(extract_button).to_be_hidden()
|
|
332
338
|
page.get_by_title("Draw a polyline").click()
|
|
@@ -352,7 +358,9 @@ def test_cannot_transfer_shape_to_marker(live_server, page, tilelayer):
|
|
|
352
358
|
# Click again to finish
|
|
353
359
|
map.click(position={"x": 100, "y": 100})
|
|
354
360
|
expect(polygons).to_have_count(1)
|
|
355
|
-
extract_button = page.get_by_role(
|
|
361
|
+
extract_button = page.get_by_role(
|
|
362
|
+
"button", name="Extract shape to separate feature"
|
|
363
|
+
)
|
|
356
364
|
polygons.first.click(position={"x": 20, "y": 20}, button="right")
|
|
357
365
|
expect(extract_button).to_be_hidden()
|
|
358
366
|
page.get_by_title("Draw a marker").click()
|
|
@@ -377,7 +385,7 @@ def test_can_clone_polygon(live_server, page, tilelayer, settings):
|
|
|
377
385
|
map.click(position={"x": 100, "y": 100})
|
|
378
386
|
expect(polygons).to_have_count(1)
|
|
379
387
|
polygons.first.click(button="right")
|
|
380
|
-
page.get_by_role("
|
|
388
|
+
page.get_by_role("button", name="Clone this feature").click()
|
|
381
389
|
expect(polygons).to_have_count(2)
|
|
382
390
|
data = save_and_get_json(page)
|
|
383
391
|
assert len(data["features"]) == 2
|
|
@@ -402,7 +410,7 @@ def test_can_transform_polygon_to_line(live_server, page, tilelayer, settings):
|
|
|
402
410
|
expect(polygons).to_have_count(1)
|
|
403
411
|
expect(paths).to_have_count(1)
|
|
404
412
|
polygons.first.click(button="right")
|
|
405
|
-
page.get_by_role("
|
|
413
|
+
page.get_by_role("button", name="Transform to lines").click()
|
|
406
414
|
# No more polygons (will fill), but one path, it must be a line
|
|
407
415
|
expect(polygons).to_have_count(0)
|
|
408
416
|
expect(paths).to_have_count(1)
|
|
@@ -157,8 +157,10 @@ def test_can_draw_multi(live_server, page, tilelayer):
|
|
|
157
157
|
page.keyboard.press("Escape")
|
|
158
158
|
expect(add_shape).to_be_hidden()
|
|
159
159
|
lines.first.click(button="right", position={"x": 10, "y": 1})
|
|
160
|
-
expect(page.get_by_role("
|
|
161
|
-
expect(
|
|
160
|
+
expect(page.get_by_role("button", name="Transform to polygon")).to_be_hidden()
|
|
161
|
+
expect(
|
|
162
|
+
page.get_by_role("button", name="Remove shape from the multi")
|
|
163
|
+
).to_be_visible()
|
|
162
164
|
|
|
163
165
|
|
|
164
166
|
def test_can_transfer_shape_from_simple_polyline(live_server, page, tilelayer):
|
|
@@ -188,7 +190,7 @@ def test_can_transfer_shape_from_simple_polyline(live_server, page, tilelayer):
|
|
|
188
190
|
# Now that line 2 is selected, right click on first one
|
|
189
191
|
# and transfer shape
|
|
190
192
|
lines.first.click(position={"x": 10, "y": 1}, button="right")
|
|
191
|
-
page.get_by_role("
|
|
193
|
+
page.get_by_role("button", name="Transfer shape to edited feature").click()
|
|
192
194
|
expect(lines).to_have_count(1)
|
|
193
195
|
|
|
194
196
|
|
|
@@ -227,7 +229,7 @@ def test_can_transfer_shape_from_multi(live_server, page, tilelayer, settings):
|
|
|
227
229
|
# Now that line 2 is selected, right click on first one
|
|
228
230
|
# and transfer shape
|
|
229
231
|
lines.first.click(position={"x": 10, "y": 1}, button="right")
|
|
230
|
-
page.get_by_role("
|
|
232
|
+
page.get_by_role("button", name="Transfer shape to edited feature").click()
|
|
231
233
|
expect(lines).to_have_count(2)
|
|
232
234
|
data = save_and_get_json(page)
|
|
233
235
|
assert data["features"][0]["geometry"] == {
|
|
@@ -259,7 +261,9 @@ def test_can_extract_shape(live_server, page, tilelayer):
|
|
|
259
261
|
# Click again to finish
|
|
260
262
|
map.click(position={"x": 100, "y": 200})
|
|
261
263
|
expect(lines).to_have_count(1)
|
|
262
|
-
extract_button = page.get_by_role(
|
|
264
|
+
extract_button = page.get_by_role(
|
|
265
|
+
"button", name="Extract shape to separate feature"
|
|
266
|
+
)
|
|
263
267
|
expect(extract_button).to_be_hidden()
|
|
264
268
|
page.get_by_title("Add a line to the current multi").click()
|
|
265
269
|
map.click(position={"x": 250, "y": 250})
|
|
@@ -287,7 +291,7 @@ def test_can_clone_polyline(live_server, page, tilelayer, settings):
|
|
|
287
291
|
map.click(position={"x": 100, "y": 200})
|
|
288
292
|
expect(lines).to_have_count(1)
|
|
289
293
|
lines.first.click(position={"x": 10, "y": 1}, button="right")
|
|
290
|
-
page.get_by_role("
|
|
294
|
+
page.get_by_role("button", name="Clone this feature").click()
|
|
291
295
|
expect(lines).to_have_count(2)
|
|
292
296
|
data = save_and_get_json(page)
|
|
293
297
|
assert len(data["features"]) == 2
|
|
@@ -313,7 +317,7 @@ def test_can_transform_polyline_to_polygon(live_server, page, tilelayer, setting
|
|
|
313
317
|
expect(paths).to_have_count(1)
|
|
314
318
|
expect(polygons).to_have_count(0)
|
|
315
319
|
paths.first.click(position={"x": 10, "y": 1}, button="right")
|
|
316
|
-
page.get_by_role("
|
|
320
|
+
page.get_by_role("button", name="Transform to polygon").click()
|
|
317
321
|
expect(polygons).to_have_count(1)
|
|
318
322
|
expect(paths).to_have_count(1)
|
|
319
323
|
data = save_and_get_json(page)
|
|
@@ -374,7 +378,7 @@ def test_can_merge_lines(live_server, page, tilelayer, settings):
|
|
|
374
378
|
|
|
375
379
|
# Right click and merge nodes
|
|
376
380
|
map.click(button="right", position={"x": 100, "y": 200})
|
|
377
|
-
|
|
381
|
+
page.get_by_role("button", name="Merge lines").click()
|
|
378
382
|
data = save_and_get_json(page)
|
|
379
383
|
assert len(data["features"]) == 1
|
|
380
384
|
assert data["features"][0]["geometry"]["type"] == "LineString"
|
|
@@ -60,12 +60,10 @@ def test_cancel_deleting_datalayer_should_restore(
|
|
|
60
60
|
expect(layers).to_have_count(1)
|
|
61
61
|
expect(markers).to_have_count(1)
|
|
62
62
|
page.get_by_role("link", name="Manage layers").click()
|
|
63
|
-
page.once("dialog", lambda dialog: dialog.accept())
|
|
64
63
|
page.locator(".panel.right").get_by_title("Delete layer").click()
|
|
64
|
+
page.get_by_role("button", name="OK").click()
|
|
65
65
|
expect(markers).to_have_count(0)
|
|
66
|
-
page.get_by_role("button", name="Open browser").click()
|
|
67
66
|
expect(page.get_by_text("test datalayer")).to_be_hidden()
|
|
68
|
-
page.once("dialog", lambda dialog: dialog.accept())
|
|
69
67
|
page.get_by_role("button", name="Cancel edits").click()
|
|
70
68
|
page.locator("dialog").get_by_role("button", name="OK").click()
|
|
71
69
|
expect(markers).to_have_count(1)
|
|
@@ -174,8 +172,8 @@ def test_can_restore_version(live_server, openmap, page, datalayer):
|
|
|
174
172
|
page.get_by_role("link", name="Manage layers").click()
|
|
175
173
|
page.locator(".panel.right").get_by_title("Edit", exact=True).click()
|
|
176
174
|
page.get_by_text("Versions").click()
|
|
177
|
-
page.once("dialog", lambda dialog: dialog.accept())
|
|
178
175
|
page.get_by_role("button", name="Restore this version").last.click()
|
|
176
|
+
page.get_by_role("button", name="OK").click()
|
|
179
177
|
expect(marker).to_have_class(re.compile(".*umap-ball-icon.*"))
|
|
180
178
|
|
|
181
179
|
|
|
@@ -196,8 +194,8 @@ def test_deleting_datalayer_should_remove_from_browser_and_layers_list(
|
|
|
196
194
|
page.get_by_role("link", name="Manage layers").click()
|
|
197
195
|
expect(panel.get_by_text("test datalayer")).to_be_visible()
|
|
198
196
|
expect(edit_panel.get_by_text("test datalayer")).to_be_visible()
|
|
199
|
-
page.once("dialog", lambda dialog: dialog.accept())
|
|
200
197
|
page.locator(".panel.right").get_by_title("Delete layer").click()
|
|
198
|
+
page.get_by_role("button", name="OK").click()
|
|
201
199
|
expect(panel.get_by_text("test datalayer")).to_be_hidden()
|
|
202
200
|
expect(edit_panel.get_by_text("test datalayer")).to_be_hidden()
|
|
203
201
|
|
|
@@ -210,6 +208,6 @@ def test_deleting_datalayer_should_remove_from_caption(
|
|
|
210
208
|
page.get_by_role("button", name="About").click()
|
|
211
209
|
page.get_by_role("link", name="Manage layers").click()
|
|
212
210
|
expect(panel.get_by_text("test datalayer")).to_be_visible()
|
|
213
|
-
page.once("dialog", lambda dialog: dialog.accept())
|
|
214
211
|
page.locator(".panel.right").get_by_title("Delete layer").click()
|
|
212
|
+
page.get_by_role("button", name="OK").click()
|
|
215
213
|
expect(panel.get_by_text("test datalayer")).to_be_hidden()
|
|
@@ -40,7 +40,7 @@ def test_map_name_impacts_ui(live_server, page, tilelayer):
|
|
|
40
40
|
|
|
41
41
|
name_input.fill("something else")
|
|
42
42
|
|
|
43
|
-
expect(page.get_by_role("button", name="something else").
|
|
43
|
+
expect(page.get_by_role("button", name="something else").first).to_be_visible()
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
def test_zoomcontrol_impacts_ui(live_server, page, tilelayer):
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import os
|
|
2
3
|
import platform
|
|
3
4
|
import re
|
|
4
5
|
from pathlib import Path
|
|
@@ -70,6 +71,10 @@ def test_umap_import_from_file(live_server, tilelayer, page):
|
|
|
70
71
|
expect(nonloaded).to_have_count(1)
|
|
71
72
|
|
|
72
73
|
|
|
74
|
+
@pytest.mark.skipif(
|
|
75
|
+
os.environ.get("CI", "false") == "true",
|
|
76
|
+
reason="Test is failing intermittently, skipping in the CI",
|
|
77
|
+
)
|
|
73
78
|
def test_umap_import_from_textarea(live_server, tilelayer, page, settings):
|
|
74
79
|
settings.UMAP_ALLOW_ANONYMOUS = True
|
|
75
80
|
page.goto(f"{live_server.url}/map/new/")
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import os
|
|
1
2
|
import re
|
|
2
3
|
|
|
3
4
|
import pytest
|
|
@@ -147,6 +148,10 @@ def test_default_view_latest_with_polygon(map, live_server, page):
|
|
|
147
148
|
expect(layers).to_have_count(1)
|
|
148
149
|
|
|
149
150
|
|
|
151
|
+
@pytest.mark.skipif(
|
|
152
|
+
os.environ.get("CI", "false") == "true",
|
|
153
|
+
reason="Test is failing intermittently, skipping in the CI",
|
|
154
|
+
)
|
|
150
155
|
def test_default_view_locate(browser, live_server, map):
|
|
151
156
|
context = browser.new_context(
|
|
152
157
|
geolocation={"longitude": 8.52967, "latitude": 39.16267},
|
|
@@ -234,8 +234,8 @@ def test_can_delete_datalayer(live_server, map, login, datalayer):
|
|
|
234
234
|
expect(layers).to_have_count(1)
|
|
235
235
|
expect(markers).to_have_count(1)
|
|
236
236
|
page.get_by_role("link", name="Manage layers").click()
|
|
237
|
-
page.once("dialog", lambda dialog: dialog.accept())
|
|
238
237
|
page.locator(".panel.right").get_by_title("Delete layer").click()
|
|
238
|
+
page.get_by_role("button", name="OK").click()
|
|
239
239
|
with page.expect_response(re.compile(r".*/datalayer/delete/.*")):
|
|
240
240
|
page.get_by_role("button", name="Save").click()
|
|
241
241
|
expect(markers).to_have_count(0)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import re
|
|
2
|
+
from copy import deepcopy
|
|
2
3
|
|
|
3
4
|
import pytest
|
|
4
5
|
from playwright.sync_api import expect
|
|
@@ -33,19 +34,9 @@ DATALAYER_DATA = {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
def bootstrap(map, live_server):
|
|
38
|
-
map.settings["properties"]["zoom"] = 6
|
|
39
|
-
map.settings["geometry"] = {
|
|
40
|
-
"type": "Point",
|
|
41
|
-
"coordinates": [8.429, 53.239],
|
|
42
|
-
}
|
|
43
|
-
map.save()
|
|
37
|
+
def test_should_open_popup_on_click(live_server, map, page):
|
|
44
38
|
DataLayerFactory(map=map, data=DATALAYER_DATA)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def test_should_open_popup_on_click(live_server, map, page, bootstrap):
|
|
48
|
-
page.goto(f"{live_server.url}{map.get_absolute_url()}")
|
|
39
|
+
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/53.239/8.429")
|
|
49
40
|
polygon = page.locator("path").first
|
|
50
41
|
expect(polygon).to_have_attribute("fill-opacity", "0.3")
|
|
51
42
|
polygon.click()
|
|
@@ -57,3 +48,12 @@ def test_should_open_popup_on_click(live_server, map, page, bootstrap):
|
|
|
57
48
|
# Close popup
|
|
58
49
|
page.locator("#map").click()
|
|
59
50
|
expect(polygon).to_have_attribute("fill-opacity", "0.3")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_should_not_react_to_click_if_interactive_false(live_server, map, page):
|
|
54
|
+
data = deepcopy(DATALAYER_DATA)
|
|
55
|
+
data["features"][0]["properties"]["_umap_options"] = {"interactive": False}
|
|
56
|
+
DataLayerFactory(map=map, data=data)
|
|
57
|
+
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/53.239/8.429")
|
|
58
|
+
polygon = page.locator("path").first
|
|
59
|
+
expect(polygon).to_have_css("pointer-events", "none")
|