umap-project 2.7.3__py3-none-any.whl → 2.8.0__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.
Files changed (292) hide show
  1. umap/__init__.py +1 -1
  2. umap/forms.py +4 -14
  3. umap/locale/am_ET/LC_MESSAGES/django.mo +0 -0
  4. umap/locale/am_ET/LC_MESSAGES/django.po +278 -151
  5. umap/locale/ar/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/ar/LC_MESSAGES/django.po +335 -141
  7. umap/locale/bg/LC_MESSAGES/django.mo +0 -0
  8. umap/locale/bg/LC_MESSAGES/django.po +279 -152
  9. umap/locale/br/LC_MESSAGES/django.mo +0 -0
  10. umap/locale/br/LC_MESSAGES/django.po +95 -79
  11. umap/locale/ca/LC_MESSAGES/django.mo +0 -0
  12. umap/locale/ca/LC_MESSAGES/django.po +85 -68
  13. umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  14. umap/locale/cs_CZ/LC_MESSAGES/django.po +78 -66
  15. umap/locale/da/LC_MESSAGES/django.mo +0 -0
  16. umap/locale/da/LC_MESSAGES/django.po +280 -153
  17. umap/locale/de/LC_MESSAGES/django.mo +0 -0
  18. umap/locale/de/LC_MESSAGES/django.po +80 -64
  19. umap/locale/el/LC_MESSAGES/django.mo +0 -0
  20. umap/locale/el/LC_MESSAGES/django.po +82 -66
  21. umap/locale/en/LC_MESSAGES/django.po +73 -61
  22. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  23. umap/locale/es/LC_MESSAGES/django.po +75 -63
  24. umap/locale/et/LC_MESSAGES/django.mo +0 -0
  25. umap/locale/et/LC_MESSAGES/django.po +280 -153
  26. umap/locale/eu/LC_MESSAGES/django.mo +0 -0
  27. umap/locale/eu/LC_MESSAGES/django.po +82 -66
  28. umap/locale/fa_IR/LC_MESSAGES/django.mo +0 -0
  29. umap/locale/fa_IR/LC_MESSAGES/django.po +80 -64
  30. umap/locale/fi/LC_MESSAGES/django.mo +0 -0
  31. umap/locale/fi/LC_MESSAGES/django.po +278 -151
  32. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  33. umap/locale/fr/LC_MESSAGES/django.po +75 -63
  34. umap/locale/gl/LC_MESSAGES/django.mo +0 -0
  35. umap/locale/gl/LC_MESSAGES/django.po +280 -153
  36. umap/locale/he/LC_MESSAGES/django.mo +0 -0
  37. umap/locale/he/LC_MESSAGES/django.po +281 -154
  38. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  39. umap/locale/hu/LC_MESSAGES/django.po +80 -64
  40. umap/locale/is/LC_MESSAGES/django.mo +0 -0
  41. umap/locale/is/LC_MESSAGES/django.po +280 -153
  42. umap/locale/it/LC_MESSAGES/django.mo +0 -0
  43. umap/locale/it/LC_MESSAGES/django.po +82 -66
  44. umap/locale/ja/LC_MESSAGES/django.mo +0 -0
  45. umap/locale/ja/LC_MESSAGES/django.po +280 -153
  46. umap/locale/ko/LC_MESSAGES/django.mo +0 -0
  47. umap/locale/ko/LC_MESSAGES/django.po +280 -153
  48. umap/locale/lt/LC_MESSAGES/django.mo +0 -0
  49. umap/locale/lt/LC_MESSAGES/django.po +280 -153
  50. umap/locale/ms/LC_MESSAGES/django.mo +0 -0
  51. umap/locale/ms/LC_MESSAGES/django.po +82 -66
  52. umap/locale/nl/LC_MESSAGES/django.mo +0 -0
  53. umap/locale/nl/LC_MESSAGES/django.po +280 -153
  54. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  55. umap/locale/pl/LC_MESSAGES/django.po +82 -66
  56. umap/locale/pt/LC_MESSAGES/django.mo +0 -0
  57. umap/locale/pt/LC_MESSAGES/django.po +75 -63
  58. umap/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
  59. umap/locale/pt_BR/LC_MESSAGES/django.po +280 -153
  60. umap/locale/pt_PT/LC_MESSAGES/django.mo +0 -0
  61. umap/locale/pt_PT/LC_MESSAGES/django.po +280 -153
  62. umap/locale/ru/LC_MESSAGES/django.mo +0 -0
  63. umap/locale/ru/LC_MESSAGES/django.po +280 -153
  64. umap/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
  65. umap/locale/sk_SK/LC_MESSAGES/django.po +280 -153
  66. umap/locale/sl/LC_MESSAGES/django.mo +0 -0
  67. umap/locale/sl/LC_MESSAGES/django.po +280 -153
  68. umap/locale/sr/LC_MESSAGES/django.mo +0 -0
  69. umap/locale/sr/LC_MESSAGES/django.po +280 -153
  70. umap/locale/sv/LC_MESSAGES/django.mo +0 -0
  71. umap/locale/sv/LC_MESSAGES/django.po +81 -65
  72. umap/locale/th_TH/LC_MESSAGES/django.mo +0 -0
  73. umap/locale/th_TH/LC_MESSAGES/django.po +257 -185
  74. umap/locale/tr/LC_MESSAGES/django.mo +0 -0
  75. umap/locale/tr/LC_MESSAGES/django.po +280 -153
  76. umap/locale/uk_UA/LC_MESSAGES/django.mo +0 -0
  77. umap/locale/uk_UA/LC_MESSAGES/django.po +280 -153
  78. umap/locale/vi/LC_MESSAGES/django.mo +0 -0
  79. umap/locale/vi/LC_MESSAGES/django.po +278 -151
  80. umap/locale/zh/LC_MESSAGES/django.mo +0 -0
  81. umap/locale/zh/LC_MESSAGES/django.po +278 -151
  82. umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
  83. umap/locale/zh_TW/LC_MESSAGES/django.po +97 -81
  84. umap/management/commands/empty_trash.py +35 -0
  85. umap/management/commands/migrate_to_S3.py +29 -0
  86. umap/migrations/0023_alter_datalayer_uuid.py +19 -0
  87. umap/migrations/0024_alter_map_share_status.py +30 -0
  88. umap/migrations/0025_alter_datalayer_geojson.py +24 -0
  89. umap/models.py +68 -116
  90. umap/settings/base.py +23 -3
  91. umap/settings/local_s3.py +45 -0
  92. umap/static/umap/base.css +3 -603
  93. umap/static/umap/content.css +5 -3
  94. umap/static/umap/css/bar.css +202 -0
  95. umap/static/umap/css/form.css +620 -0
  96. umap/static/umap/css/icon.css +21 -1
  97. umap/static/umap/css/popup.css +125 -0
  98. umap/static/umap/img/16-white.svg +16 -4
  99. umap/static/umap/img/16.svg +1 -1
  100. umap/static/umap/img/source/16-white.svg +46 -45
  101. umap/static/umap/img/source/16.svg +1 -753
  102. umap/static/umap/js/components/fragment.js +3 -1
  103. umap/static/umap/js/modules/browser.js +20 -19
  104. umap/static/umap/js/modules/caption.js +21 -22
  105. umap/static/umap/js/modules/data/features.js +120 -78
  106. umap/static/umap/js/modules/data/layer.js +195 -153
  107. umap/static/umap/js/modules/facets.js +9 -9
  108. umap/static/umap/js/modules/formatter.js +5 -5
  109. umap/static/umap/js/modules/global.js +4 -52
  110. umap/static/umap/js/modules/help.js +18 -21
  111. umap/static/umap/js/modules/importer.js +133 -56
  112. umap/static/umap/js/modules/importers/cadastrefr.js +4 -0
  113. umap/static/umap/js/modules/importers/geodatamine.js +3 -3
  114. umap/static/umap/js/modules/importers/overpass.js +5 -0
  115. umap/static/umap/js/modules/permissions.js +85 -87
  116. umap/static/umap/js/modules/rendering/icon.js +2 -1
  117. umap/static/umap/js/modules/rendering/layers/base.js +15 -15
  118. umap/static/umap/js/modules/rendering/layers/classified.js +1 -1
  119. umap/static/umap/js/modules/rendering/layers/cluster.js +1 -1
  120. umap/static/umap/js/modules/rendering/layers/heat.js +1 -1
  121. umap/static/umap/js/modules/rendering/map.js +390 -0
  122. umap/static/umap/js/modules/rendering/popup.js +19 -19
  123. umap/static/umap/js/modules/rendering/template.js +88 -21
  124. umap/static/umap/js/modules/rendering/ui.js +63 -14
  125. umap/static/umap/js/modules/request.js +2 -2
  126. umap/static/umap/js/modules/rules.js +22 -25
  127. umap/static/umap/js/modules/saving.js +47 -0
  128. umap/static/umap/js/modules/schema.js +6 -0
  129. umap/static/umap/js/modules/share.js +21 -24
  130. umap/static/umap/js/modules/slideshow.js +24 -20
  131. umap/static/umap/js/modules/sync/updaters.js +7 -9
  132. umap/static/umap/js/modules/tableeditor.js +20 -19
  133. umap/static/umap/js/modules/ui/bar.js +196 -0
  134. umap/static/umap/js/modules/ui/dialog.js +5 -0
  135. umap/static/umap/js/modules/ui/panel.js +10 -9
  136. umap/static/umap/js/modules/umap.js +1691 -0
  137. umap/static/umap/js/modules/urls.js +2 -2
  138. umap/static/umap/js/modules/utils.js +22 -6
  139. umap/static/umap/js/umap.controls.js +81 -305
  140. umap/static/umap/js/umap.core.js +29 -50
  141. umap/static/umap/js/umap.forms.js +78 -27
  142. umap/static/umap/keycloak.png +0 -0
  143. umap/static/umap/locale/am_ET.js +26 -10
  144. umap/static/umap/locale/am_ET.json +26 -10
  145. umap/static/umap/locale/ar.js +26 -10
  146. umap/static/umap/locale/ar.json +26 -10
  147. umap/static/umap/locale/ast.js +26 -10
  148. umap/static/umap/locale/ast.json +26 -10
  149. umap/static/umap/locale/bg.js +26 -10
  150. umap/static/umap/locale/bg.json +26 -10
  151. umap/static/umap/locale/br.js +27 -20
  152. umap/static/umap/locale/br.json +27 -20
  153. umap/static/umap/locale/ca.js +32 -29
  154. umap/static/umap/locale/ca.json +32 -29
  155. umap/static/umap/locale/cs_CZ.js +24 -17
  156. umap/static/umap/locale/cs_CZ.json +24 -17
  157. umap/static/umap/locale/da.js +26 -10
  158. umap/static/umap/locale/da.json +26 -10
  159. umap/static/umap/locale/de.js +21 -14
  160. umap/static/umap/locale/de.json +21 -14
  161. umap/static/umap/locale/el.js +28 -12
  162. umap/static/umap/locale/el.json +28 -12
  163. umap/static/umap/locale/en.js +14 -9
  164. umap/static/umap/locale/en.json +14 -9
  165. umap/static/umap/locale/en_US.json +26 -10
  166. umap/static/umap/locale/es.js +16 -13
  167. umap/static/umap/locale/es.json +16 -13
  168. umap/static/umap/locale/et.js +26 -10
  169. umap/static/umap/locale/et.json +26 -10
  170. umap/static/umap/locale/eu.js +16 -9
  171. umap/static/umap/locale/eu.json +16 -9
  172. umap/static/umap/locale/fa_IR.js +16 -9
  173. umap/static/umap/locale/fa_IR.json +16 -9
  174. umap/static/umap/locale/fi.js +26 -10
  175. umap/static/umap/locale/fi.json +26 -10
  176. umap/static/umap/locale/fr.js +14 -9
  177. umap/static/umap/locale/fr.json +14 -9
  178. umap/static/umap/locale/gl.js +26 -10
  179. umap/static/umap/locale/gl.json +26 -10
  180. umap/static/umap/locale/he.js +26 -10
  181. umap/static/umap/locale/he.json +26 -10
  182. umap/static/umap/locale/hr.js +26 -10
  183. umap/static/umap/locale/hr.json +26 -10
  184. umap/static/umap/locale/hu.js +16 -9
  185. umap/static/umap/locale/hu.json +16 -9
  186. umap/static/umap/locale/id.js +26 -10
  187. umap/static/umap/locale/id.json +26 -10
  188. umap/static/umap/locale/is.js +26 -10
  189. umap/static/umap/locale/is.json +26 -10
  190. umap/static/umap/locale/it.js +26 -10
  191. umap/static/umap/locale/it.json +26 -10
  192. umap/static/umap/locale/ja.js +26 -10
  193. umap/static/umap/locale/ja.json +26 -10
  194. umap/static/umap/locale/ko.js +26 -10
  195. umap/static/umap/locale/ko.json +26 -10
  196. umap/static/umap/locale/lt.js +26 -10
  197. umap/static/umap/locale/lt.json +26 -10
  198. umap/static/umap/locale/ms.js +28 -12
  199. umap/static/umap/locale/ms.json +28 -12
  200. umap/static/umap/locale/nl.js +28 -12
  201. umap/static/umap/locale/nl.json +28 -12
  202. umap/static/umap/locale/no.js +26 -10
  203. umap/static/umap/locale/no.json +26 -10
  204. umap/static/umap/locale/pl.js +28 -12
  205. umap/static/umap/locale/pl.json +28 -12
  206. umap/static/umap/locale/pl_PL.json +26 -10
  207. umap/static/umap/locale/pt.js +16 -9
  208. umap/static/umap/locale/pt.json +16 -9
  209. umap/static/umap/locale/pt_BR.js +26 -10
  210. umap/static/umap/locale/pt_BR.json +26 -10
  211. umap/static/umap/locale/pt_PT.js +16 -9
  212. umap/static/umap/locale/pt_PT.json +16 -9
  213. umap/static/umap/locale/ro.js +26 -10
  214. umap/static/umap/locale/ro.json +26 -10
  215. umap/static/umap/locale/ru.js +26 -10
  216. umap/static/umap/locale/ru.json +26 -10
  217. umap/static/umap/locale/si.js +7 -7
  218. umap/static/umap/locale/si.json +7 -7
  219. umap/static/umap/locale/sk_SK.js +26 -10
  220. umap/static/umap/locale/sk_SK.json +26 -10
  221. umap/static/umap/locale/sl.js +26 -10
  222. umap/static/umap/locale/sl.json +26 -10
  223. umap/static/umap/locale/sr.js +26 -10
  224. umap/static/umap/locale/sr.json +26 -10
  225. umap/static/umap/locale/sv.js +27 -11
  226. umap/static/umap/locale/sv.json +27 -11
  227. umap/static/umap/locale/th_TH.js +28 -12
  228. umap/static/umap/locale/th_TH.json +28 -12
  229. umap/static/umap/locale/tr.js +26 -10
  230. umap/static/umap/locale/tr.json +26 -10
  231. umap/static/umap/locale/uk_UA.js +26 -10
  232. umap/static/umap/locale/uk_UA.json +26 -10
  233. umap/static/umap/locale/vi.js +26 -10
  234. umap/static/umap/locale/vi.json +26 -10
  235. umap/static/umap/locale/vi_VN.json +26 -10
  236. umap/static/umap/locale/zh.js +26 -10
  237. umap/static/umap/locale/zh.json +26 -10
  238. umap/static/umap/locale/zh_CN.json +26 -10
  239. umap/static/umap/locale/zh_TW.Big5.json +26 -10
  240. umap/static/umap/locale/zh_TW.js +34 -27
  241. umap/static/umap/locale/zh_TW.json +34 -27
  242. umap/static/umap/map.css +39 -530
  243. umap/static/umap/unittests/URLs.js +15 -15
  244. umap/static/umap/unittests/utils.js +23 -1
  245. umap/static/umap/vars.css +2 -1
  246. umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +5 -1
  247. umap/storage/__init__.py +3 -0
  248. umap/storage/fs.py +101 -0
  249. umap/storage/s3.py +61 -0
  250. umap/templates/base.html +2 -0
  251. umap/templates/registration/login.html +7 -6
  252. umap/templates/umap/components/alerts/alert.html +4 -0
  253. umap/templates/umap/css.html +6 -0
  254. umap/templates/umap/js.html +3 -2
  255. umap/templates/umap/map_init.html +6 -5
  256. umap/templates/umap/user_dashboard.html +20 -19
  257. umap/tests/base.py +5 -1
  258. umap/tests/fixtures/test_upload_simple_marker.json +19 -0
  259. umap/tests/integration/conftest.py +2 -1
  260. umap/tests/integration/test_anonymous_owned_map.py +18 -10
  261. umap/tests/integration/test_browser.py +16 -1
  262. umap/tests/integration/test_dashboard.py +1 -1
  263. umap/tests/integration/test_edit_datalayer.py +29 -7
  264. umap/tests/integration/test_import.py +28 -6
  265. umap/tests/integration/test_optimistic_merge.py +31 -8
  266. umap/tests/integration/test_owned_map.py +22 -16
  267. umap/tests/integration/test_popup.py +44 -0
  268. umap/tests/integration/test_save.py +35 -0
  269. umap/tests/integration/test_view_marker.py +12 -0
  270. umap/tests/integration/test_view_polyline.py +257 -0
  271. umap/tests/integration/test_websocket_sync.py +81 -9
  272. umap/tests/test_dashboard.py +82 -0
  273. umap/tests/test_datalayer.py +6 -7
  274. umap/tests/test_datalayer_s3.py +135 -0
  275. umap/tests/test_datalayer_views.py +28 -10
  276. umap/tests/test_empty_trash.py +34 -0
  277. umap/tests/test_map.py +12 -3
  278. umap/tests/test_map_views.py +69 -37
  279. umap/tests/test_statics.py +1 -1
  280. umap/tests/test_team_views.py +35 -1
  281. umap/tests/test_views.py +31 -52
  282. umap/urls.py +3 -3
  283. umap/views.py +126 -90
  284. {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/METADATA +16 -13
  285. {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/RECORD +289 -269
  286. umap/management/commands/purge_purgatory.py +0 -28
  287. umap/static/umap/js/umap.js +0 -1903
  288. umap/tests/test_purge_purgatory.py +0 -25
  289. /umap/{storage.py → storage/staticfiles.py} +0 -0
  290. {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/WHEEL +0 -0
  291. {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/entry_points.txt +0 -0
  292. {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,3 +1,5 @@
1
+ from pathlib import Path
2
+
1
3
  import pytest
2
4
  from playwright.sync_api import expect
3
5
 
@@ -49,3 +51,258 @@ def test_should_open_popup_on_click(live_server, map, page, bootstrap):
49
51
  # Close popup
50
52
  page.locator("#map").click()
51
53
  expect(line).to_have_attribute("stroke-opacity", "0.5")
54
+
55
+
56
+ def test_can_use_measure_on_name(live_server, map, page):
57
+ data = {
58
+ "type": "FeatureCollection",
59
+ "features": [
60
+ {
61
+ "type": "Feature",
62
+ "properties": {"name": "linestring"},
63
+ "geometry": {
64
+ "type": "LineString",
65
+ "coordinates": [
66
+ [11.25, 53.585984],
67
+ [10.151367, 52.975108],
68
+ ],
69
+ },
70
+ },
71
+ {
72
+ "type": "Feature",
73
+ "properties": {"name": "multilinestring"},
74
+ "geometry": {
75
+ "type": "MultiLineString",
76
+ "coordinates": [[[8, 53], [13, 52]], [[12, 51], [15, 52]]],
77
+ },
78
+ },
79
+ ],
80
+ }
81
+ map.settings["properties"]["labelKey"] = "{name} ({measure})"
82
+ map.settings["properties"]["onLoadPanel"] = "databrowser"
83
+ map.save()
84
+ DataLayerFactory(map=map, data=data)
85
+ page.goto(f"{live_server.url}{map.get_absolute_url()}#6/10/50")
86
+ expect(page.get_by_text("linestring (99.7 km)")).to_be_visible()
87
+ expect(page.get_by_text("multilinestring (592 km)")).to_be_visible()
88
+
89
+
90
+ def test_can_use_gain_and_loss(live_server, map, page):
91
+ data = {
92
+ "type": "FeatureCollection",
93
+ "features": [
94
+ {
95
+ "type": "Feature",
96
+ "geometry": {
97
+ "type": "LineString",
98
+ "coordinates": [
99
+ [8.420888, 39.327819, 12.1],
100
+ [8.420915, 39.327745, 12.9],
101
+ [8.420906, 39.327543, 14.8],
102
+ [8.420876, 39.327312, 17],
103
+ [8.420754, 39.327023, 16.8],
104
+ [8.420609, 39.326776, 16.6],
105
+ [8.42051, 39.326467, 16.4],
106
+ [8.420409, 39.326254, 16.3],
107
+ [8.420367, 39.326108, 16.2],
108
+ [8.420287, 39.326044, 16.2],
109
+ [8.420294, 39.325794, 15.1],
110
+ [8.419974, 39.325549, 12.5],
111
+ [8.419887, 39.325508, 11.9],
112
+ [8.419702, 39.325343, 10.3],
113
+ [8.419574, 39.325289, 9.4],
114
+ [8.41943, 39.325183, 8.2],
115
+ [8.419393, 39.325127, 7.8],
116
+ [8.419297, 39.325108, 7.2],
117
+ [8.419179, 39.325014, 6.2],
118
+ [8.419179, 39.324979, 6.1],
119
+ [8.419179, 39.324979, 6.1],
120
+ [8.419182, 39.324653, 6],
121
+ [8.419129, 39.324508, 5.9],
122
+ [8.419074, 39.324482, 5.9],
123
+ [8.419007, 39.324362, 5.8],
124
+ [8.418957, 39.324324, 5.8],
125
+ [8.418944, 39.324291, 5.8],
126
+ [8.418947, 39.324233, 5.8],
127
+ [8.418967, 39.324196, 5.7],
128
+ [8.41895, 39.324126, 5.6],
129
+ [8.418838, 39.323996, 5.4],
130
+ [8.418814, 39.323774, 5],
131
+ [8.418931, 39.323546, 10.1],
132
+ [8.41896, 39.323444, 12.3],
133
+ [8.418971, 39.323232, 16.9],
134
+ [8.419068, 39.322974, 13.5],
135
+ [8.41914, 39.322946, 12.7],
136
+ [8.419245, 39.322895, 12.3],
137
+ [8.419342, 39.322857, 11.9],
138
+ [8.419492, 39.322855, 11.3],
139
+ [8.419591, 39.322768, 11.1],
140
+ [8.419672, 39.322724, 11],
141
+ [8.419776, 39.322704, 10.9],
142
+ [8.419823, 39.322711, 10.8],
143
+ [8.41971, 39.322631, 8.5],
144
+ [8.419668, 39.322581, 7.3],
145
+ [8.419653, 39.322537, 6.3],
146
+ [8.419628, 39.32243, 5.3],
147
+ [8.419629, 39.322384, 5.4],
148
+ [8.419656, 39.322346, 5.5],
149
+ [8.419703, 39.322304, 5.6],
150
+ [8.419802, 39.322305, 5.7],
151
+ [8.419868, 39.32228, 5.8],
152
+ [8.419994, 39.322223, 6.1],
153
+ [8.420066, 39.322174, 6.2],
154
+ [8.42013, 39.32211, 6.4],
155
+ [8.420142, 39.322013, 6.5],
156
+ [8.420167, 39.321924, 6.7],
157
+ [8.420188, 39.321788, 7],
158
+ [8.420269, 39.32165, 7.3],
159
+ [8.420342, 39.321625, 7.4],
160
+ [8.420427, 39.321609, 7.5],
161
+ [8.420645, 39.321582, 7.8],
162
+ [8.420753, 39.321699, 8.1],
163
+ [8.420881, 39.321801, 8.4],
164
+ [8.421082, 39.321898, 8.7],
165
+ [8.421184, 39.321868, 8.9],
166
+ [8.421351, 39.321877, 9.1],
167
+ [8.421451, 39.321834, 8.2],
168
+ [8.421545, 39.321811, 7.5],
169
+ [8.421815, 39.321691, 5.1],
170
+ [8.421877, 39.321632, 4.3],
171
+ [8.42196, 39.321602, 3.7],
172
+ [8.422083, 39.321621, 4.5],
173
+ [8.422462, 39.321579, 8.7],
174
+ [8.422875, 39.321691, 13.5],
175
+ [8.423069, 39.321732, 15.7],
176
+ [8.423231, 39.321687, 17.6],
177
+ [8.423405, 39.321726, 19.6],
178
+ [8.423626, 39.321719, 22.1],
179
+ [8.424103, 39.321776, 27.4],
180
+ [8.424214, 39.321746, 28.7],
181
+ [8.424402, 39.321632, 27.5],
182
+ [8.424486, 39.321559, 26.8],
183
+ [8.424524, 39.321501, 26.3],
184
+ [8.424916, 39.321097, 22.6],
185
+ [8.424969, 39.321007, 21.9],
186
+ [8.425387, 39.320766, 19],
187
+ [8.425489, 39.320645, 20.4],
188
+ [8.425621, 39.320556, 22.1],
189
+ [8.425699, 39.320574, 22.8],
190
+ [8.425774, 39.320511, 23.9],
191
+ [8.425831, 39.320336, 19.6],
192
+ [8.425822, 39.32021, 16.1],
193
+ [8.42575, 39.320086, 12.4],
194
+ [8.425788, 39.320004, 10],
195
+ [8.425946, 39.319822, 10.7],
196
+ [8.426039, 39.319781, 11],
197
+ [8.426264, 39.319776, 11.8],
198
+ [8.426305, 39.319718, 12],
199
+ [8.426362, 39.319433, 6.8],
200
+ [8.426414, 39.31936, 5.3],
201
+ [8.426422, 39.319161, 1.6],
202
+ [8.426449, 39.319085, 0.2],
203
+ [8.426568, 39.31904, 0.4],
204
+ [8.426608, 39.318981, 1.8],
205
+ [8.426714, 39.318923, 3.8],
206
+ [8.427072, 39.318862, 9.6],
207
+ [8.427204, 39.31886, 11.7],
208
+ [8.427359, 39.318896, 14.3],
209
+ [8.427434, 39.31895, 15.9],
210
+ [8.427519, 39.318968, 17.3],
211
+ [8.427558, 39.318972, 18.4],
212
+ [8.427616, 39.318991, 19.2],
213
+ [8.427685, 39.319082, 21.3],
214
+ [8.42773, 39.31921, 25.1],
215
+ [8.427914, 39.319306, 29.9],
216
+ [8.42849, 39.319358, 46.7],
217
+ [8.429645, 39.319309, 79.8],
218
+ [8.430532, 39.319314, 85],
219
+ [8.430582, 39.319297, 85.2],
220
+ [8.430808, 39.319195, 84.8],
221
+ [8.43098, 39.319076, 84.5],
222
+ [8.431138, 39.318999, 84.2],
223
+ [8.431283, 39.318985, 84],
224
+ [8.431288, 39.318946, 84.8],
225
+ [8.431373, 39.318825, 87.6],
226
+ [8.431411, 39.318796, 87.9],
227
+ [8.431678, 39.318827, 87.1],
228
+ [8.431773, 39.318752, 88.3],
229
+ [8.431854, 39.318552, 90.7],
230
+ [8.431832, 39.31847, 91.7],
231
+ [8.431959, 39.318284, 94.1],
232
+ [8.431968, 39.318034, 97],
233
+ [8.43207, 39.31791, 98.7],
234
+ [8.432118, 39.317736, 100.8],
235
+ [8.432263, 39.317582, 103],
236
+ [8.432291, 39.317263, 106.7],
237
+ [8.432279, 39.316848, 111.5],
238
+ [8.432358, 39.31652, 115.3],
239
+ [8.432327, 39.316486, 115.8],
240
+ [8.432336, 39.316437, 116.4],
241
+ [8.432287, 39.316409, 116.4],
242
+ [8.432257, 39.316391, 116.2],
243
+ [8.432179, 39.316251, 115.4],
244
+ [8.432156, 39.316183, 115.6],
245
+ [8.43223, 39.316138, 116.5],
246
+ [8.43223, 39.316043, 117.7],
247
+ [8.432274, 39.315918, 119.4],
248
+ [8.432254, 39.315799, 121],
249
+ [8.432377, 39.315713, 122.6],
250
+ [8.43248, 39.315542, 125.1],
251
+ [8.43257, 39.315451, 126],
252
+ [8.432652, 39.315352, 127],
253
+ [8.432724, 39.315291, 127.7],
254
+ [8.432779, 39.315208, 128.5],
255
+ [8.432863, 39.315109, 129.5],
256
+ [8.432945, 39.315038, 130.3],
257
+ [8.433002, 39.315014, 130.7],
258
+ [8.433092, 39.315007, 131.3],
259
+ [8.43318, 39.315012, 131.9],
260
+ [8.433295, 39.315111, 133],
261
+ [8.433346, 39.315126, 133.4],
262
+ [8.43338, 39.315113, 133.6],
263
+ [8.433404, 39.31509, 133.8],
264
+ [8.433408, 39.315058, 132.4],
265
+ [8.433422, 39.31498, 131.6],
266
+ [8.43347, 39.314876, 130.3],
267
+ [8.433562, 39.314771, 128.2],
268
+ [8.433817, 39.314543, 123],
269
+ [8.434004, 39.314434, 119.9],
270
+ [8.434262, 39.314344, 121.2],
271
+ [8.434729, 39.314236, 123.9],
272
+ [8.435085, 39.31388, 127.2],
273
+ [8.435254, 39.313808, 128.4],
274
+ [8.435388, 39.313779, 128.4],
275
+ [8.435547, 39.313774, 129.9],
276
+ [8.4357, 39.313825, 131.6],
277
+ [8.435802, 39.313882, 132.8],
278
+ [8.435866, 39.313979, 134.1],
279
+ [8.435902, 39.314064, 135.2],
280
+ [8.435973, 39.314103, 136],
281
+ [8.436062, 39.314107, 136.9],
282
+ [8.436143, 39.314101, 137.7],
283
+ [8.436215, 39.313989, 137.7],
284
+ [8.436162, 39.313752, 137.5],
285
+ [8.436209, 39.313402, 137.2],
286
+ [8.436413, 39.313182, 137],
287
+ [8.436559, 39.313127, 136.9],
288
+ [8.43664, 39.313115, 136.8],
289
+ [8.436682, 39.313058, 137.7],
290
+ [8.436798, 39.312789, 139.1],
291
+ [8.436706, 39.312486, 140.7],
292
+ [8.436703, 39.312448, 141],
293
+ ],
294
+ },
295
+ "properties": {"name": "some track"},
296
+ "id": "MzMTI",
297
+ }
298
+ ],
299
+ "_umap_options": {"popupContentTemplate": "{name}\n⭧ {gain} m\n⭨ {loss} m"},
300
+ }
301
+ DataLayerFactory(map=map, data=data)
302
+ page.goto(
303
+ f"{live_server.url}{map.get_absolute_url()}?onLoadPanel=databrowser#16/39.3201/8.4278"
304
+ )
305
+ # We can't make PW to click on the path, so let's use the browser for that
306
+ page.get_by_text("some track").click()
307
+ expect(page.get_by_text("⭧ 211 m")).to_be_visible()
308
+ expect(page.get_by_text("⭨ 82 m")).to_be_visible()
@@ -3,7 +3,7 @@ import re
3
3
  import pytest
4
4
  from playwright.sync_api import expect
5
5
 
6
- from umap.models import Map
6
+ from umap.models import DataLayer, Map
7
7
 
8
8
  from ..base import DataLayerFactory, MapFactory
9
9
 
@@ -161,7 +161,7 @@ def test_websocket_connection_can_sync_polygons(
161
161
 
162
162
  @pytest.mark.xdist_group(name="websockets")
163
163
  def test_websocket_connection_can_sync_map_properties(
164
- context, live_server, websocket_server, tilelayer
164
+ new_page, live_server, websocket_server, tilelayer
165
165
  ):
166
166
  map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
167
167
  map.settings["properties"]["syncEnabled"] = True
@@ -169,9 +169,9 @@ def test_websocket_connection_can_sync_map_properties(
169
169
  DataLayerFactory(map=map, data={})
170
170
 
171
171
  # Create two tabs
172
- peerA = context.new_page()
172
+ peerA = new_page()
173
173
  peerA.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
174
- peerB = context.new_page()
174
+ peerB = new_page()
175
175
  peerB.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
176
176
 
177
177
  # Name change is synced
@@ -193,7 +193,7 @@ def test_websocket_connection_can_sync_map_properties(
193
193
 
194
194
  @pytest.mark.xdist_group(name="websockets")
195
195
  def test_websocket_connection_can_sync_datalayer_properties(
196
- context, live_server, websocket_server, tilelayer
196
+ new_page, live_server, websocket_server, tilelayer
197
197
  ):
198
198
  map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
199
199
  map.settings["properties"]["syncEnabled"] = True
@@ -201,9 +201,9 @@ def test_websocket_connection_can_sync_datalayer_properties(
201
201
  DataLayerFactory(map=map, data={})
202
202
 
203
203
  # Create two tabs
204
- peerA = context.new_page()
204
+ peerA = new_page()
205
205
  peerA.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
206
- peerB = context.new_page()
206
+ peerB = new_page()
207
207
  peerB.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
208
208
 
209
209
  # Layer addition, name and type are synced
@@ -215,7 +215,7 @@ def test_websocket_connection_can_sync_datalayer_properties(
215
215
  peerA.locator("body").press("Escape")
216
216
 
217
217
  peerB.get_by_role("link", name="Manage layers").click()
218
- peerB.get_by_role("button", name="Edit").first.click()
218
+ peerB.locator(".panel.right").get_by_role("button", name="Edit").first.click()
219
219
  expect(peerB.locator('input[name="name"]')).to_have_value("synced layer!")
220
220
  expect(peerB.get_by_role("combobox")).to_have_value("Choropleth")
221
221
 
@@ -267,7 +267,7 @@ def test_websocket_connection_can_sync_cloned_polygons(
267
267
  b_polygon = peerB.locator("path")
268
268
 
269
269
  # Clone on peer B and save
270
- b_polygon.click(button="right")
270
+ b_polygon.click(button="right", delay=200)
271
271
  peerB.get_by_role("button", name="Clone this feature").click()
272
272
 
273
273
  expect(peerB.locator("path")).to_have_count(2)
@@ -343,3 +343,75 @@ def test_websocket_connection_can_sync_late_joining_peer(
343
343
 
344
344
  # Clean up: close edit mode
345
345
  peerB.locator("body").press("Escape")
346
+
347
+
348
+ @pytest.mark.xdist_group(name="websockets")
349
+ def test_should_sync_datalayers(new_page, live_server, websocket_server, tilelayer):
350
+ map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
351
+ map.settings["properties"]["syncEnabled"] = True
352
+ map.save()
353
+
354
+ assert not DataLayer.objects.count()
355
+
356
+ # Create two tabs
357
+ peerA = new_page("Page A")
358
+ peerA.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
359
+ peerB = new_page("Page B")
360
+ peerB.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
361
+
362
+ # Create a new layer from peerA
363
+ peerA.get_by_role("link", name="Manage layers").click()
364
+ peerA.get_by_role("button", name="Add a layer").click()
365
+
366
+ # Check layer has been sync to peerB
367
+ peerB.get_by_role("button", name="Open browser").click()
368
+ expect(peerB.get_by_text("Layer 1")).to_be_visible()
369
+
370
+ # Draw a marker in layer 1 from peerA
371
+ peerA.get_by_role("link", name="Draw a marker (Ctrl+M)").click()
372
+ peerA.locator("#map").click()
373
+
374
+ # Check marker is visible from peerB
375
+ expect(peerB.locator(".leaflet-marker-icon")).to_be_visible()
376
+
377
+ # Save layer to the server
378
+ with peerA.expect_response(re.compile(".*/datalayer/create/.*")):
379
+ peerA.get_by_role("button", name="Save").click()
380
+
381
+ assert DataLayer.objects.count() == 1
382
+
383
+ # Create another layer from peerA and draw a marker on it (without saving to server)
384
+ peerA.get_by_role("link", name="Manage layers").click()
385
+ peerA.get_by_role("button", name="Add a layer").click()
386
+ peerA.get_by_role("link", name="Draw a marker (Ctrl+M)").click()
387
+ peerA.locator("#map").click()
388
+
389
+ # Make sure this new marker is in Layer 2 for peerB
390
+ expect(peerB.get_by_text("Layer 2")).to_be_visible()
391
+ peerB.locator(".panel.left").get_by_role("button", name="Show/hide layer").nth(
392
+ 1
393
+ ).click()
394
+ expect(peerB.locator(".leaflet-marker-icon")).to_be_visible()
395
+
396
+ # Now draw a marker from peerB
397
+ peerB.get_by_role("link", name="Draw a marker (Ctrl+M)").click()
398
+ peerB.locator("#map").click()
399
+ peerB.locator('input[name="name"]').fill("marker from peerB")
400
+
401
+ # Save from peer B
402
+ with peerB.expect_response(re.compile(".*/datalayer/create/.*")):
403
+ peerB.get_by_role("button", name="Save").click()
404
+
405
+ assert DataLayer.objects.count() == 2
406
+
407
+ # Check this new marker is visible from peerA
408
+ peerA.get_by_role("button", name="Open browser").click()
409
+ peerA.locator(".panel.left").get_by_role("button", name="Show/hide layer").nth(
410
+ 1
411
+ ).click()
412
+
413
+ # Now peerA saves the layer 2 to the server
414
+ with peerA.expect_response(re.compile(".*/datalayer/update/.*")):
415
+ peerA.get_by_role("button", name="Save").click()
416
+
417
+ assert DataLayer.objects.count() == 2
@@ -0,0 +1,82 @@
1
+ import pytest
2
+ from django.contrib.auth import get_user_model
3
+ from django.urls import reverse
4
+
5
+ from umap.models import Map
6
+
7
+ from .base import MapFactory, UserFactory
8
+
9
+ User = get_user_model()
10
+
11
+ pytestmark = pytest.mark.django_db
12
+
13
+
14
+ def test_user_dashboard_is_restricted_to_logged_in(client):
15
+ response = client.get(reverse("user_dashboard"))
16
+ assert response.status_code == 302
17
+ assert response["Location"] == "/en/login/?next=/en/me"
18
+
19
+
20
+ def test_user_dashboard_display_user_maps(client, map):
21
+ client.login(username=map.owner.username, password="123123")
22
+ response = client.get(reverse("user_dashboard"))
23
+ assert response.status_code == 200
24
+ body = response.content.decode()
25
+ assert map.name in body
26
+ assert f"{map.get_absolute_url()}?edit" in body
27
+ assert f"{map.get_absolute_url()}?share" in body
28
+ assert f"/map/{map.pk}/download" in body
29
+ assert "Everyone (public)" in body
30
+ assert "Owner only" in body
31
+
32
+
33
+ def test_user_dashboard_do_not_display_blocked_user_maps(client, map):
34
+ map.share_status = Map.BLOCKED
35
+ map.save()
36
+ client.login(username=map.owner.username, password="123123")
37
+ response = client.get(reverse("user_dashboard"))
38
+ assert response.status_code == 200
39
+ body = response.content.decode()
40
+ assert map.name not in body
41
+
42
+
43
+ def test_user_dashboard_do_not_display_deleted_user_maps(client, map):
44
+ map.share_status = Map.DELETED
45
+ map.save()
46
+ client.login(username=map.owner.username, password="123123")
47
+ response = client.get(reverse("user_dashboard"))
48
+ assert response.status_code == 200
49
+ body = response.content.decode()
50
+ assert map.name not in body
51
+
52
+
53
+ @pytest.mark.parametrize("share_status", [Map.DRAFT, Map.PRIVATE, Map.PUBLIC, Map.OPEN])
54
+ def test_user_dashboard_display_user_team_maps(client, map, team, user, share_status):
55
+ user.teams.add(team)
56
+ user.save()
57
+ map.team = team
58
+ map.share_status = share_status
59
+ map.save()
60
+ assert map.owner != user
61
+ client.login(username=user.username, password="123123")
62
+ response = client.get(reverse("user_dashboard"))
63
+ assert response.status_code == 200
64
+ body = response.content.decode()
65
+ assert map.name in body
66
+ assert map.get_absolute_url() in body
67
+
68
+
69
+ def test_user_dashboard_display_user_maps_distinct(client, map):
70
+ # cf https://github.com/umap-project/umap/issues/1325
71
+ anonymap = MapFactory(name="Map witout owner should not appear")
72
+ user1 = UserFactory(username="user1")
73
+ user2 = UserFactory(username="user2")
74
+ map.editors.add(user1)
75
+ map.editors.add(user2)
76
+ map.save()
77
+ client.login(username=map.owner.username, password="123123")
78
+ response = client.get(reverse("user_dashboard"))
79
+ assert response.status_code == 200
80
+ body = response.content.decode()
81
+ assert body.count(f'<a href="/en/map/test-map_{map.pk}">test map</a>') == 1
82
+ assert body.count(anonymap.name) == 0
@@ -22,10 +22,11 @@ def test_datalayers_should_be_ordered_by_rank(map, datalayer):
22
22
  assert list(map.datalayer_set.all()) == [c1, c2, c3, c4, datalayer]
23
23
 
24
24
 
25
- def test_upload_to(map, datalayer):
25
+ def test_upload_to(map):
26
26
  map.pk = 302
27
- datalayer.pk = 17
28
- assert datalayer.upload_to().startswith("datalayer/2/0/302/17_")
27
+ map.save()
28
+ datalayer = DataLayerFactory(map=map)
29
+ assert datalayer.geojson.name.startswith(f"datalayer/2/0/302/{datalayer.pk}_")
29
30
 
30
31
 
31
32
  def test_save_should_use_pk_as_name(map, datalayer):
@@ -65,7 +66,7 @@ def test_clone_should_clone_geojson_too(datalayer):
65
66
  def test_should_remove_old_versions_on_save(map, settings):
66
67
  datalayer = DataLayerFactory(uuid="0f1161c0-c07f-4ba4-86c5-8d8981d8a813", old_id=17)
67
68
  settings.UMAP_KEEP_VERSIONS = 3
68
- root = Path(datalayer.storage_root())
69
+ root = Path(datalayer.geojson.storage._base_path(datalayer))
69
70
  before = len(datalayer.geojson.storage.listdir(root)[1])
70
71
  newer = f"{datalayer.pk}_1440924889.geojson"
71
72
  medium = f"{datalayer.pk}_1440923687.geojson"
@@ -273,9 +274,8 @@ def test_anonymous_can_edit_in_inherit_mode_and_map_in_public_mode(
273
274
 
274
275
 
275
276
  def test_should_remove_all_versions_on_delete(map, settings):
276
- settings.UMAP_PURGATORY_ROOT = tempfile.mkdtemp()
277
277
  datalayer = DataLayerFactory(uuid="0f1161c0-c07f-4ba4-86c5-8d8981d8a813", old_id=17)
278
- root = Path(datalayer.storage_root())
278
+ root = Path(datalayer.geojson.storage._base_path(datalayer))
279
279
  before = len(datalayer.geojson.storage.listdir(root)[1])
280
280
  other = "123456_1440918637.geojson"
281
281
  files = [
@@ -292,4 +292,3 @@ def test_should_remove_all_versions_on_delete(map, settings):
292
292
  datalayer.delete()
293
293
  found = datalayer.geojson.storage.listdir(root)[1]
294
294
  assert found == [other, f"{other}.gz"]
295
- assert len(list(Path(settings.UMAP_PURGATORY_ROOT).iterdir())) == 4 + before
@@ -0,0 +1,135 @@
1
+ import json
2
+ import os
3
+
4
+ import boto3
5
+ import pytest
6
+ from botocore.errorfactory import ClientError
7
+ from django.core.files.base import ContentFile
8
+ from django.core.files.storage import storages
9
+ from moto import mock_aws
10
+
11
+ from umap.models import DataLayer
12
+
13
+ from .base import DataLayerFactory
14
+
15
+ pytestmark = pytest.mark.django_db
16
+
17
+
18
+ @pytest.fixture(scope="module", autouse=True)
19
+ def patch_storage():
20
+ """Mocked AWS Credentials for moto."""
21
+ os.environ["AWS_ACCESS_KEY_ID"] = "testing"
22
+ os.environ["AWS_SECRET_ACCESS_KEY"] = "testing"
23
+ os.environ["AWS_SECURITY_TOKEN"] = "testing"
24
+ os.environ["AWS_SESSION_TOKEN"] = "testing"
25
+ os.environ["AWS_DEFAULT_REGION"] = "us-east-1"
26
+ before = DataLayer.geojson.field.storage
27
+
28
+ DataLayer.geojson.field.storage = storages.create_storage(
29
+ {
30
+ "BACKEND": "umap.storage.s3.S3DataStorage",
31
+ "OPTIONS": {
32
+ "access_key": "testing",
33
+ "secret_key": "testing",
34
+ "bucket_name": "umap",
35
+ "region_name": "us-east-1",
36
+ },
37
+ }
38
+ )
39
+ yield
40
+ DataLayer.geojson.field.storage = before
41
+
42
+
43
+ @pytest.fixture(scope="module", autouse=True)
44
+ def mocked_aws():
45
+ """
46
+ Mock all AWS interactions
47
+ Requires you to create your own boto3 clients
48
+ """
49
+ with mock_aws():
50
+ client = boto3.client("s3", region_name="us-east-1")
51
+ client.create_bucket(Bucket="umap")
52
+ client.put_bucket_versioning(
53
+ Bucket="umap", VersioningConfiguration={"Status": "Enabled"}
54
+ )
55
+ yield
56
+
57
+
58
+ def test_can_create_datalayer(map, datalayer):
59
+ other = DataLayerFactory(map=map)
60
+ assert datalayer.geojson.name == f"{datalayer.pk}.geojson"
61
+ assert other.geojson.name == f"{other.pk}.geojson"
62
+
63
+
64
+ def test_clone_should_return_new_instance(map, datalayer):
65
+ clone = datalayer.clone()
66
+ assert datalayer.pk != clone.pk
67
+ assert datalayer.name == clone.name
68
+ assert datalayer.map == clone.map
69
+ assert datalayer.geojson != clone.geojson
70
+ assert datalayer.geojson.name != clone.geojson.name
71
+ assert clone.geojson.name == f"{clone.pk}.geojson"
72
+
73
+
74
+ def test_update_should_add_version(map, datalayer):
75
+ assert len(datalayer.versions) == 1
76
+ datalayer.geojson = ContentFile("{}", "foo.json")
77
+ datalayer.save()
78
+ assert len(datalayer.versions) == 2
79
+
80
+
81
+ def test_get_version(map, datalayer):
82
+ assert len(datalayer.versions) == 1
83
+ datalayer.geojson = ContentFile(b'{"foo": "bar"}', "foo.json")
84
+ datalayer.save()
85
+ assert len(datalayer.versions) == 2
86
+ latest = datalayer.versions[0]["ref"]
87
+ version = datalayer.get_version(latest)
88
+ assert json.loads(version) == {"foo": "bar"}
89
+ older = datalayer.versions[1]["ref"]
90
+ version = datalayer.get_version(older)
91
+ assert json.loads(version) == {
92
+ "_umap_options": {
93
+ "browsable": True,
94
+ "displayOnLoad": True,
95
+ "name": "test datalayer",
96
+ },
97
+ "features": [
98
+ {
99
+ "geometry": {
100
+ "coordinates": [
101
+ 14.68896484375,
102
+ 48.55297816440071,
103
+ ],
104
+ "type": "Point",
105
+ },
106
+ "properties": {
107
+ "_umap_options": {
108
+ "color": "DarkCyan",
109
+ "iconClass": "Ball",
110
+ },
111
+ "description": "Da place anonymous again 755",
112
+ "name": "Here",
113
+ },
114
+ "type": "Feature",
115
+ },
116
+ ],
117
+ "type": "FeatureCollection",
118
+ }
119
+
120
+ latest = datalayer.reference_version
121
+ version = datalayer.get_version(latest)
122
+ assert json.loads(version) == {"foo": "bar"}
123
+
124
+
125
+ def test_delete_datalayer_should_delete_all_versions(datalayer):
126
+ # create a new version
127
+ datalayer.geojson = ContentFile('{"foo": "bar"}', "foo.json")
128
+ datalayer.save()
129
+ s3_key = datalayer.geojson.name
130
+ datalayer.delete()
131
+ with pytest.raises(ClientError):
132
+ datalayer.geojson.storage.connection.meta.client.get_object(
133
+ Bucket="umap",
134
+ Key=s3_key,
135
+ )