c2cgeoportal-admin 2.5.0.100__py3-none-any.whl → 2.7.1.156__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.
- c2cgeoportal_admin/__init__.py +19 -12
- c2cgeoportal_admin/lib/__init__.py +0 -0
- c2cgeoportal_admin/lib/lingua_extractor.py +77 -0
- c2cgeoportal_admin/lib/ogcserver_synchronizer.py +409 -0
- c2cgeoportal_admin/py.typed +0 -0
- c2cgeoportal_admin/routes.py +18 -10
- c2cgeoportal_admin/schemas/dimensions.py +13 -11
- c2cgeoportal_admin/schemas/functionalities.py +63 -22
- c2cgeoportal_admin/schemas/interfaces.py +23 -19
- c2cgeoportal_admin/schemas/metadata.py +121 -47
- c2cgeoportal_admin/schemas/restriction_areas.py +22 -20
- c2cgeoportal_admin/schemas/roles.py +8 -6
- c2cgeoportal_admin/schemas/treegroup.py +84 -18
- c2cgeoportal_admin/schemas/treeitem.py +2 -3
- c2cgeoportal_admin/static/layertree.css +26 -4
- c2cgeoportal_admin/static/navbar.css +59 -36
- c2cgeoportal_admin/static/theme.css +48 -11
- c2cgeoportal_admin/subscribers.py +3 -3
- c2cgeoportal_admin/templates/404.jinja2 +23 -0
- c2cgeoportal_admin/templates/edit.jinja2 +23 -0
- c2cgeoportal_admin/templates/home.jinja2 +23 -0
- c2cgeoportal_admin/templates/index.jinja2 +23 -0
- c2cgeoportal_admin/templates/layertree.jinja2 +55 -11
- c2cgeoportal_admin/templates/layout.jinja2 +23 -0
- c2cgeoportal_admin/templates/navigation_navbar.jinja2 +56 -0
- c2cgeoportal_admin/templates/ogcserver_synchronize.jinja2 +90 -0
- c2cgeoportal_admin/templates/widgets/child.pt +35 -3
- c2cgeoportal_admin/templates/widgets/children.pt +121 -92
- c2cgeoportal_admin/templates/widgets/dimension.pt +23 -0
- c2cgeoportal_admin/templates/widgets/dimensions.pt +23 -0
- c2cgeoportal_admin/templates/widgets/functionality_fields.pt +51 -0
- c2cgeoportal_admin/templates/widgets/layer_fields.pt +23 -0
- c2cgeoportal_admin/templates/widgets/layer_group_fields.pt +23 -0
- c2cgeoportal_admin/templates/widgets/layer_v1_fields.pt +23 -0
- c2cgeoportal_admin/templates/widgets/metadata.pt +30 -1
- c2cgeoportal_admin/templates/widgets/metadatas.pt +23 -0
- c2cgeoportal_admin/templates/widgets/ogcserver_fields.pt +23 -0
- c2cgeoportal_admin/templates/widgets/restriction_area_fields.pt +25 -9
- c2cgeoportal_admin/templates/widgets/role_fields.pt +52 -25
- c2cgeoportal_admin/templates/widgets/theme_fields.pt +23 -0
- c2cgeoportal_admin/templates/widgets/user_fields.pt +23 -0
- c2cgeoportal_admin/views/dimension_layers.py +7 -6
- c2cgeoportal_admin/views/functionalities.py +31 -5
- c2cgeoportal_admin/views/home.py +5 -5
- c2cgeoportal_admin/views/interfaces.py +8 -8
- c2cgeoportal_admin/views/layer_groups.py +9 -11
- c2cgeoportal_admin/views/layers.py +8 -7
- c2cgeoportal_admin/views/layers_vectortiles.py +30 -10
- c2cgeoportal_admin/views/layers_wms.py +45 -37
- c2cgeoportal_admin/views/layers_wmts.py +39 -33
- c2cgeoportal_admin/views/layertree.py +34 -26
- c2cgeoportal_admin/views/oauth2_clients.py +89 -0
- c2cgeoportal_admin/views/ogc_servers.py +130 -27
- c2cgeoportal_admin/views/restriction_areas.py +50 -8
- c2cgeoportal_admin/views/roles.py +60 -8
- c2cgeoportal_admin/views/themes.py +15 -14
- c2cgeoportal_admin/views/themes_ordering.py +38 -18
- c2cgeoportal_admin/views/treeitems.py +12 -11
- c2cgeoportal_admin/views/users.py +7 -5
- c2cgeoportal_admin/widgets.py +79 -28
- {c2cgeoportal_admin-2.5.0.100.dist-info → c2cgeoportal_admin-2.7.1.156.dist-info}/METADATA +16 -11
- c2cgeoportal_admin-2.7.1.156.dist-info/RECORD +92 -0
- {c2cgeoportal_admin-2.5.0.100.dist-info → c2cgeoportal_admin-2.7.1.156.dist-info}/WHEEL +1 -1
- c2cgeoportal_admin-2.7.1.156.dist-info/entry_points.txt +5 -0
- tests/__init__.py +23 -18
- tests/conftest.py +4 -15
- tests/test_edit_url.py +16 -18
- tests/test_functionalities.py +23 -10
- tests/test_interface.py +8 -8
- tests/test_layer_groups.py +15 -23
- tests/test_layers_vectortiles.py +16 -20
- tests/test_layers_wms.py +37 -75
- tests/test_layers_wmts.py +20 -24
- tests/test_layertree.py +107 -100
- tests/test_learn.py +1 -1
- tests/test_lingua_extractor_config.py +66 -0
- tests/test_main.py +4 -2
- tests/test_metadatas.py +79 -70
- tests/test_oauth2_clients.py +157 -0
- tests/test_ogc_servers.py +51 -7
- tests/test_restriction_areas.py +81 -17
- tests/test_role.py +110 -76
- tests/test_themes.py +44 -37
- tests/test_themes_ordering.py +1 -1
- tests/test_treegroup.py +2 -2
- tests/test_user.py +31 -64
- tests/themes_ordering.py +1 -1
- c2cgeoportal_admin/templates/navigation_vertical.jinja2 +0 -10
- c2cgeoportal_admin-2.5.0.100.dist-info/RECORD +0 -84
- c2cgeoportal_admin-2.5.0.100.dist-info/entry_points.txt +0 -3
- {c2cgeoportal_admin-2.5.0.100.dist-info → c2cgeoportal_admin-2.7.1.156.dist-info}/top_level.txt +0 -0
tests/test_role.py
CHANGED
@@ -3,14 +3,12 @@
|
|
3
3
|
import json
|
4
4
|
import re
|
5
5
|
|
6
|
+
import pytest
|
6
7
|
from geoalchemy2.shape import from_shape, to_shape
|
7
8
|
from pyramid.testing import DummyRequest
|
8
|
-
import pytest
|
9
|
-
from selenium.webdriver.common.by import By
|
10
9
|
from shapely.geometry import Polygon, box, shape
|
11
10
|
|
12
|
-
from . import
|
13
|
-
from .selenium.page import IndexPage
|
11
|
+
from .test_treegroup import TestTreeGroup
|
14
12
|
|
15
13
|
|
16
14
|
@pytest.fixture(scope="function")
|
@@ -18,20 +16,21 @@ from .selenium.page import IndexPage
|
|
18
16
|
def roles_test_data(dbsession, transact):
|
19
17
|
del transact
|
20
18
|
|
21
|
-
from c2cgeoportal_commons.models.main import
|
19
|
+
from c2cgeoportal_commons.models.main import Functionality, RestrictionArea, Role
|
22
20
|
from c2cgeoportal_commons.models.static import User
|
23
21
|
|
22
|
+
# Note that "default_basemap" is not relevant for roles
|
24
23
|
functionalities = {}
|
25
|
-
for name in ("default_basemap", "
|
24
|
+
for name in ("default_basemap", "default_theme", "print_template"):
|
26
25
|
functionalities[name] = []
|
27
26
|
for v in range(0, 4):
|
28
|
-
functionality = Functionality(name=name, value="value_{}"
|
27
|
+
functionality = Functionality(name=name, value=f"value_{v}")
|
29
28
|
dbsession.add(functionality)
|
30
29
|
functionalities[name].append(functionality)
|
31
30
|
|
32
31
|
restrictionareas = []
|
33
32
|
for i in range(0, 5):
|
34
|
-
restrictionarea = RestrictionArea(name="restrictionarea_{}"
|
33
|
+
restrictionarea = RestrictionArea(name=f"restrictionarea_{i}")
|
35
34
|
dbsession.add(restrictionarea)
|
36
35
|
restrictionareas.append(restrictionarea)
|
37
36
|
|
@@ -39,9 +38,9 @@ def roles_test_data(dbsession, transact):
|
|
39
38
|
for i in range(0, 23):
|
40
39
|
role = Role("secretary_" + str(i))
|
41
40
|
role.functionalities = [
|
42
|
-
functionalities["
|
43
|
-
functionalities["
|
44
|
-
functionalities["
|
41
|
+
functionalities["default_theme"][0],
|
42
|
+
functionalities["print_template"][0],
|
43
|
+
functionalities["print_template"][1],
|
45
44
|
]
|
46
45
|
role.restrictionareas = [restrictionareas[0], restrictionareas[1]]
|
47
46
|
role.extent = from_shape(box(485869.5728, 76443.1884, 837076.5648, 299941.7864), srid=21781)
|
@@ -68,7 +67,7 @@ def roles_test_data(dbsession, transact):
|
|
68
67
|
|
69
68
|
|
70
69
|
@pytest.mark.usefixtures("roles_test_data", "test_app")
|
71
|
-
class TestRole(
|
70
|
+
class TestRole(TestTreeGroup):
|
72
71
|
|
73
72
|
_prefix = "/admin/roles"
|
74
73
|
|
@@ -87,24 +86,80 @@ class TestRole(AbstractViewsTests):
|
|
87
86
|
]
|
88
87
|
self.check_grid_headers(resp, expected)
|
89
88
|
|
90
|
-
@pytest.mark.skip(reason="Translation
|
89
|
+
@pytest.mark.skip(reason="Translation seems not available in tests")
|
91
90
|
def test_index_rendering_fr(self, test_app):
|
92
91
|
resp = self.get(test_app, locale="fr")
|
93
92
|
|
94
|
-
self.check_left_menu(resp, "
|
93
|
+
self.check_left_menu(resp, "Rôles")
|
95
94
|
|
96
95
|
expected = [
|
97
|
-
("
|
98
|
-
("
|
96
|
+
("actions", "", "false"),
|
97
|
+
("id", "id", "true"),
|
98
|
+
("name", "Nom"),
|
99
99
|
("description", "Description"),
|
100
|
-
("functionalities", "
|
101
|
-
("restrictionareas", "
|
100
|
+
("functionalities", "Fonctionnalités", "false"),
|
101
|
+
("restrictionareas", "Zones de restriction", "false"),
|
102
102
|
]
|
103
|
-
self.check_grid_headers(resp, expected)
|
103
|
+
self.check_grid_headers(resp, expected, new="Nouveau")
|
104
|
+
|
105
|
+
def test_submit_new(self, dbsession, test_app, roles_test_data):
|
106
|
+
from c2cgeoportal_commons.models.main import Role
|
107
|
+
|
108
|
+
roles = roles_test_data["roles"]
|
109
|
+
functionalities = roles_test_data["functionalities"]
|
110
|
+
restrictionareas = roles_test_data["restrictionareas"]
|
111
|
+
users = roles_test_data["users"]
|
112
|
+
|
113
|
+
resp = test_app.post(
|
114
|
+
"/admin/roles/new",
|
115
|
+
(
|
116
|
+
("_charset_", "UTF-8"),
|
117
|
+
("__formid__", "deform"),
|
118
|
+
("id", ""),
|
119
|
+
("name", "new_name"),
|
120
|
+
("description", "new_description"),
|
121
|
+
("extent", ""),
|
122
|
+
("__start__", "functionalities:sequence"),
|
123
|
+
("functionalities", str(functionalities["default_basemap"][0].id)),
|
124
|
+
("functionalities", str(functionalities["print_template"][1].id)),
|
125
|
+
("__end__", "functionalities:sequence"),
|
126
|
+
("__start__", "restrictionareas:sequence"),
|
127
|
+
("restrictionareas", str(restrictionareas[0].id)),
|
128
|
+
("restrictionareas", str(restrictionareas[1].id)),
|
129
|
+
("__end__", "restrictionareas:sequence"),
|
130
|
+
("__start__", "users:sequence"),
|
131
|
+
("__start__", "user:mapping"),
|
132
|
+
("id", str(users[0].id)),
|
133
|
+
("__end__", "user:mapping"),
|
134
|
+
("__start__", "user:mapping"),
|
135
|
+
("id", str(users[1].id)),
|
136
|
+
("__end__", "user:mapping"),
|
137
|
+
("__end__", "users:sequence"),
|
138
|
+
("formsubmit", "formsubmit"),
|
139
|
+
),
|
140
|
+
status=302,
|
141
|
+
)
|
142
|
+
|
143
|
+
role = dbsession.query(Role).filter(Role.name == "new_name").one()
|
144
|
+
assert str(role.id) == re.match(
|
145
|
+
r"http://localhost/admin/roles/(.*)\?msg_col=submit_ok", resp.location
|
146
|
+
).group(1)
|
147
|
+
|
148
|
+
assert role.name == "new_name"
|
149
|
+
assert role.description == "new_description"
|
150
|
+
assert set(role.functionalities) == {
|
151
|
+
functionalities["default_basemap"][0],
|
152
|
+
functionalities["print_template"][1],
|
153
|
+
}
|
154
|
+
assert set(role.restrictionareas) == {restrictionareas[0], restrictionareas[1]}
|
155
|
+
assert set(role.users) == {users[0], users[1]}
|
104
156
|
|
105
157
|
def test_edit(self, dbsession, test_app, roles_test_data):
|
106
158
|
role = roles_test_data["roles"][10]
|
107
159
|
|
160
|
+
# Ensure role.users is loaded with relationship "order_by"
|
161
|
+
dbsession.expire(role)
|
162
|
+
|
108
163
|
form = self.get_item(test_app, role.id).form
|
109
164
|
|
110
165
|
assert "secretary_10" == form["name"].value
|
@@ -121,30 +176,33 @@ class TestRole(AbstractViewsTests):
|
|
121
176
|
assert expected.almost_equals(shape(json.loads(form["extent"].value)), decimal=0)
|
122
177
|
|
123
178
|
functionalities = roles_test_data["functionalities"]
|
124
|
-
assert
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
)
|
130
|
-
) == set(f.id for f in role.functionalities)
|
179
|
+
assert {
|
180
|
+
functionalities["default_theme"][0].id,
|
181
|
+
functionalities["print_template"][0].id,
|
182
|
+
functionalities["print_template"][1].id,
|
183
|
+
} == {f.id for f in role.functionalities}
|
131
184
|
self.check_checkboxes(
|
132
185
|
form,
|
133
186
|
"functionalities",
|
134
187
|
[
|
135
188
|
{
|
136
|
-
"label": "{}={
|
189
|
+
"label": f"{f.name}={f.value}",
|
137
190
|
"value": str(f.id),
|
138
191
|
"checked": f in role.functionalities,
|
139
192
|
}
|
140
|
-
for f in
|
141
|
-
[
|
193
|
+
for f in sorted(
|
194
|
+
[
|
195
|
+
f
|
196
|
+
for f in sum(functionalities.values(), [])
|
197
|
+
if f.name in ("default_theme", "print_template")
|
198
|
+
],
|
199
|
+
key=lambda f: (f.name, f.value),
|
142
200
|
)
|
143
201
|
],
|
144
202
|
)
|
145
203
|
|
146
204
|
ras = roles_test_data["restrictionareas"]
|
147
|
-
assert
|
205
|
+
assert {ras[0].id, ras[1].id} == {ra.id for ra in role.restrictionareas}
|
148
206
|
self.check_checkboxes(
|
149
207
|
form,
|
150
208
|
"restrictionareas",
|
@@ -154,6 +212,15 @@ class TestRole(AbstractViewsTests):
|
|
154
212
|
],
|
155
213
|
)
|
156
214
|
|
215
|
+
self.check_children(
|
216
|
+
form,
|
217
|
+
"users",
|
218
|
+
[
|
219
|
+
{"label": user.username, "values": {"id": str(user.id)}}
|
220
|
+
for user in sorted(role.users, key=lambda u: u.username)
|
221
|
+
],
|
222
|
+
)
|
223
|
+
|
157
224
|
form["name"] = "New name"
|
158
225
|
form["description"] = "New description"
|
159
226
|
form["extent"] = json.dumps(
|
@@ -172,9 +239,9 @@ class TestRole(AbstractViewsTests):
|
|
172
239
|
)
|
173
240
|
|
174
241
|
functionality_ids = [
|
175
|
-
roles_test_data["functionalities"]["
|
176
|
-
roles_test_data["functionalities"]["
|
177
|
-
roles_test_data["functionalities"]["
|
242
|
+
roles_test_data["functionalities"]["default_theme"][1].id,
|
243
|
+
roles_test_data["functionalities"]["print_template"][1].id,
|
244
|
+
roles_test_data["functionalities"]["print_template"][2].id,
|
178
245
|
]
|
179
246
|
form["functionalities"] = [str(id) for id in functionality_ids]
|
180
247
|
|
@@ -203,18 +270,18 @@ class TestRole(AbstractViewsTests):
|
|
203
270
|
)
|
204
271
|
assert expected.almost_equals(to_shape(role.extent), decimal=0)
|
205
272
|
|
206
|
-
assert set(functionality_ids) ==
|
207
|
-
assert set(ra_ids) ==
|
273
|
+
assert set(functionality_ids) == {f.id for f in role.functionalities}
|
274
|
+
assert set(ra_ids) == {f.id for f in role.restrictionareas}
|
208
275
|
|
209
276
|
def test_duplicate(self, roles_test_data, test_app, dbsession):
|
210
277
|
from c2cgeoportal_commons.models.main import Role
|
211
278
|
|
212
279
|
role_proto = roles_test_data["roles"][7]
|
213
280
|
|
214
|
-
resp = test_app.get("/admin/roles/{}/duplicate"
|
281
|
+
resp = test_app.get(f"/admin/roles/{role_proto.id}/duplicate", status=200)
|
215
282
|
form = resp.form
|
216
283
|
|
217
|
-
assert "" == form
|
284
|
+
assert "" == self.get_first_field_named(form, "id").value
|
218
285
|
assert role_proto.name == form["name"].value
|
219
286
|
assert role_proto.description == form["description"].value
|
220
287
|
form["name"].value = "clone"
|
@@ -225,26 +292,24 @@ class TestRole(AbstractViewsTests):
|
|
225
292
|
r"http://localhost/admin/roles/(.*)\?msg_col=submit_ok", resp.location
|
226
293
|
).group(1)
|
227
294
|
assert role_proto.id != role.id
|
228
|
-
assert role_proto.functionalities
|
229
|
-
assert role_proto.
|
230
|
-
assert role_proto.
|
231
|
-
assert role_proto.restrictionareas[1].name == role.restrictionareas[1].name
|
232
|
-
assert role_proto.restrictionareas[1].id == role.restrictionareas[1].id
|
295
|
+
assert set(role_proto.functionalities) == set(role.functionalities)
|
296
|
+
assert set(role_proto.restrictionareas) == set(role.restrictionareas)
|
297
|
+
assert set(role_proto.users) == set(role.users)
|
233
298
|
|
234
299
|
def test_delete(self, test_app, dbsession):
|
235
300
|
from c2cgeoportal_commons.models.main import Role
|
236
301
|
|
237
302
|
role_id = dbsession.query(Role.id).first().id
|
238
|
-
test_app.delete("/admin/roles/{}"
|
303
|
+
test_app.delete(f"/admin/roles/{role_id}", status=200)
|
239
304
|
assert dbsession.query(Role).get(role_id) is None
|
240
305
|
|
241
306
|
def test_unicity_validator(self, roles_test_data, test_app):
|
242
307
|
role_proto = roles_test_data["roles"][7]
|
243
|
-
resp = test_app.get("/admin/roles/{}/duplicate"
|
308
|
+
resp = test_app.get(f"/admin/roles/{role_proto.id}/duplicate", status=200)
|
244
309
|
|
245
310
|
resp = resp.form.submit("submit")
|
246
311
|
|
247
|
-
self._check_submission_problem(resp, "{} is already used."
|
312
|
+
self._check_submission_problem(resp, f"{role_proto.name} is already used.")
|
248
313
|
|
249
314
|
@pytest.mark.usefixtures("raise_db_error_on_query")
|
250
315
|
def test_grid_dberror(self, dbsession):
|
@@ -253,34 +318,3 @@ class TestRole(AbstractViewsTests):
|
|
253
318
|
request = DummyRequest(dbsession=dbsession, params={"offset": 0, "limit": 10})
|
254
319
|
info = RoleViews(request).grid()
|
255
320
|
assert info.status_int == 500, "Expected 500 status when db error"
|
256
|
-
|
257
|
-
|
258
|
-
@skip_if_ci
|
259
|
-
@pytest.mark.selenium
|
260
|
-
@pytest.mark.usefixtures("selenium", "selenium_app", "roles_test_data")
|
261
|
-
class TestRoleSelenium:
|
262
|
-
|
263
|
-
_prefix = "/admin/roles"
|
264
|
-
|
265
|
-
def test_index(self, selenium, selenium_app, roles_test_data, dbsession):
|
266
|
-
from c2cgeoportal_commons.models.static import Role
|
267
|
-
|
268
|
-
selenium.get(selenium_app + self._prefix)
|
269
|
-
|
270
|
-
index_page = IndexPage(selenium)
|
271
|
-
index_page.select_language("en")
|
272
|
-
index_page.check_pagination_info("Showing 1 to 23 of 23 rows", 10)
|
273
|
-
index_page.select_page_size(10)
|
274
|
-
index_page.check_pagination_info("Showing 1 to 10 of 23 rows", 10)
|
275
|
-
|
276
|
-
# delete
|
277
|
-
role = roles_test_data["roles"][3]
|
278
|
-
deleted_id = role.id
|
279
|
-
index_page.click_delete(deleted_id)
|
280
|
-
index_page.check_pagination_info("Showing 1 to 10 of 22 rows", 10)
|
281
|
-
assert dbsession.query(Role).get(deleted_id) is None
|
282
|
-
|
283
|
-
# edit
|
284
|
-
role = roles_test_data["roles"][4]
|
285
|
-
index_page.find_item_action(role.id, "edit").click()
|
286
|
-
index_page.find_element(By.XPATH, "//canvas", timeout=5)
|
tests/test_themes.py
CHANGED
@@ -13,33 +13,38 @@ def theme_test_data(dbsession, transact):
|
|
13
13
|
del transact
|
14
14
|
|
15
15
|
from c2cgeoportal_commons.models.main import (
|
16
|
-
Theme,
|
17
|
-
Role,
|
18
16
|
Functionality,
|
19
|
-
LayergroupTreeitem,
|
20
17
|
Interface,
|
21
|
-
Metadata,
|
22
18
|
LayerGroup,
|
19
|
+
LayergroupTreeitem,
|
23
20
|
LayerWMS,
|
21
|
+
Metadata,
|
24
22
|
OGCServer,
|
23
|
+
Role,
|
24
|
+
Theme,
|
25
25
|
)
|
26
26
|
|
27
27
|
interfaces = [Interface(name) for name in ["desktop", "mobile", "edit", "routing"]]
|
28
|
+
dbsession.add_all(interfaces)
|
28
29
|
|
29
|
-
groups = [LayerGroup(name="layer_group_{}"
|
30
|
+
groups = [LayerGroup(name=f"layer_group_{i}") for i in range(0, 5)]
|
31
|
+
dbsession.add_all(groups)
|
30
32
|
|
31
33
|
layer = LayerWMS(name="layer_wms")
|
32
34
|
layer.ogc_server = OGCServer(name="server")
|
33
|
-
dbsession.add(layer)
|
34
35
|
layers = [layer]
|
36
|
+
dbsession.add_all(layers)
|
35
37
|
|
38
|
+
# Note that "default_theme" is not relevant for themes
|
36
39
|
functionalities = [
|
37
|
-
Functionality(name=name, value="value_{}"
|
38
|
-
for name in ("default_basemap", "
|
40
|
+
Functionality(name=name, value=f"value_{v}")
|
41
|
+
for name in ("default_basemap", "default_theme")
|
39
42
|
for v in range(0, 4)
|
40
43
|
]
|
44
|
+
dbsession.add_all(functionalities)
|
41
45
|
|
42
46
|
roles = [Role("secretary_" + str(i)) for i in range(0, 4)]
|
47
|
+
dbsession.add_all(roles)
|
43
48
|
|
44
49
|
metadatas_protos = [
|
45
50
|
("copyable", "true"),
|
@@ -48,7 +53,7 @@ def theme_test_data(dbsession, transact):
|
|
48
53
|
]
|
49
54
|
themes = []
|
50
55
|
for i in range(0, 25):
|
51
|
-
theme = Theme(name="theme_{}"
|
56
|
+
theme = Theme(name=f"theme_{i}", ordering=1, icon=f"icon_{i}")
|
52
57
|
theme.public = 1 == i % 2
|
53
58
|
theme.interfaces = [interfaces[i % 4], interfaces[(i + 2) % 4]]
|
54
59
|
theme.metadatas = [
|
@@ -57,7 +62,7 @@ def theme_test_data(dbsession, transact):
|
|
57
62
|
]
|
58
63
|
for metadata in theme.metadatas:
|
59
64
|
metadata.item = theme
|
60
|
-
theme.functionalities = [functionalities[i %
|
65
|
+
theme.functionalities = [functionalities[i % 4]]
|
61
66
|
theme.restricted_roles = [roles[i % 4], roles[(i + 2) % 4]]
|
62
67
|
|
63
68
|
dbsession.add(
|
@@ -117,7 +122,7 @@ class TestTheme(TestTreeGroup):
|
|
117
122
|
|
118
123
|
assert first_theme.id == int(first_row["_id_"])
|
119
124
|
assert first_theme.name == first_row["name"]
|
120
|
-
assert "default_basemap=value_0
|
125
|
+
assert "default_basemap=value_0" == first_row["functionalities"]
|
121
126
|
assert "secretary_0, secretary_2" == first_row["restricted_roles"]
|
122
127
|
assert "desktop, edit" == first_row["interfaces"]
|
123
128
|
assert 'copyable: true, snappingConfig: {"tolerance": 50}' == first_row["metadatas"]
|
@@ -146,16 +151,16 @@ class TestTheme(TestTreeGroup):
|
|
146
151
|
|
147
152
|
def test_public_checkbox_edit(self, test_app, theme_test_data):
|
148
153
|
theme = theme_test_data["themes"][10]
|
149
|
-
form10 = test_app.get("/admin/themes/{
|
154
|
+
form10 = test_app.get(f"/admin/themes/{theme.id}", status=200).form
|
150
155
|
assert not form10["public"].checked
|
151
156
|
theme = theme_test_data["themes"][11]
|
152
|
-
form11 = test_app.get("/admin/themes/{
|
157
|
+
form11 = test_app.get(f"/admin/themes/{theme.id}", status=200).form
|
153
158
|
assert form11["public"].checked
|
154
159
|
|
155
160
|
def test_edit(self, test_app, theme_test_data, dbsession):
|
156
161
|
theme = theme_test_data["themes"][0]
|
157
162
|
|
158
|
-
resp = test_app.get("/admin/themes/{
|
163
|
+
resp = test_app.get(f"/admin/themes/{theme.id}", status=200)
|
159
164
|
form = resp.form
|
160
165
|
|
161
166
|
assert str(theme.id) == self.get_first_field_named(form, "id").value
|
@@ -166,21 +171,24 @@ class TestTheme(TestTreeGroup):
|
|
166
171
|
assert theme.public == form["public"].checked
|
167
172
|
|
168
173
|
interfaces = theme_test_data["interfaces"]
|
169
|
-
assert
|
174
|
+
assert {interfaces[0].id, interfaces[2].id} == {i.id for i in theme.interfaces}
|
170
175
|
self._check_interfaces(form, interfaces, theme)
|
171
176
|
|
172
177
|
functionalities = theme_test_data["functionalities"]
|
173
|
-
assert
|
178
|
+
assert {functionalities[0].id} == {f.id for f in theme.functionalities}
|
174
179
|
self.check_checkboxes(
|
175
180
|
form,
|
176
181
|
"functionalities",
|
177
182
|
[
|
178
183
|
{
|
179
|
-
"label": "{}={
|
184
|
+
"label": f"{f.name}={f.value}",
|
180
185
|
"value": str(f.id),
|
181
186
|
"checked": f in theme.functionalities,
|
182
187
|
}
|
183
|
-
for f in sorted(
|
188
|
+
for f in sorted(
|
189
|
+
[f for f in functionalities if f.name in ("default_basemap")],
|
190
|
+
key=lambda f: (f.name, f.value),
|
191
|
+
)
|
184
192
|
],
|
185
193
|
)
|
186
194
|
|
@@ -220,12 +228,8 @@ class TestTheme(TestTreeGroup):
|
|
220
228
|
assert value == getattr(theme, key)
|
221
229
|
else:
|
222
230
|
assert str(value or "") == str(getattr(theme, key) or "")
|
223
|
-
assert
|
224
|
-
|
225
|
-
)
|
226
|
-
assert set([functionalities[2].id]) == set(
|
227
|
-
[functionality.id for functionality in theme.functionalities]
|
228
|
-
)
|
231
|
+
assert {interfaces[1].id, interfaces[3].id} == {interface.id for interface in theme.interfaces}
|
232
|
+
assert {functionalities[2].id} == {functionality.id for functionality in theme.functionalities}
|
229
233
|
assert 0 == len(theme.restricted_roles)
|
230
234
|
|
231
235
|
def test_post_new_with_children_invalid(self, test_app, theme_test_data):
|
@@ -234,7 +238,7 @@ class TestTheme(TestTreeGroup):
|
|
234
238
|
"""
|
235
239
|
groups = theme_test_data["groups"]
|
236
240
|
resp = test_app.post(
|
237
|
-
"{}/new"
|
241
|
+
f"{self._prefix}/new",
|
238
242
|
(
|
239
243
|
("_charset_", "UTF-8"),
|
240
244
|
("__formid__", "deform"),
|
@@ -256,7 +260,7 @@ class TestTheme(TestTreeGroup):
|
|
256
260
|
def test_post_new_with_children_success(self, test_app, dbsession, theme_test_data):
|
257
261
|
groups = theme_test_data["groups"]
|
258
262
|
resp = test_app.post(
|
259
|
-
"{}/new"
|
263
|
+
f"{self._prefix}/new",
|
260
264
|
(
|
261
265
|
("_charset_", "UTF-8"),
|
262
266
|
("__formid__", "deform"),
|
@@ -304,7 +308,7 @@ class TestTheme(TestTreeGroup):
|
|
304
308
|
"""
|
305
309
|
layers = theme_test_data["layers"]
|
306
310
|
resp = test_app.post(
|
307
|
-
"{}/new"
|
311
|
+
f"{self._prefix}/new",
|
308
312
|
(
|
309
313
|
("_charset_", "UTF-8"),
|
310
314
|
("__formid__", "deform"),
|
@@ -324,7 +328,7 @@ class TestTheme(TestTreeGroup):
|
|
324
328
|
status=200,
|
325
329
|
)
|
326
330
|
assert (
|
327
|
-
"Value {} does not exist in table treeitem or is not allowed to avoid cycles"
|
331
|
+
f"Value {layers[0].id} does not exist in table treeitem or is not allowed to avoid cycles"
|
328
332
|
== resp.html.select_one(".item-children_relation + .help-block").getText().strip()
|
329
333
|
)
|
330
334
|
|
@@ -333,7 +337,7 @@ class TestTheme(TestTreeGroup):
|
|
333
337
|
|
334
338
|
theme = theme_test_data["themes"][1]
|
335
339
|
|
336
|
-
resp = test_app.get("{}/{}/duplicate"
|
340
|
+
resp = test_app.get(f"{self._prefix}/{theme.id}/duplicate", status=200)
|
337
341
|
form = resp.form
|
338
342
|
|
339
343
|
assert "" == self.get_first_field_named(form, "id").value
|
@@ -345,22 +349,25 @@ class TestTheme(TestTreeGroup):
|
|
345
349
|
assert theme.public == form["public"].checked
|
346
350
|
|
347
351
|
interfaces = theme_test_data["interfaces"]
|
348
|
-
assert
|
352
|
+
assert {interfaces[1].id, interfaces[3].id} == {i.id for i in theme.interfaces}
|
349
353
|
|
350
354
|
self._check_interfaces(form, interfaces, theme)
|
351
355
|
|
352
356
|
functionalities = theme_test_data["functionalities"]
|
353
|
-
assert
|
357
|
+
assert {functionalities[1].id} == {f.id for f in theme.functionalities}
|
354
358
|
self.check_checkboxes(
|
355
359
|
form,
|
356
360
|
"functionalities",
|
357
361
|
[
|
358
362
|
{
|
359
|
-
"label": "{}={
|
363
|
+
"label": f"{f.name}={f.value}",
|
360
364
|
"value": str(f.id),
|
361
365
|
"checked": f in theme.functionalities,
|
362
366
|
}
|
363
|
-
for f in sorted(
|
367
|
+
for f in sorted(
|
368
|
+
[f for f in functionalities if f.name in ("default_basemap")],
|
369
|
+
key=lambda f: (f.name, f.value),
|
370
|
+
)
|
364
371
|
],
|
365
372
|
)
|
366
373
|
|
@@ -381,7 +388,7 @@ class TestTheme(TestTreeGroup):
|
|
381
388
|
duplicated = dbsession.query(Theme).filter(Theme.name == "duplicated").one()
|
382
389
|
|
383
390
|
assert str(duplicated.id) == re.match(
|
384
|
-
|
391
|
+
rf"http://localhost{self._prefix}/(.*)\?msg_col=submit_ok", resp.location
|
385
392
|
).group(1)
|
386
393
|
assert duplicated.id != theme.id
|
387
394
|
assert duplicated.children_relation[0].id != theme.children_relation[0].id
|
@@ -391,13 +398,13 @@ class TestTheme(TestTreeGroup):
|
|
391
398
|
from c2cgeoportal_commons.models.main import Theme
|
392
399
|
|
393
400
|
theme_id = dbsession.query(Theme.id).first().id
|
394
|
-
test_app.delete("/admin/themes/{}"
|
401
|
+
test_app.delete(f"/admin/themes/{theme_id}", status=200)
|
395
402
|
assert dbsession.query(Theme).get(theme_id) is None
|
396
403
|
|
397
404
|
def test_unicity_validator(self, theme_test_data, test_app):
|
398
405
|
theme = theme_test_data["themes"][1]
|
399
|
-
resp = test_app.get("{}/{}/duplicate"
|
406
|
+
resp = test_app.get(f"{self._prefix}/{theme.id}/duplicate", status=200)
|
400
407
|
|
401
408
|
resp = resp.form.submit("submit")
|
402
409
|
|
403
|
-
self._check_submission_problem(resp, "{} is already used."
|
410
|
+
self._check_submission_problem(resp, f"{theme.name} is already used.")
|
tests/test_themes_ordering.py
CHANGED
@@ -14,7 +14,7 @@ def theme_test_data(dbsession, transact):
|
|
14
14
|
|
15
15
|
themes = []
|
16
16
|
for i in range(0, 3):
|
17
|
-
theme = Theme(name="theme_{}"
|
17
|
+
theme = Theme(name=f"theme_{i}", ordering=i, icon=f"icon_{i}")
|
18
18
|
|
19
19
|
dbsession.add(theme)
|
20
20
|
themes.append(theme)
|
tests/test_treegroup.py
CHANGED
@@ -5,10 +5,10 @@ from . import AbstractViewsTests
|
|
5
5
|
|
6
6
|
class TestTreeGroup(AbstractViewsTests):
|
7
7
|
def check_children(self, form, group, expected):
|
8
|
-
form_group = form.html.select_one(".item-{}"
|
8
|
+
form_group = form.html.select_one(f".item-{group}")
|
9
9
|
items = form_group.select(".deform-seq-item")
|
10
10
|
assert len(expected) == len(items)
|
11
11
|
for item, exp in zip(items, expected):
|
12
12
|
assert exp["label"] == item.select_one(".well").getText().strip()
|
13
13
|
for key, value in exp["values"].items():
|
14
|
-
assert value == item.select_one('input[name="{}"]'
|
14
|
+
assert value == item.select_one(f'input[name="{key}"]')["value"]
|