umap-project 3.4.0b1__py3-none-any.whl → 3.4.2__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.
- umap/__init__.py +1 -1
- umap/context_processors.py +1 -1
- umap/locale/da/LC_MESSAGES/django.mo +0 -0
- umap/locale/da/LC_MESSAGES/django.po +20 -16
- umap/locale/en/LC_MESSAGES/django.po +18 -14
- umap/locale/es/LC_MESSAGES/django.mo +0 -0
- umap/locale/es/LC_MESSAGES/django.po +20 -16
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +18 -14
- umap/locale/pl/LC_MESSAGES/django.mo +0 -0
- umap/locale/pl/LC_MESSAGES/django.po +72 -71
- umap/migrations/0018_datalayer_uuid.py +1 -1
- umap/models.py +7 -3
- umap/settings/local.py.sample +1 -1
- umap/static/umap/content.css +0 -3
- umap/static/umap/css/bar.css +9 -6
- umap/static/umap/css/form.css +27 -11
- umap/static/umap/css/popup.css +1 -0
- umap/static/umap/js/components/base.js +1 -1
- umap/static/umap/js/components/copiable.js +47 -0
- umap/static/umap/js/modules/autocomplete.js +31 -58
- umap/static/umap/js/modules/browser.js +8 -8
- umap/static/umap/js/modules/data/features.js +33 -36
- umap/static/umap/js/modules/data/fields.js +446 -0
- umap/static/umap/js/modules/data/layer.js +76 -93
- umap/static/umap/js/modules/domutils.js +24 -4
- umap/static/umap/js/modules/filters.js +20 -47
- umap/static/umap/js/modules/form/fields.js +4 -4
- umap/static/umap/js/modules/formatter.js +9 -1
- umap/static/umap/js/modules/help.js +13 -14
- umap/static/umap/js/modules/i18n.js +1 -1
- umap/static/umap/js/modules/importer.js +18 -27
- umap/static/umap/js/modules/importers/banfr.js +0 -1
- umap/static/umap/js/modules/importers/cadastrefr.js +19 -19
- umap/static/umap/js/modules/importers/communesfr.js +7 -8
- umap/static/umap/js/modules/importers/datasets.js +14 -14
- umap/static/umap/js/modules/importers/geodatamine.js +20 -22
- umap/static/umap/js/modules/importers/opendata.js +10 -0
- umap/static/umap/js/modules/importers/overpass.js +19 -18
- umap/static/umap/js/modules/managers.js +1 -265
- umap/static/umap/js/modules/permissions.js +5 -3
- umap/static/umap/js/modules/rendering/controls.js +6 -4
- umap/static/umap/js/modules/rendering/icon.js +5 -9
- umap/static/umap/js/modules/rendering/layers/base.js +1 -1
- umap/static/umap/js/modules/rendering/layers/classified.js +16 -11
- umap/static/umap/js/modules/rendering/layers/heat.js +27 -21
- umap/static/umap/js/modules/rendering/map.js +22 -22
- umap/static/umap/js/modules/rendering/popup.js +6 -3
- umap/static/umap/js/modules/rendering/template.js +31 -37
- umap/static/umap/js/modules/rendering/ui.js +1 -2
- umap/static/umap/js/modules/rules.js +34 -41
- umap/static/umap/js/modules/schema.js +0 -7
- umap/static/umap/js/modules/share.js +36 -69
- umap/static/umap/js/modules/slideshow.js +3 -3
- umap/static/umap/js/modules/tableeditor.js +0 -1
- umap/static/umap/js/modules/ui/bar.js +51 -32
- umap/static/umap/js/modules/ui/dialog.js +10 -1
- umap/static/umap/js/modules/ui/panel.js +28 -23
- umap/static/umap/js/modules/ui/tooltip.js +1 -1
- umap/static/umap/js/modules/umap.js +84 -84
- umap/static/umap/js/modules/utils.js +13 -4
- umap/static/umap/js/umap.controls.js +33 -14
- umap/static/umap/locale/am_ET.js +19 -8
- umap/static/umap/locale/am_ET.json +19 -8
- umap/static/umap/locale/ar.js +19 -8
- umap/static/umap/locale/ar.json +19 -8
- umap/static/umap/locale/ast.js +19 -8
- umap/static/umap/locale/ast.json +19 -8
- umap/static/umap/locale/bg.js +19 -8
- umap/static/umap/locale/bg.json +19 -8
- umap/static/umap/locale/br.js +20 -9
- umap/static/umap/locale/br.json +20 -9
- umap/static/umap/locale/ca.js +19 -8
- umap/static/umap/locale/ca.json +19 -8
- umap/static/umap/locale/cs_CZ.js +20 -9
- umap/static/umap/locale/cs_CZ.json +20 -9
- umap/static/umap/locale/da.js +54 -43
- umap/static/umap/locale/da.json +54 -43
- umap/static/umap/locale/de.js +44 -33
- umap/static/umap/locale/de.json +44 -33
- umap/static/umap/locale/el.js +20 -9
- umap/static/umap/locale/el.json +20 -9
- umap/static/umap/locale/en.js +20 -9
- umap/static/umap/locale/en.json +20 -9
- umap/static/umap/locale/en_US.json +19 -8
- umap/static/umap/locale/es.js +55 -44
- umap/static/umap/locale/es.json +55 -44
- umap/static/umap/locale/et.js +20 -9
- umap/static/umap/locale/et.json +20 -9
- umap/static/umap/locale/eu.js +25 -14
- umap/static/umap/locale/eu.json +25 -14
- umap/static/umap/locale/fa_IR.js +20 -9
- umap/static/umap/locale/fa_IR.json +20 -9
- umap/static/umap/locale/fi.js +19 -8
- umap/static/umap/locale/fi.json +19 -8
- umap/static/umap/locale/fr.js +21 -10
- umap/static/umap/locale/fr.json +21 -10
- umap/static/umap/locale/gl.js +147 -136
- umap/static/umap/locale/gl.json +147 -136
- umap/static/umap/locale/he.js +19 -8
- umap/static/umap/locale/he.json +19 -8
- umap/static/umap/locale/hr.js +19 -8
- umap/static/umap/locale/hr.json +19 -8
- umap/static/umap/locale/hu.js +62 -51
- umap/static/umap/locale/hu.json +62 -51
- umap/static/umap/locale/id.js +19 -8
- umap/static/umap/locale/id.json +19 -8
- umap/static/umap/locale/is.js +20 -9
- umap/static/umap/locale/is.json +20 -9
- umap/static/umap/locale/it.js +20 -9
- umap/static/umap/locale/it.json +20 -9
- umap/static/umap/locale/ja.js +19 -8
- umap/static/umap/locale/ja.json +19 -8
- umap/static/umap/locale/ko.js +19 -8
- umap/static/umap/locale/ko.json +19 -8
- umap/static/umap/locale/lt.js +19 -8
- umap/static/umap/locale/lt.json +19 -8
- umap/static/umap/locale/ms.js +20 -9
- umap/static/umap/locale/ms.json +20 -9
- umap/static/umap/locale/nl.js +20 -9
- umap/static/umap/locale/nl.json +20 -9
- umap/static/umap/locale/no.js +19 -8
- umap/static/umap/locale/no.json +19 -8
- umap/static/umap/locale/pl.js +56 -45
- umap/static/umap/locale/pl.json +56 -45
- umap/static/umap/locale/pl_PL.json +19 -8
- umap/static/umap/locale/pt.js +20 -9
- umap/static/umap/locale/pt.json +20 -9
- umap/static/umap/locale/pt_BR.js +19 -8
- umap/static/umap/locale/pt_BR.json +19 -8
- umap/static/umap/locale/pt_PT.js +19 -8
- umap/static/umap/locale/pt_PT.json +19 -8
- umap/static/umap/locale/ro.js +19 -8
- umap/static/umap/locale/ro.json +19 -8
- umap/static/umap/locale/ru.js +19 -8
- umap/static/umap/locale/ru.json +19 -8
- umap/static/umap/locale/si.js +1 -1
- umap/static/umap/locale/si.json +1 -1
- umap/static/umap/locale/sk_SK.js +19 -8
- umap/static/umap/locale/sk_SK.json +19 -8
- umap/static/umap/locale/sl.js +19 -8
- umap/static/umap/locale/sl.json +19 -8
- umap/static/umap/locale/sr.js +19 -8
- umap/static/umap/locale/sr.json +19 -8
- umap/static/umap/locale/sv.js +19 -8
- umap/static/umap/locale/sv.json +19 -8
- umap/static/umap/locale/th_TH.js +19 -8
- umap/static/umap/locale/th_TH.json +19 -8
- umap/static/umap/locale/tr.js +19 -8
- umap/static/umap/locale/tr.json +19 -8
- umap/static/umap/locale/uk_UA.js +19 -8
- umap/static/umap/locale/uk_UA.json +19 -8
- umap/static/umap/locale/vi.js +19 -8
- umap/static/umap/locale/vi.json +19 -8
- umap/static/umap/locale/vi_VN.json +19 -8
- umap/static/umap/locale/zh.js +19 -8
- umap/static/umap/locale/zh.json +19 -8
- umap/static/umap/locale/zh_CN.json +19 -8
- umap/static/umap/locale/zh_TW.Big5.json +19 -8
- umap/static/umap/locale/zh_TW.js +53 -42
- umap/static/umap/locale/zh_TW.json +53 -42
- umap/static/umap/map.css +8 -7
- umap/static/umap/unittests/utils.js +7 -7
- umap/templates/umap/content_footer.html +1 -0
- umap/templates/umap/css.html +0 -2
- umap/templates/umap/js.html +1 -3
- umap/templates/umap/login_popup_end.html +2 -2
- umap/tests/integration/conftest.py +11 -2
- umap/tests/integration/test_anonymous_owned_map.py +2 -2
- umap/tests/integration/test_conditional_rules.py +107 -52
- umap/tests/integration/test_draw_polygon.py +4 -0
- umap/tests/integration/test_draw_polyline.py +11 -0
- umap/tests/integration/test_edit_datalayer.py +1 -1
- umap/tests/integration/test_fields.py +19 -0
- umap/tests/integration/test_filters.py +6 -7
- umap/tests/integration/test_iframe.py +1 -1
- umap/tests/integration/test_import.py +23 -0
- umap/tests/integration/test_map.py +2 -2
- umap/tests/integration/test_map_preview.py +1 -1
- umap/tests/integration/test_owned_map.py +2 -2
- umap/tests/integration/test_picto.py +1 -1
- umap/tests/integration/test_popup.py +31 -0
- umap/tests/integration/test_remote_data.py +4 -4
- umap/tests/integration/test_save.py +1 -1
- umap/tests/integration/test_search.py +41 -0
- umap/tests/integration/test_share.py +2 -2
- umap/tests/integration/test_team.py +1 -1
- umap/tests/integration/test_websocket_sync.py +69 -20
- umap/tests/test_dashboard.py +1 -1
- umap/tests/test_statics.py +2 -2
- umap/tests/test_utils.py +4 -1
- umap/tests/test_views.py +1 -1
- umap/utils.py +3 -2
- {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/METADATA +17 -17
- {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/RECORD +198 -199
- umap/static/umap/js/umap.core.js +0 -93
- umap/static/umap/vendors/editinosm/Leaflet.EditInOSM.css +0 -46
- umap/static/umap/vendors/editinosm/Leaflet.EditInOSM.js +0 -240
- umap/static/umap/vendors/editinosm/edit-in-osm.png +0 -0
- {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/WHEEL +0 -0
- {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/entry_points.txt +0 -0
- {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -147,14 +147,14 @@ def test_default_view_latest_with_polygon(map, live_server, page):
|
|
|
147
147
|
expect(layers).to_have_count(1)
|
|
148
148
|
|
|
149
149
|
|
|
150
|
-
def test_default_view_locate(browser, live_server, map):
|
|
150
|
+
def test_default_view_locate(browser, live_server, map, new_page):
|
|
151
151
|
context = browser.new_context(
|
|
152
152
|
geolocation={"longitude": 8.52967, "latitude": 39.16267},
|
|
153
153
|
permissions=["geolocation"],
|
|
154
154
|
)
|
|
155
155
|
map.settings["properties"]["defaultView"] = "locate"
|
|
156
156
|
map.save()
|
|
157
|
-
page =
|
|
157
|
+
page = new_page(custom_context=context)
|
|
158
158
|
page.goto(f"{live_server.url}{map.get_absolute_url()}")
|
|
159
159
|
expect(page).to_have_url(re.compile(r".*#18/39\.16267/8\.52967"))
|
|
160
160
|
|
|
@@ -58,7 +58,7 @@ def test_map_preview_can_load_remote_geojson(page, live_server, tilelayer):
|
|
|
58
58
|
expect(markers).to_have_count(1)
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
def
|
|
61
|
+
def test_map_preview_can_load_multiple_remote_geojson(page, live_server, tilelayer):
|
|
62
62
|
def handle(route):
|
|
63
63
|
if "2" in route.request.url:
|
|
64
64
|
route.fulfill(json=GEOJSON2)
|
|
@@ -183,7 +183,7 @@ def test_can_change_perms_after_create(tilelayer, live_server, login, user):
|
|
|
183
183
|
page.goto(f"{live_server.url}/en/map/new")
|
|
184
184
|
# Create a layer
|
|
185
185
|
page.get_by_title("Manage layers").click()
|
|
186
|
-
page.
|
|
186
|
+
page.get_by_role("button", name="Add a layer").click()
|
|
187
187
|
page.locator("input[name=name]").fill("Layer 1")
|
|
188
188
|
expect(
|
|
189
189
|
page.get_by_role("button", name="Visibility: Draft (private)")
|
|
@@ -217,7 +217,7 @@ def test_can_change_owner(map, live_server, login, user):
|
|
|
217
217
|
page.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
|
|
218
218
|
edit_permissions = page.get_by_title("Update permissions and editors")
|
|
219
219
|
edit_permissions.click()
|
|
220
|
-
close = page.locator(".umap-field-owner .close")
|
|
220
|
+
close = page.locator(".umap-field-owner .icon-close")
|
|
221
221
|
close.click()
|
|
222
222
|
input = page.locator("input.edit-owner")
|
|
223
223
|
with page.expect_response(re.compile(r".*/agnocomplete/.*")):
|
|
@@ -136,7 +136,7 @@ def test_can_change_picto_at_marker_level(openmap, live_server, page, pictos):
|
|
|
136
136
|
expect(define).to_be_visible()
|
|
137
137
|
expect(undefine).to_be_hidden()
|
|
138
138
|
define.click()
|
|
139
|
-
# Map has an icon defined, so it
|
|
139
|
+
# Map has an icon defined, so it should open on Recent tab
|
|
140
140
|
symbols = page.locator(".umap-pictogram-body .umap-pictogram-choice")
|
|
141
141
|
expect(page.get_by_text("Recent")).to_be_visible()
|
|
142
142
|
expect(symbols).to_have_count(1)
|
|
@@ -42,3 +42,34 @@ def test_openstreetmap_popup(live_server, map, page):
|
|
|
42
42
|
"src",
|
|
43
43
|
"https://api.panoramax.xyz/api/pictures/d811b398-d930-4cf8-95a2-0c29c34d9fca/sd.jpg",
|
|
44
44
|
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_table_popup(live_server, map, page):
|
|
48
|
+
data = {
|
|
49
|
+
"type": "FeatureCollection",
|
|
50
|
+
"features": [
|
|
51
|
+
{
|
|
52
|
+
"type": "Feature",
|
|
53
|
+
"geometry": {"type": "Point", "coordinates": [2.49, 48.79]},
|
|
54
|
+
"properties": {
|
|
55
|
+
"url": "https://restaurant.org",
|
|
56
|
+
"formatted": "with **bold**",
|
|
57
|
+
},
|
|
58
|
+
"id": "AzMjk",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
"_umap_options": {
|
|
62
|
+
"popupTemplate": "Table",
|
|
63
|
+
"fields": [
|
|
64
|
+
{"key": "url", "type": "String"},
|
|
65
|
+
{"key": "formatted", "type": "Text"},
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
DataLayerFactory(map=map, data=data)
|
|
70
|
+
page.goto(f"{live_server.url}{map.get_absolute_url()}#18/48.79/2.49")
|
|
71
|
+
page.locator(".leaflet-marker-icon").click()
|
|
72
|
+
expect(page.get_by_role("link", name="https://restaurant.org")).to_be_visible()
|
|
73
|
+
expect(page.get_by_role("cell", name="with bold").locator("strong")).to_have_text(
|
|
74
|
+
"bold"
|
|
75
|
+
)
|
|
@@ -16,7 +16,7 @@ def intercept_remote_data(page):
|
|
|
16
16
|
"features": [
|
|
17
17
|
{
|
|
18
18
|
"type": "Feature",
|
|
19
|
-
"properties": {"name": "Point 2"},
|
|
19
|
+
"properties": {"name": "Point 2", "foobar": "bla"},
|
|
20
20
|
"geometry": {
|
|
21
21
|
"type": "Point",
|
|
22
22
|
"coordinates": [4.3375, 11.2707],
|
|
@@ -29,7 +29,7 @@ def intercept_remote_data(page):
|
|
|
29
29
|
"features": [
|
|
30
30
|
{
|
|
31
31
|
"type": "Feature",
|
|
32
|
-
"properties": {"name": "Point 1"},
|
|
32
|
+
"properties": {"name": "Point 1", "foobar": "baz"},
|
|
33
33
|
"geometry": {
|
|
34
34
|
"type": "Point",
|
|
35
35
|
"coordinates": [4.3375, 12.2707],
|
|
@@ -117,8 +117,8 @@ def test_create_remote_data_layer(page, live_server, tilelayer, settings):
|
|
|
117
117
|
"type": "String",
|
|
118
118
|
},
|
|
119
119
|
{
|
|
120
|
-
"key": "
|
|
121
|
-
"type": "
|
|
120
|
+
"key": "foobar",
|
|
121
|
+
"type": "String",
|
|
122
122
|
},
|
|
123
123
|
],
|
|
124
124
|
"id": str(datalayer.pk),
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from playwright.sync_api import expect
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_reverse_search(live_server, page, tilelayer):
|
|
5
|
+
photon_response = {
|
|
6
|
+
"type": "FeatureCollection",
|
|
7
|
+
"features": [
|
|
8
|
+
{
|
|
9
|
+
"type": "Feature",
|
|
10
|
+
"properties": {
|
|
11
|
+
"osm_type": "N",
|
|
12
|
+
"osm_id": 5055853416,
|
|
13
|
+
"osm_key": "place",
|
|
14
|
+
"osm_value": "locality",
|
|
15
|
+
"type": "locality",
|
|
16
|
+
"postcode": "10200",
|
|
17
|
+
"countrycode": "FR",
|
|
18
|
+
"name": "Le Haut Sentier",
|
|
19
|
+
"country": "France",
|
|
20
|
+
"city": "Thors",
|
|
21
|
+
"state": "Grand Est",
|
|
22
|
+
"county": "Aube",
|
|
23
|
+
},
|
|
24
|
+
"geometry": {"type": "Point", "coordinates": [4.7995256, 48.2985251]},
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
}
|
|
28
|
+
page.goto(f"{live_server.url}/en/map/new")
|
|
29
|
+
|
|
30
|
+
def handle_search(route):
|
|
31
|
+
route.fulfill(json=photon_response)
|
|
32
|
+
|
|
33
|
+
# Intercept the route
|
|
34
|
+
page.route(
|
|
35
|
+
"https://photon.komoot.io/reverse/?limit=1&lat=48.3&lon=4.8",
|
|
36
|
+
handle_search,
|
|
37
|
+
)
|
|
38
|
+
page.get_by_role("button", name="Search location").click()
|
|
39
|
+
page.get_by_role("searchbox", name="Type a place name or").fill("48.3 4.8")
|
|
40
|
+
expect(page.get_by_text("48.3 4.8")).to_be_visible()
|
|
41
|
+
expect(page.get_by_text("Le Haut Sentier")).to_be_visible()
|
|
@@ -8,7 +8,7 @@ pytestmark = pytest.mark.django_db
|
|
|
8
8
|
|
|
9
9
|
def test_iframe_code_can_contain_datalayers(map, live_server, datalayer, page):
|
|
10
10
|
page.goto(f"{live_server.url}{map.get_absolute_url()}?share")
|
|
11
|
-
textarea = page.
|
|
11
|
+
textarea = page.get_by_label("Iframe")
|
|
12
12
|
expect(textarea).to_be_visible()
|
|
13
13
|
expect(textarea).to_have_text(re.compile('src="'))
|
|
14
14
|
expect(textarea).to_have_text(re.compile('href="'))
|
|
@@ -28,7 +28,7 @@ def test_iframe_code_can_contain_datalayers(map, live_server, datalayer, page):
|
|
|
28
28
|
def test_iframe_code_can_contain_feature(map, live_server, datalayer, page):
|
|
29
29
|
page.goto(f"{live_server.url}{map.get_absolute_url()}?share")
|
|
30
30
|
page.locator(".icon-container").click()
|
|
31
|
-
textarea = page.
|
|
31
|
+
textarea = page.get_by_label("Iframe")
|
|
32
32
|
expect(textarea).to_be_visible()
|
|
33
33
|
expect(textarea).not_to_have_text(re.compile("feature=Here"))
|
|
34
34
|
# Open options
|
|
@@ -39,7 +39,7 @@ def test_can_remove_user_from_team(live_server, map, user, user2, team, login):
|
|
|
39
39
|
page.get_by_role("link", name="My teams").click()
|
|
40
40
|
with page.expect_navigation():
|
|
41
41
|
page.get_by_role("link", name="Edit").click()
|
|
42
|
-
page.locator("li").filter(has_text="Averell").locator(".close").click()
|
|
42
|
+
page.locator("li").filter(has_text="Averell").locator(".icon-close").click()
|
|
43
43
|
page.get_by_role("button", name="Save").click()
|
|
44
44
|
assert Team.objects.count() == 1
|
|
45
45
|
modified = Team.objects.first()
|
|
@@ -25,7 +25,9 @@ def setup_function():
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
@pytest.mark.xdist_group(name="websockets")
|
|
28
|
-
def test_websocket_connection_can_sync_markers(
|
|
28
|
+
def test_websocket_connection_can_sync_markers(
|
|
29
|
+
new_page, asgi_live_server, tilelayer, wait_for_loaded
|
|
30
|
+
):
|
|
29
31
|
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
30
32
|
map.settings["properties"]["syncEnabled"] = True
|
|
31
33
|
map.save()
|
|
@@ -34,8 +36,10 @@ def test_websocket_connection_can_sync_markers(new_page, asgi_live_server, tilel
|
|
|
34
36
|
# Create two tabs
|
|
35
37
|
peerA = new_page("Page A")
|
|
36
38
|
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
39
|
+
wait_for_loaded(peerA)
|
|
37
40
|
peerB = new_page("Page B")
|
|
38
41
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
42
|
+
wait_for_loaded(peerB)
|
|
39
43
|
|
|
40
44
|
a_marker_pane = peerA.locator(".leaflet-marker-pane > div")
|
|
41
45
|
b_marker_pane = peerB.locator(".leaflet-marker-pane > div")
|
|
@@ -49,6 +53,7 @@ def test_websocket_connection_can_sync_markers(new_page, asgi_live_server, tilel
|
|
|
49
53
|
|
|
50
54
|
a_map_el = peerA.locator("#map")
|
|
51
55
|
a_map_el.click(position={"x": 220, "y": 220})
|
|
56
|
+
peerA.wait_for_timeout(300) # Time for the panel animation to finish
|
|
52
57
|
expect(a_marker_pane).to_have_count(1)
|
|
53
58
|
expect(b_marker_pane).to_have_count(1)
|
|
54
59
|
# Peer B should not be in state dirty
|
|
@@ -91,17 +96,21 @@ def test_websocket_connection_can_sync_markers(new_page, asgi_live_server, tilel
|
|
|
91
96
|
|
|
92
97
|
|
|
93
98
|
@pytest.mark.xdist_group(name="websockets")
|
|
94
|
-
def test_websocket_connection_can_sync_polygons(
|
|
99
|
+
def test_websocket_connection_can_sync_polygons(
|
|
100
|
+
new_page, asgi_live_server, tilelayer, wait_for_loaded
|
|
101
|
+
):
|
|
95
102
|
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
96
103
|
map.settings["properties"]["syncEnabled"] = True
|
|
97
104
|
map.save()
|
|
98
105
|
DataLayerFactory(map=map, data={})
|
|
99
106
|
|
|
100
107
|
# Create two tabs
|
|
101
|
-
peerA =
|
|
108
|
+
peerA = new_page("Page A")
|
|
102
109
|
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
103
|
-
|
|
110
|
+
wait_for_loaded(peerA)
|
|
111
|
+
peerB = new_page("Page B")
|
|
104
112
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
113
|
+
wait_for_loaded(peerB)
|
|
105
114
|
|
|
106
115
|
b_map_el = peerB.locator("#map")
|
|
107
116
|
|
|
@@ -171,7 +180,7 @@ def test_websocket_connection_can_sync_polygons(context, asgi_live_server, tilel
|
|
|
171
180
|
|
|
172
181
|
@pytest.mark.xdist_group(name="websockets")
|
|
173
182
|
def test_websocket_connection_can_sync_map_properties(
|
|
174
|
-
new_page, asgi_live_server, tilelayer
|
|
183
|
+
new_page, asgi_live_server, tilelayer, wait_for_loaded
|
|
175
184
|
):
|
|
176
185
|
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
177
186
|
map.settings["properties"]["syncEnabled"] = True
|
|
@@ -181,8 +190,10 @@ def test_websocket_connection_can_sync_map_properties(
|
|
|
181
190
|
# Create two tabs
|
|
182
191
|
peerA = new_page()
|
|
183
192
|
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
193
|
+
wait_for_loaded(peerA)
|
|
184
194
|
peerB = new_page()
|
|
185
195
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
196
|
+
wait_for_loaded(peerB)
|
|
186
197
|
|
|
187
198
|
# Name change is synced
|
|
188
199
|
peerA.get_by_role("button", name="Edit map name and caption").click()
|
|
@@ -205,7 +216,7 @@ def test_websocket_connection_can_sync_map_properties(
|
|
|
205
216
|
|
|
206
217
|
@pytest.mark.xdist_group(name="websockets")
|
|
207
218
|
def test_websocket_connection_can_sync_datalayer_properties(
|
|
208
|
-
new_page, asgi_live_server, tilelayer
|
|
219
|
+
new_page, asgi_live_server, tilelayer, wait_for_loaded
|
|
209
220
|
):
|
|
210
221
|
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
211
222
|
map.settings["properties"]["syncEnabled"] = True
|
|
@@ -215,8 +226,10 @@ def test_websocket_connection_can_sync_datalayer_properties(
|
|
|
215
226
|
# Create two tabs
|
|
216
227
|
peerA = new_page()
|
|
217
228
|
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
229
|
+
wait_for_loaded(peerA)
|
|
218
230
|
peerB = new_page()
|
|
219
231
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
232
|
+
wait_for_loaded(peerB)
|
|
220
233
|
|
|
221
234
|
# Layer addition, name and type are synced
|
|
222
235
|
peerA.get_by_role("button", name="Manage layers").click()
|
|
@@ -236,7 +249,7 @@ def test_websocket_connection_can_sync_datalayer_properties(
|
|
|
236
249
|
|
|
237
250
|
@pytest.mark.xdist_group(name="websockets")
|
|
238
251
|
def test_websocket_connection_can_sync_cloned_polygons(
|
|
239
|
-
|
|
252
|
+
new_page, asgi_live_server, tilelayer, wait_for_loaded
|
|
240
253
|
):
|
|
241
254
|
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
242
255
|
map.settings["properties"]["syncEnabled"] = True
|
|
@@ -244,10 +257,12 @@ def test_websocket_connection_can_sync_cloned_polygons(
|
|
|
244
257
|
DataLayerFactory(map=map, data={})
|
|
245
258
|
|
|
246
259
|
# Create two tabs
|
|
247
|
-
peerA =
|
|
260
|
+
peerA = new_page("Page A")
|
|
248
261
|
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
249
|
-
|
|
262
|
+
wait_for_loaded(peerA)
|
|
263
|
+
peerB = new_page("Page B")
|
|
250
264
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
265
|
+
wait_for_loaded(peerB)
|
|
251
266
|
|
|
252
267
|
b_map_el = peerB.locator("#map")
|
|
253
268
|
|
|
@@ -297,7 +312,7 @@ def test_websocket_connection_can_sync_cloned_polygons(
|
|
|
297
312
|
|
|
298
313
|
@pytest.mark.xdist_group(name="websockets")
|
|
299
314
|
def test_websocket_connection_can_sync_late_joining_peer(
|
|
300
|
-
new_page, asgi_live_server, tilelayer
|
|
315
|
+
new_page, asgi_live_server, tilelayer, wait_for_loaded
|
|
301
316
|
):
|
|
302
317
|
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
303
318
|
map.settings["properties"]["syncEnabled"] = True
|
|
@@ -307,6 +322,7 @@ def test_websocket_connection_can_sync_late_joining_peer(
|
|
|
307
322
|
# Create first peer (A) and have it join immediately
|
|
308
323
|
peerA = new_page("Page A")
|
|
309
324
|
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
325
|
+
wait_for_loaded(peerA)
|
|
310
326
|
|
|
311
327
|
# Add a marker from peer A
|
|
312
328
|
a_create_marker = peerA.get_by_title("Draw a marker")
|
|
@@ -315,6 +331,7 @@ def test_websocket_connection_can_sync_late_joining_peer(
|
|
|
315
331
|
|
|
316
332
|
a_map_el = peerA.locator("#map")
|
|
317
333
|
a_map_el.click(position={"x": 220, "y": 220})
|
|
334
|
+
peerA.wait_for_timeout(300) # Time for the panel animation to finish
|
|
318
335
|
peerA.locator("body").type("First marker")
|
|
319
336
|
peerA.locator("body").press("Escape")
|
|
320
337
|
peerA.wait_for_timeout(300)
|
|
@@ -333,6 +350,7 @@ def test_websocket_connection_can_sync_late_joining_peer(
|
|
|
333
350
|
# Now create peer B and have it join
|
|
334
351
|
peerB = new_page("Page B")
|
|
335
352
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
353
|
+
wait_for_loaded(peerB)
|
|
336
354
|
|
|
337
355
|
# Check if peer B has received all the updates
|
|
338
356
|
b_marker_pane = peerB.locator(".leaflet-marker-pane > div")
|
|
@@ -357,7 +375,7 @@ def test_websocket_connection_can_sync_late_joining_peer(
|
|
|
357
375
|
|
|
358
376
|
|
|
359
377
|
@pytest.mark.xdist_group(name="websockets")
|
|
360
|
-
def test_should_sync_datalayers(new_page, asgi_live_server, tilelayer):
|
|
378
|
+
def test_should_sync_datalayers(new_page, asgi_live_server, tilelayer, wait_for_loaded):
|
|
361
379
|
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
362
380
|
map.settings["properties"]["syncEnabled"] = True
|
|
363
381
|
map.save()
|
|
@@ -367,8 +385,10 @@ def test_should_sync_datalayers(new_page, asgi_live_server, tilelayer):
|
|
|
367
385
|
# Create two tabs
|
|
368
386
|
peerA = new_page("Page A")
|
|
369
387
|
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
388
|
+
wait_for_loaded(peerA)
|
|
370
389
|
peerB = new_page("Page B")
|
|
371
390
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
391
|
+
wait_for_loaded(peerB)
|
|
372
392
|
|
|
373
393
|
# Create a new layer from peerA
|
|
374
394
|
peerA.get_by_role("button", name="Manage layers").click()
|
|
@@ -398,7 +418,7 @@ def test_should_sync_datalayers(new_page, asgi_live_server, tilelayer):
|
|
|
398
418
|
peerA.locator("#map").click()
|
|
399
419
|
|
|
400
420
|
# Make sure this new marker is in Layer 2 for peerB
|
|
401
|
-
# Show features for this layer in the
|
|
421
|
+
# Show features for this layer in the browser.
|
|
402
422
|
peerB.locator("summary").filter(has_text="Layer 2").click()
|
|
403
423
|
expect(peerB.locator("li").filter(has_text="Layer 2")).to_be_visible()
|
|
404
424
|
peerB.locator(".panel.left").get_by_role("button", name="Show/hide layer").nth(
|
|
@@ -433,7 +453,9 @@ def test_should_sync_datalayers(new_page, asgi_live_server, tilelayer):
|
|
|
433
453
|
|
|
434
454
|
|
|
435
455
|
@pytest.mark.xdist_group(name="websockets")
|
|
436
|
-
def test_should_sync_datalayers_delete(
|
|
456
|
+
def test_should_sync_datalayers_delete(
|
|
457
|
+
new_page, asgi_live_server, tilelayer, wait_for_loaded
|
|
458
|
+
):
|
|
437
459
|
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
438
460
|
map.settings["properties"]["syncEnabled"] = True
|
|
439
461
|
map.save()
|
|
@@ -473,8 +495,10 @@ def test_should_sync_datalayers_delete(new_page, asgi_live_server, tilelayer):
|
|
|
473
495
|
# Create two tabs
|
|
474
496
|
peerA = new_page("Page A")
|
|
475
497
|
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
498
|
+
wait_for_loaded(peerA)
|
|
476
499
|
peerB = new_page("Page B")
|
|
477
500
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
501
|
+
wait_for_loaded(peerB)
|
|
478
502
|
|
|
479
503
|
peerA.get_by_role("button", name="Open browser").click()
|
|
480
504
|
expect(peerA.locator(".panel").get_by_text("datalayer 1")).to_be_visible()
|
|
@@ -496,10 +520,13 @@ def test_should_sync_datalayers_delete(new_page, asgi_live_server, tilelayer):
|
|
|
496
520
|
|
|
497
521
|
|
|
498
522
|
@pytest.mark.xdist_group(name="websockets")
|
|
499
|
-
def test_create_and_sync_map(
|
|
523
|
+
def test_create_and_sync_map(
|
|
524
|
+
new_page, asgi_live_server, tilelayer, login, user, wait_for_loaded
|
|
525
|
+
):
|
|
500
526
|
# Create a syncable map with peerA
|
|
501
527
|
peerA = login(user, prefix="Page A")
|
|
502
528
|
peerA.goto(f"{asgi_live_server.url}/en/map/new/")
|
|
529
|
+
wait_for_loaded(peerA)
|
|
503
530
|
peerA.get_by_role("button", name="Map advanced properties").click()
|
|
504
531
|
expect(peerA.get_by_text("Real-time collaboration", exact=True)).to_be_hidden()
|
|
505
532
|
with peerA.expect_response(re.compile("./map/create/.*")):
|
|
@@ -519,6 +546,7 @@ def test_create_and_sync_map(new_page, asgi_live_server, tilelayer, login, user)
|
|
|
519
546
|
# Open map and go to edit mode with peer B
|
|
520
547
|
peerB = new_page("Page B")
|
|
521
548
|
peerB.goto(peerA.url)
|
|
549
|
+
wait_for_loaded(peerB)
|
|
522
550
|
peerB.get_by_role("button", name="Edit").click()
|
|
523
551
|
|
|
524
552
|
# Create a marker from peerA
|
|
@@ -529,8 +557,10 @@ def test_create_and_sync_map(new_page, asgi_live_server, tilelayer, login, user)
|
|
|
529
557
|
|
|
530
558
|
# Add a marker from peer A
|
|
531
559
|
peerA.get_by_role("button", name="Edit").click()
|
|
560
|
+
peerA.wait_for_timeout(300) # Time for the animation to finish
|
|
532
561
|
peerA.get_by_title("Draw a marker").click()
|
|
533
562
|
peerA.locator("#map").click(position={"x": 220, "y": 220})
|
|
563
|
+
peerA.wait_for_timeout(300) # Time for the panel animation to finish
|
|
534
564
|
expect(markersA).to_have_count(1)
|
|
535
565
|
expect(markersB).to_have_count(1)
|
|
536
566
|
|
|
@@ -556,6 +586,7 @@ def test_create_and_sync_map(new_page, asgi_live_server, tilelayer, login, user)
|
|
|
556
586
|
# Add a marker from peer B
|
|
557
587
|
peerB.get_by_title("Draw a marker").click()
|
|
558
588
|
peerB.locator("#map").click(position={"x": 200, "y": 200})
|
|
589
|
+
peerA.wait_for_timeout(300) # Time for the panel animation to finish
|
|
559
590
|
expect(markersB).to_have_count(2)
|
|
560
591
|
expect(markersA).to_have_count(1)
|
|
561
592
|
with peerB.expect_response(re.compile("./datalayer/update/.*")):
|
|
@@ -568,7 +599,9 @@ def test_create_and_sync_map(new_page, asgi_live_server, tilelayer, login, user)
|
|
|
568
599
|
|
|
569
600
|
|
|
570
601
|
@pytest.mark.xdist_group(name="websockets")
|
|
571
|
-
def test_saved_datalayer_are_not_duplicated(
|
|
602
|
+
def test_saved_datalayer_are_not_duplicated(
|
|
603
|
+
new_page, asgi_live_server, tilelayer, wait_for_loaded
|
|
604
|
+
):
|
|
572
605
|
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
573
606
|
map.settings["properties"]["syncEnabled"] = True
|
|
574
607
|
map.save()
|
|
@@ -576,9 +609,10 @@ def test_saved_datalayer_are_not_duplicated(new_page, asgi_live_server, tilelaye
|
|
|
576
609
|
# Create one tab
|
|
577
610
|
peerA = new_page("Page A")
|
|
578
611
|
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
612
|
+
wait_for_loaded(peerA)
|
|
579
613
|
# Create a new datalayer
|
|
580
614
|
peerA.get_by_title("Manage layers").click()
|
|
581
|
-
peerA.
|
|
615
|
+
peerA.get_by_role("button", name="Add a layer").click()
|
|
582
616
|
peerA.locator("#map").click(position={"x": 220, "y": 220})
|
|
583
617
|
# Save layer to the server, so now the datalayer exist on the server AND
|
|
584
618
|
# is still in the live operations of peer A
|
|
@@ -588,6 +622,7 @@ def test_saved_datalayer_are_not_duplicated(new_page, asgi_live_server, tilelaye
|
|
|
588
622
|
# Now load the map from another tab
|
|
589
623
|
peerB = new_page("Page B")
|
|
590
624
|
peerB.goto(peerA.url)
|
|
625
|
+
wait_for_loaded(peerB)
|
|
591
626
|
peerB.get_by_role("button", name="Open browser").click()
|
|
592
627
|
expect(peerB.get_by_text("Layer 1")).to_be_visible()
|
|
593
628
|
peerB.get_by_role("button", name="Edit").click()
|
|
@@ -596,7 +631,9 @@ def test_saved_datalayer_are_not_duplicated(new_page, asgi_live_server, tilelaye
|
|
|
596
631
|
|
|
597
632
|
|
|
598
633
|
@pytest.mark.xdist_group(name="websockets")
|
|
599
|
-
def test_should_sync_saved_status(
|
|
634
|
+
def test_should_sync_saved_status(
|
|
635
|
+
new_page, asgi_live_server, tilelayer, wait_for_loaded
|
|
636
|
+
):
|
|
600
637
|
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
601
638
|
map.settings["properties"]["syncEnabled"] = True
|
|
602
639
|
map.save()
|
|
@@ -604,8 +641,10 @@ def test_should_sync_saved_status(new_page, asgi_live_server, tilelayer):
|
|
|
604
641
|
# Create two tabs
|
|
605
642
|
peerA = new_page("Page A")
|
|
606
643
|
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
644
|
+
wait_for_loaded(peerA)
|
|
607
645
|
peerB = new_page("Page B")
|
|
608
646
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
647
|
+
wait_for_loaded(peerB)
|
|
609
648
|
|
|
610
649
|
# Create a new marker from peerA
|
|
611
650
|
peerA.get_by_title("Draw a marker").click()
|
|
@@ -639,7 +678,9 @@ def test_should_sync_saved_status(new_page, asgi_live_server, tilelayer):
|
|
|
639
678
|
|
|
640
679
|
|
|
641
680
|
@pytest.mark.xdist_group(name="websockets")
|
|
642
|
-
def test_should_sync_line_on_escape(
|
|
681
|
+
def test_should_sync_line_on_escape(
|
|
682
|
+
new_page, asgi_live_server, tilelayer, wait_for_loaded
|
|
683
|
+
):
|
|
643
684
|
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
644
685
|
map.settings["properties"]["syncEnabled"] = True
|
|
645
686
|
map.save()
|
|
@@ -647,8 +688,10 @@ def test_should_sync_line_on_escape(new_page, asgi_live_server, tilelayer):
|
|
|
647
688
|
# Create two tabs
|
|
648
689
|
peerA = new_page("Page A")
|
|
649
690
|
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
691
|
+
wait_for_loaded(peerA)
|
|
650
692
|
peerB = new_page("Page B")
|
|
651
693
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
694
|
+
wait_for_loaded(peerB)
|
|
652
695
|
|
|
653
696
|
# Create a new marker from peerA
|
|
654
697
|
peerA.get_by_title("Draw a polyline").click()
|
|
@@ -662,7 +705,7 @@ def test_should_sync_line_on_escape(new_page, asgi_live_server, tilelayer):
|
|
|
662
705
|
|
|
663
706
|
@pytest.mark.xdist_group(name="websockets")
|
|
664
707
|
def test_should_sync_datalayer_clear(
|
|
665
|
-
new_page, asgi_live_server, tilelayer, map, datalayer
|
|
708
|
+
new_page, asgi_live_server, tilelayer, map, datalayer, wait_for_loaded
|
|
666
709
|
):
|
|
667
710
|
map.settings["properties"]["syncEnabled"] = True
|
|
668
711
|
map.edit_status = Map.ANONYMOUS
|
|
@@ -671,8 +714,10 @@ def test_should_sync_datalayer_clear(
|
|
|
671
714
|
# Create two tabs
|
|
672
715
|
peerA = new_page("Page A")
|
|
673
716
|
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
717
|
+
wait_for_loaded(peerA)
|
|
674
718
|
peerB = new_page("Page B")
|
|
675
719
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
720
|
+
wait_for_loaded(peerB)
|
|
676
721
|
expect(peerA.locator(".leaflet-marker-icon")).to_have_count(1)
|
|
677
722
|
expect(peerB.locator(".leaflet-marker-icon")).to_have_count(1)
|
|
678
723
|
|
|
@@ -691,7 +736,9 @@ def test_should_sync_datalayer_clear(
|
|
|
691
736
|
|
|
692
737
|
|
|
693
738
|
@pytest.mark.xdist_group(name="websockets")
|
|
694
|
-
def test_should_save_remote_dirty_datalayers(
|
|
739
|
+
def test_should_save_remote_dirty_datalayers(
|
|
740
|
+
new_page, asgi_live_server, tilelayer, wait_for_loaded
|
|
741
|
+
):
|
|
695
742
|
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
696
743
|
map.settings["properties"]["syncEnabled"] = True
|
|
697
744
|
map.save()
|
|
@@ -701,8 +748,10 @@ def test_should_save_remote_dirty_datalayers(new_page, asgi_live_server, tilelay
|
|
|
701
748
|
# Create two tabs
|
|
702
749
|
peerA = new_page("Page A")
|
|
703
750
|
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
751
|
+
wait_for_loaded(peerA)
|
|
704
752
|
peerB = new_page("Page B")
|
|
705
753
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
754
|
+
wait_for_loaded(peerB)
|
|
706
755
|
|
|
707
756
|
# Create a new layer from peerA
|
|
708
757
|
peerA.get_by_role("button", name="Manage layers").click()
|
umap/tests/test_dashboard.py
CHANGED
|
@@ -68,7 +68,7 @@ def test_user_dashboard_display_user_team_maps(client, map, team, user, share_st
|
|
|
68
68
|
|
|
69
69
|
def test_user_dashboard_display_user_maps_distinct(client, map):
|
|
70
70
|
# cf https://github.com/umap-project/umap/issues/1325
|
|
71
|
-
anonymap = MapFactory(name="Map
|
|
71
|
+
anonymap = MapFactory(name="Map without owner should not appear")
|
|
72
72
|
user1 = UserFactory(username="user1")
|
|
73
73
|
user2 = UserFactory(username="user2")
|
|
74
74
|
map.editors.add(user1)
|
umap/tests/test_statics.py
CHANGED
|
@@ -32,9 +32,9 @@ def test_collectstatic_ran_successfully_with_hashes(settings, staticfiles):
|
|
|
32
32
|
assert "hash" in json_manifest.keys()
|
|
33
33
|
assert "umap/base.css" in json_manifest["paths"]
|
|
34
34
|
# Hash + the dot ("umap/base.<hash>.css").
|
|
35
|
-
|
|
35
|
+
md5_hash_length = 12 + 1
|
|
36
36
|
# The value of the manifest must contain the hash (length).
|
|
37
37
|
assert (
|
|
38
38
|
len(json_manifest["paths"]["umap/base.css"])
|
|
39
|
-
== len("umap/base.css") +
|
|
39
|
+
== len("umap/base.css") + md5_hash_length
|
|
40
40
|
)
|
umap/tests/test_utils.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import stat
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
|
|
3
4
|
import pytest
|
|
@@ -5,7 +6,8 @@ import pytest
|
|
|
5
6
|
from umap.utils import gzip_file, normalize_string
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
def test_gzip_file():
|
|
9
|
+
def test_gzip_file(settings):
|
|
10
|
+
settings.FILE_UPLOAD_PERMISSIONS = 0o666
|
|
9
11
|
# Let's use any old file so we can check that the date of the gzip file is set.
|
|
10
12
|
src = Path(__file__).parent / "settings.py"
|
|
11
13
|
dest = Path("/tmp/test_settings.py.gz")
|
|
@@ -14,6 +16,7 @@ def test_gzip_file():
|
|
|
14
16
|
dest_stat = dest.stat()
|
|
15
17
|
dest.unlink()
|
|
16
18
|
assert src_stat.st_mtime == dest_stat.st_mtime
|
|
19
|
+
assert stat.filemode(dest_stat.st_mode) == "-rw-rw-rw-"
|
|
17
20
|
|
|
18
21
|
|
|
19
22
|
@pytest.mark.parametrize(
|
umap/tests/test_views.py
CHANGED
umap/utils.py
CHANGED
|
@@ -80,7 +80,7 @@ def get_uri_template(urlname, args=None, prefix="", module=None):
|
|
|
80
80
|
result, params = possibility[0]
|
|
81
81
|
return _convert(result, params)
|
|
82
82
|
else:
|
|
83
|
-
# If there are
|
|
83
|
+
# If there are optional arguments passed, use them to try to find
|
|
84
84
|
# the correct pattern.
|
|
85
85
|
# First, we need to build a list with all the arguments
|
|
86
86
|
seen_params = []
|
|
@@ -150,6 +150,7 @@ def gzip_file(from_path, to_path):
|
|
|
150
150
|
with gzip.open(to_path, "wb") as f_out:
|
|
151
151
|
f_out.writelines(f_in)
|
|
152
152
|
os.utime(to_path, ns=(stat.st_mtime_ns, stat.st_mtime_ns))
|
|
153
|
+
os.chmod(to_path, settings.FILE_UPLOAD_PERMISSIONS)
|
|
153
154
|
|
|
154
155
|
|
|
155
156
|
def is_ajax(request):
|
|
@@ -226,5 +227,5 @@ def collect_pictograms():
|
|
|
226
227
|
|
|
227
228
|
|
|
228
229
|
def normalize_string(s):
|
|
229
|
-
n = unicodedata.normalize("NFKD", s)
|
|
230
|
+
n = unicodedata.normalize("NFKD", str(s))
|
|
230
231
|
return "".join([c for c in n if not unicodedata.combining(c)]).lower()
|