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.

Files changed (104) hide show
  1. umap/__init__.py +1 -1
  2. umap/admin.py +64 -1
  3. umap/context_processors.py +1 -0
  4. umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  5. umap/locale/cs_CZ/LC_MESSAGES/django.po +96 -92
  6. umap/locale/de/LC_MESSAGES/django.mo +0 -0
  7. umap/locale/de/LC_MESSAGES/django.po +19 -18
  8. umap/locale/en/LC_MESSAGES/django.po +47 -43
  9. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  10. umap/locale/fr/LC_MESSAGES/django.po +51 -47
  11. umap/locale/pt/LC_MESSAGES/django.mo +0 -0
  12. umap/locale/pt/LC_MESSAGES/django.po +64 -60
  13. umap/management/commands/clean_tilelayer.py +152 -0
  14. umap/management/commands/purge_purgatory.py +28 -0
  15. umap/models.py +27 -2
  16. umap/settings/base.py +2 -0
  17. umap/static/umap/base.css +4 -4
  18. umap/static/umap/css/contextmenu.css +5 -0
  19. umap/static/umap/css/icon.css +7 -2
  20. umap/static/umap/img/16-white.svg +9 -2
  21. umap/static/umap/img/16.svg +3 -0
  22. umap/static/umap/img/source/16-white.svg +10 -3
  23. umap/static/umap/img/source/16.svg +4 -1
  24. umap/static/umap/js/modules/autocomplete.js +7 -3
  25. umap/static/umap/js/modules/browser.js +7 -1
  26. umap/static/umap/js/modules/caption.js +6 -1
  27. umap/static/umap/js/modules/data/features.js +176 -2
  28. umap/static/umap/js/modules/data/layer.js +31 -26
  29. umap/static/umap/js/modules/formatter.js +3 -2
  30. umap/static/umap/js/modules/global.js +2 -0
  31. umap/static/umap/js/modules/importers/communesfr.js +13 -1
  32. umap/static/umap/js/modules/permissions.js +123 -93
  33. umap/static/umap/js/modules/rendering/ui.js +37 -212
  34. umap/static/umap/js/modules/sync/engine.js +365 -14
  35. umap/static/umap/js/modules/sync/hlc.js +106 -0
  36. umap/static/umap/js/modules/sync/updaters.js +4 -4
  37. umap/static/umap/js/modules/sync/websocket.js +1 -1
  38. umap/static/umap/js/modules/ui/base.js +2 -2
  39. umap/static/umap/js/modules/ui/contextmenu.js +34 -17
  40. umap/static/umap/js/modules/urls.js +5 -1
  41. umap/static/umap/js/modules/utils.js +5 -1
  42. umap/static/umap/js/umap.controls.js +47 -47
  43. umap/static/umap/js/umap.core.js +3 -3
  44. umap/static/umap/js/umap.forms.js +3 -1
  45. umap/static/umap/js/umap.js +95 -112
  46. umap/static/umap/locale/br.js +13 -4
  47. umap/static/umap/locale/br.json +13 -4
  48. umap/static/umap/locale/ca.js +21 -12
  49. umap/static/umap/locale/ca.json +21 -12
  50. umap/static/umap/locale/cs_CZ.js +87 -78
  51. umap/static/umap/locale/cs_CZ.json +87 -78
  52. umap/static/umap/locale/de.js +17 -8
  53. umap/static/umap/locale/de.json +17 -8
  54. umap/static/umap/locale/en.js +9 -2
  55. umap/static/umap/locale/en.json +9 -2
  56. umap/static/umap/locale/eu.js +10 -3
  57. umap/static/umap/locale/eu.json +10 -3
  58. umap/static/umap/locale/fa_IR.js +11 -4
  59. umap/static/umap/locale/fa_IR.json +11 -4
  60. umap/static/umap/locale/fr.js +11 -4
  61. umap/static/umap/locale/fr.json +11 -4
  62. umap/static/umap/locale/hu.js +10 -3
  63. umap/static/umap/locale/hu.json +10 -3
  64. umap/static/umap/locale/pt.js +17 -8
  65. umap/static/umap/locale/pt.json +17 -8
  66. umap/static/umap/locale/pt_PT.js +13 -4
  67. umap/static/umap/locale/pt_PT.json +13 -4
  68. umap/static/umap/locale/zh_TW.js +13 -4
  69. umap/static/umap/locale/zh_TW.json +13 -4
  70. umap/static/umap/map.css +7 -22
  71. umap/static/umap/unittests/hlc.js +158 -0
  72. umap/static/umap/unittests/sync.js +321 -15
  73. umap/static/umap/unittests/utils.js +23 -0
  74. umap/static/umap/vendors/georsstogeojson/GeoRSSToGeoJSON.js +111 -80
  75. umap/templates/umap/dashboard_menu.html +4 -2
  76. umap/templates/umap/js.html +0 -4
  77. umap/tests/integration/test_anonymous_owned_map.py +1 -0
  78. umap/tests/integration/test_basics.py +1 -1
  79. umap/tests/integration/test_circles_layer.py +12 -0
  80. umap/tests/integration/test_datalayer.py +5 -0
  81. umap/tests/integration/test_draw_polygon.py +17 -9
  82. umap/tests/integration/test_draw_polyline.py +12 -8
  83. umap/tests/integration/test_edit_datalayer.py +4 -6
  84. umap/tests/integration/test_edit_map.py +1 -1
  85. umap/tests/integration/test_import.py +5 -0
  86. umap/tests/integration/test_map.py +5 -0
  87. umap/tests/integration/test_owned_map.py +1 -1
  88. umap/tests/integration/test_view_polygon.py +12 -12
  89. umap/tests/integration/test_websocket_sync.py +65 -3
  90. umap/tests/test_clean_tilelayer.py +83 -0
  91. umap/tests/test_datalayer.py +24 -0
  92. umap/tests/test_map_views.py +1 -0
  93. umap/tests/test_purge_purgatory.py +25 -0
  94. umap/tests/test_websocket_server.py +22 -0
  95. umap/urls.py +5 -1
  96. umap/views.py +6 -3
  97. umap/websocket_server.py +130 -27
  98. {umap_project-2.6.3.dist-info → umap_project-2.7.0b0.dist-info}/METADATA +9 -9
  99. {umap_project-2.6.3.dist-info → umap_project-2.7.0b0.dist-info}/RECORD +102 -97
  100. umap/static/umap/vendors/contextmenu/leaflet.contextmenu.min.css +0 -1
  101. umap/static/umap/vendors/contextmenu/leaflet.contextmenu.min.js +0 -7
  102. {umap_project-2.6.3.dist-info → umap_project-2.7.0b0.dist-info}/WHEEL +0 -0
  103. {umap_project-2.6.3.dist-info → umap_project-2.7.0b0.dist-info}/entry_points.txt +0 -0
  104. {umap_project-2.6.3.dist-info → umap_project-2.7.0b0.dist-info}/licenses/LICENSE +0 -0
@@ -1,89 +1,120 @@
1
- var GeoRSSToGeoJSON = function (dom, options) {
1
+ export function parse(dom, options) {
2
+ const g = {
3
+ type: 'FeatureCollection',
4
+ features: [],
5
+ }
2
6
 
3
- function get(x, y) { return x.getElementsByTagName(y); }
4
- function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; }
5
- function norm(el) { if (el.normalize) { el.normalize(); } return el; }
6
- function nodeVal(x) { if (x) {norm(x);} return x && x.firstChild && x.firstChild.nodeValue; }
7
- function attr(x, y) { return x.getAttribute(y); }
8
-
9
- var g = {
10
- type: 'FeatureCollection',
11
- features: []
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
- function geom (node) {
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
- function p(c) {return parseFloat(c);}
17
- function r(c) {return c.reverse().map(p);} // we have latlon we want lonlat
18
- function e(f) {var _=[]; for (var i=0; i<f.length; i+=2) {_.push(r(f.slice(i, i+2)));} return _;}
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
- var type, coordinates;
55
+ let type
56
+ let coordinates
21
57
 
22
- NODE = node;
23
- if (get1(node, 'geo:long')) {
24
- type = 'Point';
25
- coordinates = [p(nodeVal(get1(node, 'geo:long'))), p(nodeVal(get1(node, 'geo:lat')))];
26
- } else if (get1(node, 'long')) {
27
- type = 'Point';
28
- coordinates = [p(nodeVal(get1(node, 'long'))), p(nodeVal(get1(node, 'lat')))];
29
- } else if (get1(node, 'georss:point')) {
30
- type = 'Point';
31
- coordinates = r(nodeVal(get1(node, 'georss:point')).split(' '));
32
- } else if (get1(node, 'point')) {
33
- type = 'Point';
34
- coordinates = r(nodeVal(get1(node, 'point')).split(' '));
35
- } else {
36
- var line = get1(node, 'georss:line'),
37
- poly = get1(node, 'georss:polygon');
38
- if (line || poly) {
39
- type = line ? 'LineString' : 'Polygon';
40
- var tag = line ? 'georss:line' : 'georss:polygon';
41
- coordinates = nodeVal(get1(node, tag)).split(' ');
42
- if (coordinates.length % 2 !== 0) return;
43
- coordinates = e(coordinates);
44
- if (poly) {
45
- coordinates = [coordinates];
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
- function processOne (node) {
58
- var geometry = geom(node);
59
- // TODO collect and fire errors
60
- if (!geometry) return;
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
- var items = get(dom, 'item');
84
- for (var i = 0; i < items.length; i++) {
85
- processOne(items[i]);
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
- return g;
88
- };
89
- if (typeof module !== 'undefined') module.exports = {GeoRSSToGeoJSON: GeoRSSToGeoJSON};
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
- <a {% if selected == "profile" %}class="selected"{% endif %}
11
- href="{% url 'user_profile' %}">{% trans "My profile" %}</a>
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>
@@ -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.get_by_text("My Dashboard (Joe)")).to_be_visible()
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("link", name="Transform to lines")).to_be_hidden()
165
- expect(page.get_by_role("link", name="Remove shape from the multi")).to_be_visible()
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("link", name="Transform to lines")).to_be_hidden()
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("link", name="Transfer shape to edited feature").click()
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("link", name="Extract shape to separate feature")
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("link", name="Extract shape to separate feature")
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("link", name="Extract shape to separate feature")
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("link", name="Clone this feature").click()
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("link", name="Transform to lines").click()
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("link", name="Transform to polygon")).to_be_hidden()
161
- expect(page.get_by_role("link", name="Remove shape from the multi")).to_be_visible()
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("link", name="Transfer shape to edited feature").click()
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("link", name="Transfer shape to edited feature").click()
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("link", name="Extract shape to separate feature")
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("link", name="Clone this feature").click()
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("link", name="Transform to polygon").click()
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
- map.get_by_role("link", name="Merge lines").click()
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").nth(1)).to_be_visible()
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
- @pytest.fixture
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")