c2cgeoportal-admin 2.6.0__py3-none-any.whl → 2.9rc45__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 +42 -12
- c2cgeoportal_admin/lib/lingva_extractor.py +77 -0
- c2cgeoportal_admin/lib/ogcserver_synchronizer.py +170 -57
- c2cgeoportal_admin/py.typed +0 -0
- c2cgeoportal_admin/routes.py +18 -6
- c2cgeoportal_admin/schemas/dimensions.py +16 -10
- c2cgeoportal_admin/schemas/functionalities.py +59 -21
- c2cgeoportal_admin/schemas/interfaces.py +26 -18
- c2cgeoportal_admin/schemas/metadata.py +101 -48
- c2cgeoportal_admin/schemas/restriction_areas.py +25 -19
- c2cgeoportal_admin/schemas/roles.py +12 -6
- c2cgeoportal_admin/schemas/treegroup.py +46 -21
- c2cgeoportal_admin/schemas/treeitem.py +3 -4
- c2cgeoportal_admin/static/layertree.css +3 -4
- c2cgeoportal_admin/static/navbar.css +36 -35
- c2cgeoportal_admin/static/theme.css +19 -9
- c2cgeoportal_admin/subscribers.py +3 -3
- c2cgeoportal_admin/templates/404.jinja2 +18 -2
- c2cgeoportal_admin/templates/layertree.jinja2 +31 -9
- c2cgeoportal_admin/templates/navigation_navbar.jinja2 +33 -0
- c2cgeoportal_admin/templates/ogcserver_synchronize.jinja2 +12 -0
- c2cgeoportal_admin/templates/widgets/functionality_fields.pt +51 -0
- c2cgeoportal_admin/templates/widgets/metadata.pt +7 -1
- c2cgeoportal_admin/views/__init__.py +29 -0
- c2cgeoportal_admin/views/dimension_layers.py +14 -9
- c2cgeoportal_admin/views/functionalities.py +52 -18
- c2cgeoportal_admin/views/home.py +5 -5
- c2cgeoportal_admin/views/interfaces.py +26 -20
- c2cgeoportal_admin/views/layer_groups.py +36 -25
- c2cgeoportal_admin/views/layers.py +17 -13
- c2cgeoportal_admin/views/layers_cog.py +135 -0
- c2cgeoportal_admin/views/layers_vectortiles.py +62 -27
- c2cgeoportal_admin/views/layers_wms.py +55 -34
- c2cgeoportal_admin/views/layers_wmts.py +54 -34
- c2cgeoportal_admin/views/layertree.py +38 -29
- c2cgeoportal_admin/views/logged_views.py +83 -0
- c2cgeoportal_admin/views/logs.py +91 -0
- c2cgeoportal_admin/views/oauth2_clients.py +30 -18
- c2cgeoportal_admin/views/ogc_servers.py +132 -36
- c2cgeoportal_admin/views/restriction_areas.py +39 -27
- c2cgeoportal_admin/views/roles.py +42 -28
- c2cgeoportal_admin/views/themes.py +47 -35
- c2cgeoportal_admin/views/themes_ordering.py +19 -14
- c2cgeoportal_admin/views/treeitems.py +21 -17
- c2cgeoportal_admin/views/users.py +46 -26
- c2cgeoportal_admin/widgets.py +17 -14
- {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.9rc45.dist-info}/METADATA +12 -12
- c2cgeoportal_admin-2.9rc45.dist-info/RECORD +97 -0
- {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.9rc45.dist-info}/WHEEL +1 -1
- c2cgeoportal_admin-2.9rc45.dist-info/entry_points.txt +5 -0
- tests/__init__.py +24 -20
- tests/conftest.py +22 -11
- tests/test_edit_url.py +11 -14
- tests/test_functionalities.py +52 -14
- tests/test_home.py +0 -1
- tests/test_interface.py +34 -11
- tests/test_layer_groups.py +57 -27
- tests/test_layers_cog.py +243 -0
- tests/test_layers_vectortiles.py +43 -25
- tests/test_layers_wms.py +67 -45
- tests/test_layers_wmts.py +47 -26
- tests/test_layertree.py +99 -16
- tests/test_left_menu.py +0 -1
- tests/test_lingva_extractor_config.py +64 -0
- tests/test_logs.py +102 -0
- tests/test_main.py +3 -1
- tests/test_metadatas.py +34 -21
- tests/test_oauth2_clients.py +40 -11
- tests/test_ogc_servers.py +84 -35
- tests/test_restriction_areas.py +38 -15
- tests/test_role.py +71 -43
- tests/test_themes.py +71 -37
- tests/test_themes_ordering.py +1 -2
- tests/test_treegroup.py +2 -2
- tests/test_user.py +56 -19
- tests/themes_ordering.py +1 -2
- c2cgeoportal_admin/templates/navigation_vertical.jinja2 +0 -33
- c2cgeoportal_admin-2.6.0.dist-info/RECORD +0 -89
- c2cgeoportal_admin-2.6.0.dist-info/entry_points.txt +0 -3
- {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.9rc45.dist-info}/top_level.txt +0 -0
tests/test_interface.py
CHANGED
@@ -16,14 +16,14 @@ def interface_test_data(dbsession, transact):
|
|
16
16
|
|
17
17
|
themes = []
|
18
18
|
for i in range(0, 5):
|
19
|
-
theme = Theme(name="theme_{}"
|
19
|
+
theme = Theme(name=f"theme_{i}", ordering=1)
|
20
20
|
themes.append(theme)
|
21
21
|
|
22
|
-
servers = [OGCServer(name="server_{}"
|
22
|
+
servers = [OGCServer(name=f"server_{i}") for i in range(0, 4)]
|
23
23
|
|
24
24
|
layers = []
|
25
25
|
for i in range(0, 15):
|
26
|
-
layer = LayerWMS(name="layer_wms_{}"
|
26
|
+
layer = LayerWMS(name=f"layer_wms_{i}")
|
27
27
|
layer.public = 1 == i % 2
|
28
28
|
layer.ogc_server = servers[i % 4]
|
29
29
|
dbsession.add(layer)
|
@@ -31,7 +31,7 @@ def interface_test_data(dbsession, transact):
|
|
31
31
|
|
32
32
|
interfaces = []
|
33
33
|
for i in range(0, 5):
|
34
|
-
interface = Interface(name="interface_{}"
|
34
|
+
interface = Interface(name=f"interface_{i}", description=f"description_{i}")
|
35
35
|
interface.themes = [themes[i % 2], themes[(i + 5) % 5]]
|
36
36
|
interface.layers = [layers[i % 2], layers[(i + 4) % 5]]
|
37
37
|
|
@@ -45,7 +45,6 @@ def interface_test_data(dbsession, transact):
|
|
45
45
|
|
46
46
|
@pytest.mark.usefixtures("interface_test_data", "test_app")
|
47
47
|
class TestInterface(AbstractViewsTests):
|
48
|
-
|
49
48
|
_prefix = "/admin/interfaces"
|
50
49
|
|
51
50
|
def test_index_rendering(self, test_app):
|
@@ -82,7 +81,7 @@ class TestInterface(AbstractViewsTests):
|
|
82
81
|
self.check_search(test_app, "interface_0", total=1)
|
83
82
|
|
84
83
|
def test_submit_new(self, dbsession, test_app):
|
85
|
-
from c2cgeoportal_commons.models.main import Interface
|
84
|
+
from c2cgeoportal_commons.models.main import Interface, Log, LogAction
|
86
85
|
|
87
86
|
resp = test_app.post(
|
88
87
|
"/admin/interfaces/new", {"name": "new_name", "description": "new description"}, status=302
|
@@ -94,14 +93,22 @@ class TestInterface(AbstractViewsTests):
|
|
94
93
|
).group(1)
|
95
94
|
assert interface.name == "new_name"
|
96
95
|
|
96
|
+
log = dbsession.query(Log).one()
|
97
|
+
assert log.date != None
|
98
|
+
assert log.action == LogAction.INSERT
|
99
|
+
assert log.element_type == "interface"
|
100
|
+
assert log.element_id == interface.id
|
101
|
+
assert log.element_name == interface.name
|
102
|
+
assert log.username == "test_user"
|
103
|
+
|
97
104
|
def test_edit(self, test_app, interface_test_data, dbsession):
|
98
|
-
from c2cgeoportal_commons.models.main import Interface
|
105
|
+
from c2cgeoportal_commons.models.main import Interface, Log, LogAction
|
99
106
|
|
100
107
|
interface = interface_test_data["interfaces"][0]
|
101
108
|
descriptions = "{}, {}".format(
|
102
109
|
interface_test_data["interfaces"][0].description, interface_test_data["interfaces"][1].description
|
103
110
|
)
|
104
|
-
resp = test_app.get("/admin/interfaces/{
|
111
|
+
resp = test_app.get(f"/admin/interfaces/{interface.id}", status=200)
|
105
112
|
form = resp.form
|
106
113
|
form["description"] = descriptions
|
107
114
|
assert str(interface.id) == self.get_first_field_named(form, "id").value
|
@@ -110,16 +117,32 @@ class TestInterface(AbstractViewsTests):
|
|
110
117
|
assert form.submit().status_int == 302
|
111
118
|
assert len(dbsession.query(Interface).filter(Interface.description == descriptions).all()) == 1
|
112
119
|
|
120
|
+
log = dbsession.query(Log).one()
|
121
|
+
assert log.date != None
|
122
|
+
assert log.action == LogAction.UPDATE
|
123
|
+
assert log.element_type == "interface"
|
124
|
+
assert log.element_id == interface.id
|
125
|
+
assert log.element_name == interface.name
|
126
|
+
assert log.username == "test_user"
|
127
|
+
|
113
128
|
def test_delete(self, test_app, interface_test_data, dbsession):
|
114
|
-
from c2cgeoportal_commons.models.main import Interface
|
129
|
+
from c2cgeoportal_commons.models.main import Interface, Log, LogAction
|
115
130
|
|
116
131
|
interface = interface_test_data["interfaces"][0]
|
117
|
-
test_app.delete("/admin/interfaces/{
|
132
|
+
test_app.delete(f"/admin/interfaces/{interface.id}", status=200)
|
118
133
|
assert len(dbsession.query(Interface).filter(Interface.id == interface.id).all()) == 0
|
119
134
|
|
135
|
+
log = dbsession.query(Log).one()
|
136
|
+
assert log.date != None
|
137
|
+
assert log.action == LogAction.DELETE
|
138
|
+
assert log.element_type == "interface"
|
139
|
+
assert log.element_id == interface.id
|
140
|
+
assert log.element_name == interface.name
|
141
|
+
assert log.username == "test_user"
|
142
|
+
|
120
143
|
def test_duplicate(self, interface_test_data, test_app):
|
121
144
|
interface = interface_test_data["interfaces"][3]
|
122
|
-
resp = test_app.get("/admin/interfaces/{}/duplicate"
|
145
|
+
resp = test_app.get(f"/admin/interfaces/{interface.id}/duplicate", status=200)
|
123
146
|
form = resp.form
|
124
147
|
assert "" == self.get_first_field_named(form, "id").value
|
125
148
|
assert str(interface.description or "") == "description_3"
|
tests/test_layer_groups.py
CHANGED
@@ -22,7 +22,7 @@ def layer_groups_test_data(dbsession, transact):
|
|
22
22
|
|
23
23
|
groups = []
|
24
24
|
for i in range(0, 12):
|
25
|
-
group = LayerGroup(name="groups_{
|
25
|
+
group = LayerGroup(name=f"groups_{i:02d}")
|
26
26
|
group.metadatas = [
|
27
27
|
Metadata(name=metadatas_protos[id][0], value=metadatas_protos[id][1])
|
28
28
|
for id in [i % 3, (i + 2) % 3]
|
@@ -60,7 +60,6 @@ def layer_groups_test_data(dbsession, transact):
|
|
60
60
|
|
61
61
|
@pytest.mark.usefixtures("layer_groups_test_data", "test_app")
|
62
62
|
class TestLayersGroups(TestTreeGroup):
|
63
|
-
|
64
63
|
_prefix = "/admin/layer_groups"
|
65
64
|
|
66
65
|
def test_index_rendering(self, test_app):
|
@@ -73,7 +72,6 @@ class TestLayersGroups(TestTreeGroup):
|
|
73
72
|
("id", "id", "true"),
|
74
73
|
("name", "Name"),
|
75
74
|
("description", "Description"),
|
76
|
-
("is_expanded", "Expanded"),
|
77
75
|
("parents_relation", "Parents", "false"),
|
78
76
|
("metadatas", "Metadatas", "false"),
|
79
77
|
]
|
@@ -95,6 +93,8 @@ class TestLayersGroups(TestTreeGroup):
|
|
95
93
|
self.check_search(test_app, "copyable", total=8)
|
96
94
|
|
97
95
|
def test_edit(self, test_app, layer_groups_test_data, dbsession):
|
96
|
+
from c2cgeoportal_commons.models.main import Log, LogAction
|
97
|
+
|
98
98
|
group = layer_groups_test_data["groups"][1]
|
99
99
|
|
100
100
|
form = self.get_item(test_app, group.id).form
|
@@ -103,8 +103,6 @@ class TestLayersGroups(TestTreeGroup):
|
|
103
103
|
assert "hidden" == self.get_first_field_named(form, "id").attrs["type"]
|
104
104
|
assert group.name == self.get_first_field_named(form, "name").value
|
105
105
|
assert str(group.description or "") == self.get_first_field_named(form, "description").value
|
106
|
-
assert group.is_expanded is False
|
107
|
-
assert group.is_expanded == form["is_expanded"].checked
|
108
106
|
|
109
107
|
self.check_children(
|
110
108
|
form,
|
@@ -121,7 +119,6 @@ class TestLayersGroups(TestTreeGroup):
|
|
121
119
|
new_values = {
|
122
120
|
"name": "new_name",
|
123
121
|
"description": "new description",
|
124
|
-
"is_expanded": True,
|
125
122
|
}
|
126
123
|
for key, value in new_values.items():
|
127
124
|
self.set_first_field_named(form, key, value)
|
@@ -138,13 +135,21 @@ class TestLayersGroups(TestTreeGroup):
|
|
138
135
|
else:
|
139
136
|
assert str(value or "") == str(getattr(group, key) or "")
|
140
137
|
|
138
|
+
log = dbsession.query(Log).one()
|
139
|
+
assert log.date != None
|
140
|
+
assert log.action == LogAction.UPDATE
|
141
|
+
assert log.element_type == "layergroup"
|
142
|
+
assert log.element_id == group.id
|
143
|
+
assert log.element_name == group.name
|
144
|
+
assert log.username == "test_user"
|
145
|
+
|
141
146
|
def test_post_new_with_children_invalid(self, test_app, layer_groups_test_data):
|
142
147
|
"""
|
143
148
|
Check there is no rendering error when validation fails.
|
144
149
|
"""
|
145
150
|
groups = layer_groups_test_data["groups"]
|
146
151
|
resp = test_app.post(
|
147
|
-
"{}/new"
|
152
|
+
f"{self._prefix}/new",
|
148
153
|
(
|
149
154
|
("_charset_", "UTF-8"),
|
150
155
|
("__formid__", "deform"),
|
@@ -163,9 +168,11 @@ class TestLayersGroups(TestTreeGroup):
|
|
163
168
|
assert "Required" == resp.html.select_one(".item-name .help-block").getText().strip()
|
164
169
|
|
165
170
|
def test_post_new_with_children_success(self, test_app, dbsession, layer_groups_test_data):
|
171
|
+
from c2cgeoportal_commons.models.main import Log, LogAction
|
172
|
+
|
166
173
|
groups = layer_groups_test_data["groups"]
|
167
174
|
resp = test_app.post(
|
168
|
-
"{}/new"
|
175
|
+
f"{self._prefix}/new",
|
169
176
|
(
|
170
177
|
("_charset_", "UTF-8"),
|
171
178
|
("__formid__", "deform"),
|
@@ -206,11 +213,21 @@ class TestLayersGroups(TestTreeGroup):
|
|
206
213
|
rel.treeitem_id for rel in group.children_relation
|
207
214
|
]
|
208
215
|
|
216
|
+
log = dbsession.query(Log).one()
|
217
|
+
assert log.date != None
|
218
|
+
assert log.action == LogAction.INSERT
|
219
|
+
assert log.element_type == "layergroup"
|
220
|
+
assert log.element_id == group.id
|
221
|
+
assert log.element_name == group.name
|
222
|
+
assert log.username == "test_user"
|
223
|
+
|
209
224
|
def test_post_with_ancestor(self, layer_groups_test_data, test_app):
|
210
|
-
"""
|
225
|
+
"""
|
226
|
+
Check that ancestors are refused to avoid cycles.
|
227
|
+
"""
|
211
228
|
groups = layer_groups_test_data["groups"]
|
212
229
|
resp = test_app.post(
|
213
|
-
"{}/{
|
230
|
+
f"{self._prefix}/{groups[3].id}",
|
214
231
|
(
|
215
232
|
("_charset_", "UTF-8"),
|
216
233
|
("__formid__", "deform"),
|
@@ -228,7 +245,7 @@ class TestLayersGroups(TestTreeGroup):
|
|
228
245
|
status=200,
|
229
246
|
)
|
230
247
|
assert (
|
231
|
-
"Value {} does not exist in table treeitem or is not allowed to avoid cycles"
|
248
|
+
f"Value {groups[1].id} does not exist in table treeitem or is not allowed to avoid cycles"
|
232
249
|
== resp.html.select_one(".item-children_relation + .help-block").getText().strip()
|
233
250
|
)
|
234
251
|
|
@@ -237,7 +254,7 @@ class TestLayersGroups(TestTreeGroup):
|
|
237
254
|
|
238
255
|
group = layer_groups_test_data["groups"][1]
|
239
256
|
|
240
|
-
resp = test_app.get("{}/{}/duplicate"
|
257
|
+
resp = test_app.get(f"{self._prefix}/{group.id}/duplicate", status=200)
|
241
258
|
form = resp.form
|
242
259
|
|
243
260
|
group = dbsession.query(LayerGroup).filter(LayerGroup.id == group.id).one()
|
@@ -245,8 +262,6 @@ class TestLayersGroups(TestTreeGroup):
|
|
245
262
|
assert "" == self.get_first_field_named(form, "id").value
|
246
263
|
assert group.name == self.get_first_field_named(form, "name").value
|
247
264
|
assert str(group.description or "") == self.get_first_field_named(form, "description").value
|
248
|
-
assert group.is_expanded is False
|
249
|
-
assert group.is_expanded == form["is_expanded"].checked
|
250
265
|
|
251
266
|
self.check_children(
|
252
267
|
form,
|
@@ -263,7 +278,7 @@ class TestLayersGroups(TestTreeGroup):
|
|
263
278
|
duplicated = dbsession.query(LayerGroup).filter(LayerGroup.name == "duplicated").one()
|
264
279
|
|
265
280
|
assert str(duplicated.id) == re.match(
|
266
|
-
|
281
|
+
rf"http://localhost{self._prefix}/(.*)\?msg_col=submit_ok", resp.location
|
267
282
|
).group(1)
|
268
283
|
assert duplicated.id != group.id
|
269
284
|
assert duplicated.children_relation[0].id != group.children_relation[0].id
|
@@ -271,41 +286,56 @@ class TestLayersGroups(TestTreeGroup):
|
|
271
286
|
|
272
287
|
def test_unicity_validator(self, layer_groups_test_data, test_app):
|
273
288
|
group = layer_groups_test_data["groups"][1]
|
274
|
-
resp = test_app.get("{}/{}/duplicate"
|
289
|
+
resp = test_app.get(f"{self._prefix}/{group.id}/duplicate", status=200)
|
275
290
|
|
276
291
|
resp = resp.form.submit("submit")
|
277
292
|
|
278
|
-
self._check_submission_problem(resp, "{} is already used."
|
293
|
+
self._check_submission_problem(resp, f"{group.name} is already used.")
|
279
294
|
|
280
295
|
def test_delete(self, test_app, dbsession, layer_groups_test_data):
|
281
|
-
from c2cgeoportal_commons.models.main import
|
296
|
+
from c2cgeoportal_commons.models.main import (
|
297
|
+
LayerGroup,
|
298
|
+
LayergroupTreeitem,
|
299
|
+
Log,
|
300
|
+
LogAction,
|
301
|
+
TreeGroup,
|
302
|
+
TreeItem,
|
303
|
+
)
|
282
304
|
|
283
|
-
|
305
|
+
group = layer_groups_test_data["groups"][9]
|
284
306
|
|
285
307
|
assert (
|
286
308
|
3
|
287
|
-
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treegroup_id ==
|
309
|
+
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treegroup_id == group.id).count()
|
288
310
|
)
|
289
311
|
|
290
312
|
assert (
|
291
313
|
1
|
292
|
-
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treeitem_id ==
|
314
|
+
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treeitem_id == group.id).count()
|
293
315
|
)
|
294
316
|
|
295
|
-
test_app.delete("/admin/layer_groups/{}"
|
317
|
+
test_app.delete(f"/admin/layer_groups/{group.id}", status=200)
|
296
318
|
|
297
319
|
dbsession.expire_all()
|
298
320
|
|
299
|
-
assert dbsession.query(LayerGroup).get(
|
300
|
-
assert dbsession.query(TreeGroup).get(
|
301
|
-
assert dbsession.query(TreeItem).get(
|
321
|
+
assert dbsession.query(LayerGroup).get(group.id) is None
|
322
|
+
assert dbsession.query(TreeGroup).get(group.id) is None
|
323
|
+
assert dbsession.query(TreeItem).get(group.id) is None
|
302
324
|
|
303
325
|
assert (
|
304
326
|
0
|
305
|
-
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treegroup_id ==
|
327
|
+
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treegroup_id == group.id).count()
|
306
328
|
)
|
307
329
|
|
308
330
|
assert (
|
309
331
|
0
|
310
|
-
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treeitem_id ==
|
332
|
+
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treeitem_id == group.id).count()
|
311
333
|
)
|
334
|
+
|
335
|
+
log = dbsession.query(Log).one()
|
336
|
+
assert log.date != None
|
337
|
+
assert log.action == LogAction.DELETE
|
338
|
+
assert log.element_type == "layergroup"
|
339
|
+
assert log.element_id == group.id
|
340
|
+
assert log.element_name == group.name
|
341
|
+
assert log.username == "test_user"
|
tests/test_layers_cog.py
ADDED
@@ -0,0 +1,243 @@
|
|
1
|
+
# pylint: disable=no-self-use
|
2
|
+
|
3
|
+
import re
|
4
|
+
from typing import Any
|
5
|
+
|
6
|
+
import pytest
|
7
|
+
from sqlalchemy.orm import Session, SessionTransaction
|
8
|
+
from webtest import TestApp as WebTestApp # Avoid warning with pytest
|
9
|
+
|
10
|
+
from . import AbstractViewsTests, factory_build_layers, get_test_default_layers
|
11
|
+
|
12
|
+
|
13
|
+
@pytest.fixture(scope="function")
|
14
|
+
@pytest.mark.usefixtures("dbsession", "transact")
|
15
|
+
def layer_cog_test_data(dbsession: Session, transact: SessionTransaction) -> dict[str, Any]:
|
16
|
+
del transact
|
17
|
+
|
18
|
+
from c2cgeoportal_commons.models.main import LayerCOG
|
19
|
+
|
20
|
+
def layer_builder(i: int) -> LayerCOG:
|
21
|
+
name = f"layer_cog_{i}"
|
22
|
+
layer = LayerCOG(name=name)
|
23
|
+
layer.public = 1 == i % 2
|
24
|
+
layer.url = "https://example.com/image.tiff"
|
25
|
+
return layer
|
26
|
+
|
27
|
+
data = factory_build_layers(layer_builder, dbsession, add_dimension=False)
|
28
|
+
data["default"] = get_test_default_layers(dbsession, None)
|
29
|
+
|
30
|
+
dbsession.flush()
|
31
|
+
|
32
|
+
yield data
|
33
|
+
|
34
|
+
|
35
|
+
@pytest.mark.usefixtures("layer_cog_test_data", "test_app")
|
36
|
+
class TestLayerVectortiles(AbstractViewsTests):
|
37
|
+
_prefix = "/admin/layers_cog"
|
38
|
+
|
39
|
+
def test_index_rendering(self, test_app: WebTestApp) -> None:
|
40
|
+
resp = self.get(test_app)
|
41
|
+
|
42
|
+
self.check_left_menu(resp, "COG Layers")
|
43
|
+
|
44
|
+
expected = [
|
45
|
+
("actions", "", "false"),
|
46
|
+
("id", "id", "true"),
|
47
|
+
("name", "Name"),
|
48
|
+
("description", "Description"),
|
49
|
+
("public", "Public"),
|
50
|
+
("geo_table", "Geo table"),
|
51
|
+
("exclude_properties", "Exclude properties"),
|
52
|
+
("url", "URL"),
|
53
|
+
("interfaces", "Interfaces"),
|
54
|
+
("restrictionareas", "Restriction areas", "false"),
|
55
|
+
("parents_relation", "Parents", "false"),
|
56
|
+
("metadatas", "Metadatas", "false"),
|
57
|
+
]
|
58
|
+
self.check_grid_headers(resp, expected)
|
59
|
+
|
60
|
+
def test_grid_complex_column_val(self, test_app: WebTestApp, layer_cog_test_data: dict[str, Any]) -> None:
|
61
|
+
json = self.check_search(test_app, search="layer", sort="name")
|
62
|
+
|
63
|
+
row = json["rows"][0]
|
64
|
+
layer = layer_cog_test_data["layers"][0]
|
65
|
+
|
66
|
+
assert layer.name == row["name"]
|
67
|
+
assert layer.id == int(row["_id_"])
|
68
|
+
|
69
|
+
def test_new(self, test_app: WebTestApp, layer_cog_test_data: dict[str, Any], dbsession: Session) -> None:
|
70
|
+
default_cog = layer_cog_test_data["default"]["cog"]
|
71
|
+
default_cog.name = "so can I not be found"
|
72
|
+
dbsession.flush()
|
73
|
+
|
74
|
+
form = self.get_item(test_app, "new").form
|
75
|
+
|
76
|
+
assert "" == self.get_first_field_named(form, "name").value
|
77
|
+
assert "" == self.get_first_field_named(form, "id").value
|
78
|
+
assert "" == self.get_first_field_named(form, "url").value
|
79
|
+
|
80
|
+
def test_grid_search(self, test_app: WebTestApp) -> None:
|
81
|
+
self.check_search(test_app, "layer_cog_10", total=1)
|
82
|
+
|
83
|
+
def test_base_edit(self, test_app: WebTestApp, layer_cog_test_data: dict[str, Any]) -> None:
|
84
|
+
layer = layer_cog_test_data["layers"][10]
|
85
|
+
|
86
|
+
form = self.get_item(test_app, layer.id).form
|
87
|
+
|
88
|
+
assert "layer_cog_10" == self.get_first_field_named(form, "name").value
|
89
|
+
assert "" == self.get_first_field_named(form, "description").value
|
90
|
+
|
91
|
+
def test_public_checkbox_edit(self, test_app: WebTestApp, layer_cog_test_data: dict[str, Any]) -> None:
|
92
|
+
layer = layer_cog_test_data["layers"][10]
|
93
|
+
form = self.get_item(test_app, layer.id).form
|
94
|
+
assert not form["public"].checked
|
95
|
+
|
96
|
+
layer = layer_cog_test_data["layers"][11]
|
97
|
+
form = self.get_item(test_app, layer.id).form
|
98
|
+
assert form["public"].checked
|
99
|
+
|
100
|
+
def test_edit(
|
101
|
+
self, test_app: WebTestApp, layer_cog_test_data: dict[str, Any], dbsession: Session
|
102
|
+
) -> None:
|
103
|
+
from c2cgeoportal_commons.models.main import Log, LogAction
|
104
|
+
|
105
|
+
layer = layer_cog_test_data["layers"][0]
|
106
|
+
|
107
|
+
form = self.get_item(test_app, layer.id).form
|
108
|
+
|
109
|
+
assert str(layer.id) == self.get_first_field_named(form, "id").value
|
110
|
+
assert "hidden" == self.get_first_field_named(form, "id").attrs["type"]
|
111
|
+
assert layer.name == self.get_first_field_named(form, "name").value
|
112
|
+
assert str(layer.description or "") == self.get_first_field_named(form, "description").value
|
113
|
+
assert layer.public is False
|
114
|
+
assert layer.public == form["public"].checked
|
115
|
+
assert str(layer.geo_table or "") == form["geo_table"].value
|
116
|
+
assert str(layer.exclude_properties or "") == form["exclude_properties"].value
|
117
|
+
# assert str(layer.url or "") == form["url"].value
|
118
|
+
|
119
|
+
interfaces = layer_cog_test_data["interfaces"]
|
120
|
+
assert {interfaces[0].id, interfaces[2].id} == {i.id for i in layer.interfaces}
|
121
|
+
self._check_interfaces(form, interfaces, layer)
|
122
|
+
|
123
|
+
ras = layer_cog_test_data["restrictionareas"]
|
124
|
+
assert {ras[0].id, ras[2].id} == {i.id for i in layer.restrictionareas}
|
125
|
+
self._check_restrictionsareas(form, ras, layer)
|
126
|
+
|
127
|
+
new_values = {
|
128
|
+
"name": "new_name",
|
129
|
+
"description": "new description",
|
130
|
+
"public": True,
|
131
|
+
"geo_table": "new_geo_table",
|
132
|
+
"exclude_properties": "property1,property2",
|
133
|
+
"url": "https://example.com/image.tiff",
|
134
|
+
}
|
135
|
+
|
136
|
+
for key, value in new_values.items():
|
137
|
+
self.set_first_field_named(form, key, value)
|
138
|
+
form["interfaces"] = [interfaces[1].id, interfaces[3].id]
|
139
|
+
form["restrictionareas"] = [ras[1].id, ras[3].id]
|
140
|
+
|
141
|
+
resp = form.submit("submit")
|
142
|
+
assert str(layer.id) == re.match(
|
143
|
+
rf"http://localhost{self._prefix}/(.*)\?msg_col=submit_ok", resp.location
|
144
|
+
).group(1)
|
145
|
+
|
146
|
+
dbsession.expire(layer)
|
147
|
+
for key, value in new_values.items():
|
148
|
+
if isinstance(value, bool):
|
149
|
+
assert value == getattr(layer, key)
|
150
|
+
else:
|
151
|
+
assert str(value or "") == str(getattr(layer, key) or "")
|
152
|
+
assert {interfaces[1].id, interfaces[3].id} == {interface.id for interface in layer.interfaces}
|
153
|
+
assert {ras[1].id, ras[3].id} == {ra.id for ra in layer.restrictionareas}
|
154
|
+
|
155
|
+
log = dbsession.query(Log).one()
|
156
|
+
assert log.date != None
|
157
|
+
assert log.action == LogAction.UPDATE
|
158
|
+
assert log.element_type == "layer_cog"
|
159
|
+
assert log.element_id == layer.id
|
160
|
+
assert log.element_name == layer.name
|
161
|
+
assert log.username == "test_user"
|
162
|
+
|
163
|
+
def test_submit_new(
|
164
|
+
self, dbsession: Session, test_app: WebTestApp, layer_cog_test_data: dict[str, Any]
|
165
|
+
) -> None:
|
166
|
+
from c2cgeoportal_commons.models.main import LayerCOG, Log, LogAction
|
167
|
+
|
168
|
+
resp = test_app.post(
|
169
|
+
"/admin/layers_cog/new",
|
170
|
+
{
|
171
|
+
"name": "new_name",
|
172
|
+
"description": "new description",
|
173
|
+
"public": True,
|
174
|
+
"url": "https://example.com/image.tiff",
|
175
|
+
},
|
176
|
+
status=302,
|
177
|
+
)
|
178
|
+
|
179
|
+
layer = dbsession.query(LayerCOG).filter(LayerCOG.name == "new_name").one()
|
180
|
+
assert str(layer.id) == re.match(
|
181
|
+
r"http://localhost/admin/layers_cog/(.*)\?msg_col=submit_ok", resp.location
|
182
|
+
).group(1)
|
183
|
+
|
184
|
+
log = dbsession.query(Log).one()
|
185
|
+
assert log.date != None
|
186
|
+
assert log.action == LogAction.INSERT
|
187
|
+
assert log.element_type == "layer_cog"
|
188
|
+
assert log.element_id == layer.id
|
189
|
+
assert log.element_name == layer.name
|
190
|
+
assert log.username == "test_user"
|
191
|
+
|
192
|
+
def test_duplicate(
|
193
|
+
self, layer_cog_test_data: dict[str, Any], test_app: WebTestApp, dbsession: Session
|
194
|
+
) -> None:
|
195
|
+
from c2cgeoportal_commons.models.main import LayerCOG
|
196
|
+
|
197
|
+
layer = layer_cog_test_data["layers"][3]
|
198
|
+
|
199
|
+
resp = test_app.get(f"/admin/layers_cog/{layer.id}/duplicate", status=200)
|
200
|
+
form = resp.form
|
201
|
+
|
202
|
+
assert "" == self.get_first_field_named(form, "id").value
|
203
|
+
assert layer.name == self.get_first_field_named(form, "name").value
|
204
|
+
assert str(layer.description or "") == self.get_first_field_named(form, "description").value
|
205
|
+
assert layer.public is True
|
206
|
+
assert layer.public == form["public"].checked
|
207
|
+
assert str(layer.geo_table or "") == form["geo_table"].value
|
208
|
+
assert str(layer.exclude_properties or "") == form["exclude_properties"].value
|
209
|
+
# assert str(layer.url or "") == form["url"].value
|
210
|
+
interfaces = layer_cog_test_data["interfaces"]
|
211
|
+
assert {interfaces[3].id, interfaces[1].id} == {i.id for i in layer.interfaces}
|
212
|
+
self._check_interfaces(form, interfaces, layer)
|
213
|
+
|
214
|
+
self.set_first_field_named(form, "name", "clone")
|
215
|
+
resp = form.submit("submit")
|
216
|
+
|
217
|
+
layer = dbsession.query(LayerCOG).filter(LayerCOG.name == "clone").one()
|
218
|
+
assert str(layer.id) == re.match(
|
219
|
+
r"http://localhost/admin/layers_cog/(.*)\?msg_col=submit_ok", resp.location
|
220
|
+
).group(1)
|
221
|
+
|
222
|
+
assert layer.id == layer.metadatas[0].item_id
|
223
|
+
assert layer_cog_test_data["layers"][3].metadatas[0].name == layer.metadatas[0].name
|
224
|
+
assert layer_cog_test_data["layers"][3].metadatas[1].name == layer.metadatas[1].name
|
225
|
+
|
226
|
+
def test_delete(self, test_app: WebTestApp, dbsession: Session) -> None:
|
227
|
+
from c2cgeoportal_commons.models.main import Layer, LayerCOG, Log, LogAction, TreeItem
|
228
|
+
|
229
|
+
layer = dbsession.query(LayerCOG).first()
|
230
|
+
|
231
|
+
test_app.delete(f"/admin/layers_cog/{layer.id}", status=200)
|
232
|
+
|
233
|
+
assert dbsession.query(LayerCOG).get(layer.id) is None
|
234
|
+
assert dbsession.query(Layer).get(layer.id) is None
|
235
|
+
assert dbsession.query(TreeItem).get(layer.id) is None
|
236
|
+
|
237
|
+
log = dbsession.query(Log).one()
|
238
|
+
assert log.date != None
|
239
|
+
assert log.action == LogAction.DELETE
|
240
|
+
assert log.element_type == "layer_cog"
|
241
|
+
assert log.element_id == layer.id
|
242
|
+
assert log.element_name == layer.name
|
243
|
+
assert log.username == "test_user"
|