umap-project 1.14.0a5__py3-none-any.whl → 2.0.0a0__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 (224) hide show
  1. umap/__init__.py +1 -1
  2. umap/decorators.py +0 -14
  3. umap/locale/br/LC_MESSAGES/django.mo +0 -0
  4. umap/locale/br/LC_MESSAGES/django.po +137 -85
  5. umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/cs_CZ/LC_MESSAGES/django.po +136 -84
  7. umap/locale/el/LC_MESSAGES/django.mo +0 -0
  8. umap/locale/el/LC_MESSAGES/django.po +136 -84
  9. umap/locale/en/LC_MESSAGES/django.po +128 -88
  10. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  11. umap/locale/es/LC_MESSAGES/django.po +136 -84
  12. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  13. umap/locale/fr/LC_MESSAGES/django.po +131 -91
  14. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  15. umap/locale/hu/LC_MESSAGES/django.po +137 -85
  16. umap/locale/it/LC_MESSAGES/django.mo +0 -0
  17. umap/locale/it/LC_MESSAGES/django.po +136 -84
  18. umap/locale/ms/LC_MESSAGES/django.mo +0 -0
  19. umap/locale/ms/LC_MESSAGES/django.po +136 -84
  20. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  21. umap/locale/pl/LC_MESSAGES/django.po +136 -84
  22. umap/locale/sv/LC_MESSAGES/django.mo +0 -0
  23. umap/locale/sv/LC_MESSAGES/django.po +135 -83
  24. umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
  25. umap/locale/zh_TW/LC_MESSAGES/django.po +143 -91
  26. umap/models.py +23 -1
  27. umap/settings/__init__.py +1 -4
  28. umap/settings/base.py +1 -0
  29. umap/static/umap/base.css +5 -0
  30. umap/static/umap/content.css +185 -13
  31. umap/static/umap/favicons/icon.svg +2 -2
  32. umap/static/umap/img/edit.svg +3 -3
  33. umap/static/umap/img/icon-delete.svg +4 -0
  34. umap/static/umap/img/icon-download.svg +13 -0
  35. umap/static/umap/img/icon-duplicate.svg +5 -0
  36. umap/static/umap/img/icon-edit.svg +12 -0
  37. umap/static/umap/img/icon-share.svg +11 -0
  38. umap/static/umap/img/icon-view.svg +12 -0
  39. umap/static/umap/img/logo.svg +2 -2
  40. umap/static/umap/img/logo_small.svg +2 -2
  41. umap/static/umap/img/marker.svg +4 -0
  42. umap/static/umap/img/opensource.svg +2 -2
  43. umap/static/umap/img/osm.svg +2 -2
  44. umap/static/umap/js/components/fragment.js +1 -1
  45. umap/static/umap/js/modules/browser.js +159 -0
  46. umap/static/umap/js/modules/global.js +3 -1
  47. umap/static/umap/js/modules/request.js +155 -0
  48. umap/static/umap/js/umap.autocomplete.js +28 -38
  49. umap/static/umap/js/umap.controls.js +73 -58
  50. umap/static/umap/js/umap.core.js +4 -9
  51. umap/static/umap/js/umap.datalayer.permissions.js +13 -12
  52. umap/static/umap/js/umap.features.js +51 -49
  53. umap/static/umap/js/umap.forms.js +19 -19
  54. umap/static/umap/js/umap.icon.js +17 -17
  55. umap/static/umap/js/umap.importer.js +2 -1
  56. umap/static/umap/js/umap.js +242 -291
  57. umap/static/umap/js/umap.layer.js +173 -141
  58. umap/static/umap/js/umap.permissions.js +24 -25
  59. umap/static/umap/js/umap.popup.js +14 -14
  60. umap/static/umap/js/umap.share.js +4 -4
  61. umap/static/umap/js/umap.slideshow.js +4 -4
  62. umap/static/umap/js/umap.tableeditor.js +2 -2
  63. umap/static/umap/js/umap.ui.js +1 -1
  64. umap/static/umap/locale/am_ET.js +1 -11
  65. umap/static/umap/locale/am_ET.json +1 -11
  66. umap/static/umap/locale/ar.js +1 -11
  67. umap/static/umap/locale/ar.json +1 -11
  68. umap/static/umap/locale/ast.js +1 -11
  69. umap/static/umap/locale/ast.json +1 -11
  70. umap/static/umap/locale/bg.js +1 -11
  71. umap/static/umap/locale/bg.json +1 -11
  72. umap/static/umap/locale/br.js +1 -11
  73. umap/static/umap/locale/br.json +1 -11
  74. umap/static/umap/locale/ca.js +1 -11
  75. umap/static/umap/locale/ca.json +1 -11
  76. umap/static/umap/locale/cs_CZ.js +1 -11
  77. umap/static/umap/locale/cs_CZ.json +1 -11
  78. umap/static/umap/locale/da.js +1 -11
  79. umap/static/umap/locale/da.json +1 -11
  80. umap/static/umap/locale/de.js +1 -11
  81. umap/static/umap/locale/de.json +1 -11
  82. umap/static/umap/locale/el.js +1 -11
  83. umap/static/umap/locale/el.json +1 -11
  84. umap/static/umap/locale/en.js +1 -11
  85. umap/static/umap/locale/en.json +1 -11
  86. umap/static/umap/locale/en_US.json +1 -11
  87. umap/static/umap/locale/es.js +1 -11
  88. umap/static/umap/locale/es.json +1 -11
  89. umap/static/umap/locale/et.js +1 -11
  90. umap/static/umap/locale/et.json +1 -11
  91. umap/static/umap/locale/fa_IR.js +6 -16
  92. umap/static/umap/locale/fa_IR.json +6 -16
  93. umap/static/umap/locale/fi.js +1 -11
  94. umap/static/umap/locale/fi.json +1 -11
  95. umap/static/umap/locale/fr.js +1 -11
  96. umap/static/umap/locale/fr.json +1 -11
  97. umap/static/umap/locale/gl.js +1 -11
  98. umap/static/umap/locale/gl.json +1 -11
  99. umap/static/umap/locale/he.js +1 -11
  100. umap/static/umap/locale/he.json +1 -11
  101. umap/static/umap/locale/hr.js +1 -11
  102. umap/static/umap/locale/hr.json +1 -11
  103. umap/static/umap/locale/hu.js +1 -11
  104. umap/static/umap/locale/hu.json +1 -11
  105. umap/static/umap/locale/id.js +1 -11
  106. umap/static/umap/locale/id.json +1 -11
  107. umap/static/umap/locale/is.js +1 -11
  108. umap/static/umap/locale/is.json +1 -11
  109. umap/static/umap/locale/it.js +1 -11
  110. umap/static/umap/locale/it.json +1 -11
  111. umap/static/umap/locale/ja.js +1 -11
  112. umap/static/umap/locale/ja.json +1 -11
  113. umap/static/umap/locale/ko.js +1 -11
  114. umap/static/umap/locale/ko.json +1 -11
  115. umap/static/umap/locale/lt.js +1 -11
  116. umap/static/umap/locale/lt.json +1 -11
  117. umap/static/umap/locale/ms.js +1 -11
  118. umap/static/umap/locale/ms.json +1 -11
  119. umap/static/umap/locale/nl.js +1 -11
  120. umap/static/umap/locale/nl.json +1 -11
  121. umap/static/umap/locale/no.js +1 -11
  122. umap/static/umap/locale/no.json +1 -11
  123. umap/static/umap/locale/pl.js +1 -11
  124. umap/static/umap/locale/pl.json +1 -11
  125. umap/static/umap/locale/pl_PL.json +1 -11
  126. umap/static/umap/locale/pt.js +1 -11
  127. umap/static/umap/locale/pt.json +1 -11
  128. umap/static/umap/locale/pt_BR.js +1 -11
  129. umap/static/umap/locale/pt_BR.json +1 -11
  130. umap/static/umap/locale/pt_PT.js +1 -11
  131. umap/static/umap/locale/pt_PT.json +1 -11
  132. umap/static/umap/locale/ro.js +1 -11
  133. umap/static/umap/locale/ro.json +1 -11
  134. umap/static/umap/locale/ru.js +1 -11
  135. umap/static/umap/locale/ru.json +1 -11
  136. umap/static/umap/locale/sk_SK.js +1 -11
  137. umap/static/umap/locale/sk_SK.json +1 -11
  138. umap/static/umap/locale/sl.js +1 -11
  139. umap/static/umap/locale/sl.json +1 -11
  140. umap/static/umap/locale/sr.js +1 -11
  141. umap/static/umap/locale/sr.json +1 -11
  142. umap/static/umap/locale/sv.js +1 -11
  143. umap/static/umap/locale/sv.json +1 -11
  144. umap/static/umap/locale/th_TH.js +1 -11
  145. umap/static/umap/locale/th_TH.json +1 -11
  146. umap/static/umap/locale/tr.js +1 -11
  147. umap/static/umap/locale/tr.json +1 -11
  148. umap/static/umap/locale/uk_UA.js +1 -11
  149. umap/static/umap/locale/uk_UA.json +1 -11
  150. umap/static/umap/locale/vi.js +1 -11
  151. umap/static/umap/locale/vi.json +1 -11
  152. umap/static/umap/locale/vi_VN.json +1 -11
  153. umap/static/umap/locale/zh.js +1 -11
  154. umap/static/umap/locale/zh.json +1 -11
  155. umap/static/umap/locale/zh_CN.json +1 -11
  156. umap/static/umap/locale/zh_TW.Big5.json +1 -11
  157. umap/static/umap/locale/zh_TW.js +17 -27
  158. umap/static/umap/locale/zh_TW.json +17 -27
  159. umap/static/umap/map.css +2 -2
  160. umap/static/umap/nav.css +2 -1
  161. umap/static/umap/test/.eslintrc +0 -1
  162. umap/static/umap/test/Choropleth.js +29 -27
  163. umap/static/umap/test/DataLayer.js +207 -239
  164. umap/static/umap/test/Feature.js +33 -58
  165. umap/static/umap/test/Map.Export.js +11 -11
  166. umap/static/umap/test/Map.js +66 -67
  167. umap/static/umap/test/Marker.js +36 -32
  168. umap/static/umap/test/Polygon.js +95 -95
  169. umap/static/umap/test/Polyline.js +31 -31
  170. umap/static/umap/test/TableEditor.js +29 -25
  171. umap/static/umap/test/_pre.js +2 -7
  172. umap/static/umap/test/index.html +4 -4
  173. umap/static/umap/vendors/contextmenu/leaflet.contextmenu.css +54 -0
  174. umap/static/umap/vendors/contextmenu/leaflet.contextmenu.js +586 -0
  175. umap/static/umap/vendors/csv2geojson/index.js +259 -0
  176. umap/static/umap/vendors/dompurify/purify.js +1633 -0
  177. umap/static/umap/vendors/locatecontrol/L.Control.Locate.css +63 -0
  178. umap/static/umap/vendors/locatecontrol/L.Control.Locate.js +950 -0
  179. umap/static/umap/vendors/minimap/Control.MiniMap.css +88 -0
  180. umap/static/umap/vendors/minimap/Control.MiniMap.js +352 -0
  181. umap/static/umap/vendors/togeojson/togeojson.js +2 -0
  182. umap/templates/auth/user_form.html +3 -2
  183. umap/templates/base.html +1 -0
  184. umap/templates/registration/login.html +51 -36
  185. umap/templates/umap/about_summary.html +1 -1
  186. umap/templates/umap/branding.html +3 -0
  187. umap/templates/umap/content.html +15 -39
  188. umap/templates/umap/header.html +0 -0
  189. umap/templates/umap/home.html +4 -2
  190. umap/templates/umap/js.html +0 -1
  191. umap/templates/umap/map_detail.html +9 -0
  192. umap/templates/umap/map_init.html +1 -1
  193. umap/templates/umap/map_messages.html +4 -2
  194. umap/templates/umap/map_table.html +130 -69
  195. umap/templates/umap/navigation.html +2 -4
  196. umap/templates/umap/user_dashboard.html +29 -6
  197. umap/tests/base.py +1 -1
  198. umap/tests/integration/conftest.py +18 -0
  199. umap/tests/integration/test_anonymous_owned_map.py +6 -3
  200. umap/tests/integration/test_browser.py +166 -6
  201. umap/tests/integration/test_collaborative_editing.py +23 -5
  202. umap/tests/integration/test_dashboard.py +17 -0
  203. umap/tests/integration/test_edit_datalayer.py +4 -3
  204. umap/tests/integration/test_export_map.py +1 -1
  205. umap/tests/integration/test_import.py +9 -4
  206. umap/tests/integration/test_map.py +64 -0
  207. umap/tests/integration/test_map_preview.py +75 -0
  208. umap/tests/integration/test_owned_map.py +11 -25
  209. umap/tests/integration/test_picto.py +3 -3
  210. umap/tests/integration/test_querystring.py +52 -0
  211. umap/tests/integration/test_share.py +22 -0
  212. umap/tests/test_map_views.py +157 -14
  213. umap/tests/test_views.py +50 -11
  214. umap/urls.py +6 -12
  215. umap/views.py +170 -47
  216. {umap_project-1.14.0a5.dist-info → umap_project-2.0.0a0.dist-info}/METADATA +13 -15
  217. {umap_project-1.14.0a5.dist-info → umap_project-2.0.0a0.dist-info}/RECORD +220 -199
  218. umap/static/umap/js/umap.browser.js +0 -148
  219. umap/static/umap/js/umap.xhr.js +0 -304
  220. umap/static/umap/test/Controls.js +0 -100
  221. umap/static/umap/test/Map.Init.js +0 -46
  222. {umap_project-1.14.0a5.dist-info → umap_project-2.0.0a0.dist-info}/WHEEL +0 -0
  223. {umap_project-1.14.0a5.dist-info → umap_project-2.0.0a0.dist-info}/entry_points.txt +0 -0
  224. {umap_project-1.14.0a5.dist-info → umap_project-2.0.0a0.dist-info}/licenses/LICENSE +0 -0
@@ -1,9 +1,14 @@
1
+ import re
2
+ from time import sleep
3
+
1
4
  from playwright.sync_api import expect
2
5
 
3
6
  from umap.models import DataLayer
4
7
 
5
8
  from ..base import DataLayerFactory, MapFactory
6
9
 
10
+ DATALAYER_UPDATE = re.compile(r".*/datalayer/update/.*")
11
+
7
12
 
8
13
  def test_collaborative_editing_create_markers(context, live_server, tilelayer):
9
14
  # Let's create a new map with an empty datalayer
@@ -31,11 +36,17 @@ def test_collaborative_editing_create_markers(context, live_server, tilelayer):
31
36
  map_el_p1.click(position={"x": 200, "y": 200})
32
37
  expect(marker_pane_p1).to_have_count(1)
33
38
 
34
- save_p1.click()
39
+ with page_one.expect_response(DATALAYER_UPDATE):
40
+ save_p1.click()
41
+ # Prefent two layers to be saved on the same second, as we compare them based
42
+ # on time in case of conflict. FIXME do not use time for comparison.
43
+ sleep(1)
35
44
  assert DataLayer.objects.get(pk=datalayer.pk).settings == {
36
45
  "browsable": True,
37
46
  "displayOnLoad": True,
38
47
  "name": "test datalayer",
48
+ "editMode": "advanced",
49
+ "inCaption": True,
39
50
  }
40
51
 
41
52
  # Now navigate to this map from another tab
@@ -60,7 +71,9 @@ def test_collaborative_editing_create_markers(context, live_server, tilelayer):
60
71
  map_el_p2.click(position={"x": 220, "y": 220})
61
72
  expect(marker_pane_p2).to_have_count(2)
62
73
 
63
- save_p2.click()
74
+ with page_two.expect_response(DATALAYER_UPDATE):
75
+ save_p2.click()
76
+ sleep(1)
64
77
  # No change after the save
65
78
  expect(marker_pane_p2).to_have_count(2)
66
79
  assert DataLayer.objects.get(pk=datalayer.pk).settings == {
@@ -75,7 +88,8 @@ def test_collaborative_editing_create_markers(context, live_server, tilelayer):
75
88
  create_marker_p1.click()
76
89
  map_el_p1.click(position={"x": 150, "y": 150})
77
90
  expect(marker_pane_p1).to_have_count(2)
78
- save_p1.click()
91
+ with page_one.expect_response(DATALAYER_UPDATE):
92
+ save_p1.click()
79
93
  # Should now get the other marker too
80
94
  expect(marker_pane_p1).to_have_count(3)
81
95
  assert DataLayer.objects.get(pk=datalayer.pk).settings == {
@@ -92,7 +106,9 @@ def test_collaborative_editing_create_markers(context, live_server, tilelayer):
92
106
  create_marker_p1.click()
93
107
  map_el_p1.click(position={"x": 180, "y": 150})
94
108
  expect(marker_pane_p1).to_have_count(4)
95
- save_p1.click()
109
+ with page_one.expect_response(DATALAYER_UPDATE):
110
+ save_p1.click()
111
+ sleep(1)
96
112
  # Should now get the other marker too
97
113
  assert DataLayer.objects.get(pk=datalayer.pk).settings == {
98
114
  "browsable": True,
@@ -110,7 +126,9 @@ def test_collaborative_editing_create_markers(context, live_server, tilelayer):
110
126
  create_marker_p2.click()
111
127
  map_el_p2.click(position={"x": 250, "y": 150})
112
128
  expect(marker_pane_p2).to_have_count(3)
113
- save_p2.click()
129
+ with page_two.expect_response(DATALAYER_UPDATE):
130
+ save_p2.click()
131
+ sleep(1)
114
132
  # Should now get the other markers too
115
133
  assert DataLayer.objects.get(pk=datalayer.pk).settings == {
116
134
  "browsable": True,
@@ -0,0 +1,17 @@
1
+ import pytest
2
+ from playwright.sync_api import expect
3
+
4
+ from umap.models import Map
5
+
6
+ pytestmark = pytest.mark.django_db
7
+
8
+
9
+ def test_owner_can_delete_map_after_confirmation(map, live_server, login):
10
+ page = login(map.owner)
11
+ page.goto(f"{live_server.url}/en/me")
12
+ delete_button = page.get_by_title("Delete")
13
+ expect(delete_button).to_be_visible()
14
+ page.on("dialog", lambda dialog: dialog.accept())
15
+ with page.expect_navigation():
16
+ delete_button.click()
17
+ assert Map.objects.all().count() == 0
@@ -9,9 +9,10 @@ def test_should_have_fieldset_for_layer_type_properties(page, live_server, tilel
9
9
  expect(button).to_be_visible()
10
10
  button.click()
11
11
 
12
- edit = page.locator("#umap-ui-container").get_by_title("Edit", exact=True)
13
- expect(edit).to_be_visible()
14
- edit.click()
12
+ # Create a layer
13
+ page.get_by_title("Manage layers").click()
14
+ page.get_by_role("button", name="Add a layer").click()
15
+ page.locator("input[name=name]").fill("Layer 1")
15
16
 
16
17
  select = page.locator("#umap-ui-container .umap-field-type select")
17
18
  expect(select).to_be_visible()
@@ -61,7 +61,7 @@ def test_umap_export(map, live_server, datalayer, page):
61
61
  "attribution": "© OSM Contributors",
62
62
  "maxZoom": 18,
63
63
  "minZoom": 0,
64
- "url_template": "https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png",
64
+ "url_template": "https://a.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png",
65
65
  },
66
66
  "tilelayersControl": True,
67
67
  "zoom": 7,
@@ -11,8 +11,9 @@ def test_umap_import_from_file(live_server, datalayer, page):
11
11
  button = page.get_by_title("Import data")
12
12
  expect(button).to_be_visible()
13
13
  button.click()
14
+ file_input = page.locator("input[type='file']")
14
15
  with page.expect_file_chooser() as fc_info:
15
- page.locator("input[type='file']").click()
16
+ file_input.click()
16
17
  file_chooser = fc_info.value
17
18
  path = Path(__file__).parent.parent / "fixtures/display_on_load.umap"
18
19
  file_chooser.set_files(path)
@@ -20,9 +21,13 @@ def test_umap_import_from_file(live_server, datalayer, page):
20
21
  expect(button).to_be_visible()
21
22
  button.click()
22
23
  layers = page.locator(".umap-browse-datalayers li")
23
- expect(layers).to_have_count(3)
24
+ expect(layers).to_have_count(2)
24
25
  nonloaded = page.locator(".umap-browse-datalayers li.off")
25
26
  expect(nonloaded).to_have_count(1)
27
+ assert file_input.input_value()
28
+ # Close the import panel
29
+ page.keyboard.press("Escape")
30
+ assert not file_input.input_value()
26
31
 
27
32
 
28
33
  def test_umap_import_geojson_from_textarea(live_server, datalayer, page):
@@ -32,7 +37,7 @@ def test_umap_import_geojson_from_textarea(live_server, datalayer, page):
32
37
  paths = page.locator("path")
33
38
  expect(markers).to_have_count(0)
34
39
  expect(paths).to_have_count(0)
35
- expect(layers).to_have_count(1)
40
+ expect(layers).to_have_count(0)
36
41
  button = page.get_by_title("Import data")
37
42
  expect(button).to_be_visible()
38
43
  button.click()
@@ -43,7 +48,7 @@ def test_umap_import_geojson_from_textarea(live_server, datalayer, page):
43
48
  button = page.get_by_role("button", name="Import", exact=True)
44
49
  expect(button).to_be_visible()
45
50
  button.click()
46
- # No layer has been created
51
+ # A layer has been created
47
52
  expect(layers).to_have_count(1)
48
53
  expect(markers).to_have_count(2)
49
54
  expect(paths).to_have_count(3)
@@ -12,6 +12,47 @@ from ..base import DataLayerFactory
12
12
  pytestmark = pytest.mark.django_db
13
13
 
14
14
 
15
+ def test_preconnect_for_tilelayer(map, page, live_server, tilelayer):
16
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
17
+ meta = page.locator('link[rel="preconnect"]')
18
+ expect(meta).to_have_count(1)
19
+ expect(meta).to_have_attribute("href", "//a.tile.openstreetmap.fr")
20
+ # Add custom tilelayer
21
+ map.settings["properties"]["tilelayer"] = {
22
+ "name": "OSM Piano FR",
23
+ "maxZoom": 20,
24
+ "minZoom": 0,
25
+ "attribution": "test",
26
+ "url_template": "https://a.piano.tiles.quaidorsay.fr/fr{r}/{z}/{x}/{y}.png",
27
+ }
28
+ map.save()
29
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
30
+ expect(meta).to_have_attribute("href", "//a.piano.tiles.quaidorsay.fr")
31
+ # Add custom tilelayer with variable in domain, should create a preconnect
32
+ map.settings["properties"]["tilelayer"] = {
33
+ "name": "OSM Piano FR",
34
+ "maxZoom": 20,
35
+ "minZoom": 0,
36
+ "attribution": "test",
37
+ "url_template": "https://{s}.piano.tiles.quaidorsay.fr/fr{r}/{z}/{x}/{y}.png",
38
+ }
39
+ map.save()
40
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
41
+ expect(meta).to_have_count(0)
42
+
43
+
44
+ def test_default_view_without_datalayer_should_use_default_center(
45
+ map, live_server, datalayer, page
46
+ ):
47
+ datalayer.settings["displayOnLoad"] = False
48
+ datalayer.save()
49
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
50
+ # Hash is defined, so map is initialized
51
+ expect(page).to_have_url(re.compile(r".*#7/48\..+/13\..+"))
52
+ layers = page.locator(".umap-browse-datalayers li")
53
+ expect(layers).to_have_count(1)
54
+
55
+
15
56
  def test_default_view_latest_without_datalayer_should_use_default_center(
16
57
  map, live_server, datalayer, page
17
58
  ):
@@ -26,6 +67,20 @@ def test_default_view_latest_without_datalayer_should_use_default_center(
26
67
  expect(layers).to_have_count(1)
27
68
 
28
69
 
70
+ def test_default_view_data_without_datalayer_should_use_default_center(
71
+ map, live_server, datalayer, page
72
+ ):
73
+ datalayer.settings["displayOnLoad"] = False
74
+ datalayer.save()
75
+ map.settings["properties"]["defaultView"] = "data"
76
+ map.save()
77
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
78
+ # Hash is defined, so map is initialized
79
+ expect(page).to_have_url(re.compile(r".*#7/48\..+/13\..+"))
80
+ layers = page.locator(".umap-browse-datalayers li")
81
+ expect(layers).to_have_count(1)
82
+
83
+
29
84
  def test_default_view_latest_with_marker(map, live_server, datalayer, page):
30
85
  map.settings["properties"]["defaultView"] = "latest"
31
86
  map.save()
@@ -164,3 +219,12 @@ def test_basic_choropleth_map(map, live_server, page):
164
219
  # Bretagne, Pays de la Loire, AURA
165
220
  paths = page.locator("path[fill='#eff3ff']")
166
221
  expect(paths).to_have_count(3)
222
+
223
+
224
+ def test_minimap_on_load(map, live_server, datalayer, page):
225
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
226
+ expect(page.locator(".leaflet-control-minimap")).to_be_hidden()
227
+ map.settings["properties"]["miniMap"] = True
228
+ map.save()
229
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
230
+ expect(page.locator(".leaflet-control-minimap")).to_be_visible()
@@ -0,0 +1,75 @@
1
+ import json
2
+ from urllib.parse import quote
3
+
4
+ import pytest
5
+ from playwright.sync_api import expect
6
+
7
+ pytestmark = pytest.mark.django_db
8
+
9
+ GEOJSON = {
10
+ "type": "FeatureCollection",
11
+ "features": [
12
+ {
13
+ "type": "Feature",
14
+ "properties": {
15
+ "name": "Niagara Falls",
16
+ },
17
+ "geometry": {
18
+ "type": "Point",
19
+ "coordinates": [-79.04, 43.08],
20
+ },
21
+ }
22
+ ],
23
+ }
24
+ CSV = "name,latitude,longitude\nNiagara Falls,43.08,-79.04"
25
+
26
+
27
+ def test_map_preview(page, live_server, tilelayer):
28
+ page.goto(f"{live_server.url}/map/")
29
+ # Edit mode is not enabled
30
+ edit_button = page.get_by_role("button", name="Edit")
31
+ expect(edit_button).to_be_visible()
32
+
33
+
34
+ def test_map_preview_can_load_remote_geojson(page, live_server, tilelayer):
35
+ def handle(route):
36
+ route.fulfill(json=GEOJSON)
37
+
38
+ # Intercept the route to the proxy
39
+ page.route("*/**/ajax-proxy/**", handle)
40
+
41
+ page.goto(f"{live_server.url}/map/?dataUrl=http://some.org/geo.json")
42
+ markers = page.locator(".leaflet-marker-icon")
43
+ expect(markers).to_have_count(1)
44
+
45
+
46
+ def test_map_preview_can_load_remote_csv(page, live_server, tilelayer):
47
+ def handle(route):
48
+ csv = """name,latitude,longitude\nNiagara Falls,43.08,-79.04"""
49
+ route.fulfill(body=csv)
50
+
51
+ # Intercept the route to the proxy
52
+ page.route("*/**/ajax-proxy/**", handle)
53
+
54
+ page.goto(f"{live_server.url}/map/?dataUrl=http://some.org/geo.csv&dataFormat=csv")
55
+ markers = page.locator(".leaflet-marker-icon")
56
+ expect(markers).to_have_count(1)
57
+
58
+
59
+ def test_map_preview_can_load_geojson_in_querystring(page, live_server, tilelayer):
60
+ page.goto(f"{live_server.url}/map/?data={quote(json.dumps(GEOJSON))}")
61
+ markers = page.locator(".leaflet-marker-icon")
62
+ expect(markers).to_have_count(1)
63
+
64
+
65
+ def test_map_preview_can_load_csv_in_querystring(page, live_server, tilelayer):
66
+ page.goto(f"{live_server.url}/map/?data={quote(CSV)}&dataFormat=csv")
67
+ markers = page.locator(".leaflet-marker-icon")
68
+ expect(markers).to_have_count(1)
69
+
70
+
71
+ def test_map_preview_can_change_styling_from_querystring(page, live_server, tilelayer):
72
+ page.goto(f"{live_server.url}/map/?data={quote(json.dumps(GEOJSON))}&color=DarkRed")
73
+ markers = page.locator(".leaflet-marker-icon .icon_container")
74
+ expect(markers).to_have_count(1)
75
+ expect(markers).to_have_css("background-color", "rgb(139, 0, 0)")
@@ -1,4 +1,4 @@
1
- from time import sleep
1
+ import re
2
2
 
3
3
  import pytest
4
4
  from playwright.sync_api import expect
@@ -8,24 +8,6 @@ from umap.models import DataLayer, Map
8
8
  pytestmark = pytest.mark.django_db
9
9
 
10
10
 
11
- @pytest.fixture
12
- def login(context, settings, live_server):
13
- def do_login(user):
14
- # TODO use storage state to do login only once per session
15
- # https://playwright.dev/python/docs/auth
16
- settings.ENABLE_ACCOUNT_LOGIN = True
17
- page = context.new_page()
18
- page.goto(f"{live_server.url}/en/")
19
- page.locator(".login").click()
20
- page.get_by_placeholder("Username").fill(user.username)
21
- page.get_by_placeholder("Password").fill("123123")
22
- page.locator('#login_form input[type="submit"]').click()
23
- sleep(1) # Time for ajax login POST to proceed
24
- return page
25
-
26
- return do_login
27
-
28
-
29
11
  def test_map_update_with_owner(map, live_server, login):
30
12
  page = login(map.owner)
31
13
  page.goto(f"{live_server.url}{map.get_absolute_url()}")
@@ -183,18 +165,22 @@ def test_create(tilelayer, live_server, login, user):
183
165
  expect(marker).to_have_count(1)
184
166
  save = page.get_by_role("button", name="Save")
185
167
  expect(save).to_be_visible()
186
- save.click()
187
- sleep(1) # Let save ajax go back
168
+ with page.expect_response(re.compile(r".*/datalayer/create/")):
169
+ save.click()
188
170
  expect(marker).to_have_count(1)
189
171
 
190
172
 
191
173
  def test_can_change_perms_after_create(tilelayer, live_server, login, user):
192
174
  page = login(user)
193
175
  page.goto(f"{live_server.url}/en/map/new")
176
+ # Create a layer
177
+ page.get_by_title("Manage layers").click()
178
+ page.get_by_role("button", name="Add a layer").click()
179
+ page.locator("input[name=name]").fill("Layer 1")
194
180
  save = page.get_by_role("button", name="Save")
195
181
  expect(save).to_be_visible()
196
- save.click()
197
- sleep(1) # Let save ajax go back
182
+ with page.expect_response(re.compile(r".*/map/create/")):
183
+ save.click()
198
184
  edit_permissions = page.get_by_title("Update permissions and editors")
199
185
  expect(edit_permissions).to_be_visible()
200
186
  edit_permissions.click()
@@ -228,7 +214,7 @@ def test_can_change_owner(map, live_server, login, user):
228
214
  input.press("Tab")
229
215
  save = page.get_by_role("button", name="Save")
230
216
  expect(save).to_be_visible()
231
- save.click()
232
- sleep(1) # Let save ajax go
217
+ with page.expect_response(re.compile(r".*/update/permissions/.*")):
218
+ save.click()
233
219
  modified = Map.objects.get(pk=map.pk)
234
220
  assert modified.owner == user
@@ -46,7 +46,7 @@ def test_can_change_picto_at_map_level(map, live_server, page, pictos):
46
46
  marker = page.locator(".umap-div-icon img")
47
47
  expect(marker).to_have_count(1)
48
48
  # Should have default img
49
- expect(marker).to_have_attribute("src", "/static/umap/img/marker.png")
49
+ expect(marker).to_have_attribute("src", "/static/umap/img/marker.svg")
50
50
  edit_settings = page.get_by_title("Edit map properties")
51
51
  expect(edit_settings).to_be_visible()
52
52
  edit_settings.click()
@@ -66,7 +66,7 @@ def test_can_change_picto_at_map_level(map, live_server, page, pictos):
66
66
  symbols.click()
67
67
  expect(marker).to_have_attribute("src", "/uploads/pictogram/star.svg")
68
68
  undefine.click()
69
- expect(marker).to_have_attribute("src", "/static/umap/img/marker.png")
69
+ expect(marker).to_have_attribute("src", "/static/umap/img/marker.svg")
70
70
 
71
71
 
72
72
  def test_can_change_picto_at_datalayer_level(map, live_server, page, pictos):
@@ -147,7 +147,7 @@ def test_can_use_remote_url_as_picto(map, live_server, page, pictos):
147
147
  marker = page.locator(".umap-div-icon img")
148
148
  expect(marker).to_have_count(1)
149
149
  # Should have default img
150
- expect(marker).to_have_attribute("src", "/static/umap/img/marker.png")
150
+ expect(marker).to_have_attribute("src", "/static/umap/img/marker.svg")
151
151
  edit_settings = page.get_by_title("Edit map properties")
152
152
  expect(edit_settings).to_be_visible()
153
153
  edit_settings.click()
@@ -0,0 +1,52 @@
1
+ import re
2
+
3
+ import pytest
4
+ from playwright.sync_api import expect
5
+
6
+ pytestmark = pytest.mark.django_db
7
+
8
+
9
+ def test_scale_control(map, live_server, datalayer, page):
10
+ control = page.locator(".leaflet-control-scale")
11
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
12
+ expect(control).to_be_visible()
13
+ page.goto(f"{live_server.url}{map.get_absolute_url()}?scaleControl=false")
14
+ expect(control).to_be_hidden()
15
+
16
+
17
+ def test_datalayers_control(map, live_server, datalayer, page):
18
+ control = page.locator(".umap-browse-toggle")
19
+ box = page.locator(".umap-browse-datalayers")
20
+ more = page.get_by_title("More controls")
21
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
22
+ expect(control).to_be_visible()
23
+ expect(box).to_be_hidden()
24
+ page.goto(f"{live_server.url}{map.get_absolute_url()}?datalayersControl=true")
25
+ expect(control).to_be_visible()
26
+ expect(box).to_be_hidden()
27
+ page.goto(f"{live_server.url}{map.get_absolute_url()}?datalayersControl=null")
28
+ expect(control).to_be_hidden()
29
+ expect(more).to_be_visible()
30
+ more.click()
31
+ expect(control).to_be_visible()
32
+ expect(box).to_be_hidden()
33
+ page.goto(f"{live_server.url}{map.get_absolute_url()}?datalayersControl=false")
34
+ expect(control).to_be_hidden()
35
+ expect(more).to_be_visible()
36
+ more.click()
37
+ expect(control).to_be_hidden()
38
+ expect(box).to_be_hidden()
39
+ page.goto(f"{live_server.url}{map.get_absolute_url()}?datalayersControl=expanded")
40
+ expect(control).to_be_hidden()
41
+ expect(box).to_be_visible()
42
+
43
+
44
+ def test_can_deactivate_wheel_from_query_string(map, live_server, page):
45
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
46
+ expect(page).to_have_url(re.compile(r".*#7/.+"))
47
+ page.mouse.wheel(0, 1)
48
+ expect(page).to_have_url(re.compile(r".*#6/.+"))
49
+ page.goto(f"{live_server.url}{map.get_absolute_url()}?scrollWheelZoom=false")
50
+ expect(page).to_have_url(re.compile(r".*#7/.+"))
51
+ page.mouse.wheel(0, 1)
52
+ expect(page).to_have_url(re.compile(r".*#7/.+"))
@@ -0,0 +1,22 @@
1
+ import re
2
+
3
+ import pytest
4
+ from playwright.sync_api import expect
5
+
6
+ pytestmark = pytest.mark.django_db
7
+
8
+
9
+ def test_iframe_code(map, live_server, datalayer, page):
10
+ page.goto(f"{live_server.url}{map.get_absolute_url()}?share")
11
+ textarea = page.locator(".umap-share-iframe")
12
+ expect(textarea).to_be_visible()
13
+ expect(textarea).to_have_text(re.compile('src="'))
14
+ expect(textarea).to_have_text(re.compile('href="'))
15
+ # We should ave both, once for iframe link, once for full screen
16
+ expect(textarea).to_have_text(re.compile("scrollWheelZoom=true"))
17
+ expect(textarea).to_have_text(re.compile("scrollWheelZoom=false"))
18
+ expect(textarea).not_to_have_text(re.compile(f"datalayers={datalayer.pk}"))
19
+ # Open options
20
+ page.get_by_text("Embed and link options").click()
21
+ page.get_by_title("Keep current visible layers").click()
22
+ expect(textarea).to_have_text(re.compile(f"datalayers={datalayer.pk}"))