c2cgeoportal-admin 2.5.0.100__py3-none-any.whl → 2.9rc44__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 +44 -14
- c2cgeoportal_admin/lib/__init__.py +0 -0
- c2cgeoportal_admin/lib/lingva_extractor.py +77 -0
- c2cgeoportal_admin/lib/ogcserver_synchronizer.py +410 -0
- c2cgeoportal_admin/py.typed +0 -0
- c2cgeoportal_admin/routes.py +30 -11
- c2cgeoportal_admin/schemas/dimensions.py +17 -11
- c2cgeoportal_admin/schemas/functionalities.py +60 -22
- c2cgeoportal_admin/schemas/interfaces.py +27 -19
- c2cgeoportal_admin/schemas/metadata.py +122 -48
- c2cgeoportal_admin/schemas/restriction_areas.py +26 -20
- c2cgeoportal_admin/schemas/roles.py +13 -7
- c2cgeoportal_admin/schemas/treegroup.py +90 -20
- c2cgeoportal_admin/schemas/treeitem.py +3 -4
- c2cgeoportal_admin/static/layertree.css +26 -4
- c2cgeoportal_admin/static/navbar.css +59 -36
- c2cgeoportal_admin/static/theme.css +51 -11
- c2cgeoportal_admin/subscribers.py +3 -3
- c2cgeoportal_admin/templates/404.jinja2 +41 -2
- 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/__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 +29 -21
- 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 +61 -36
- c2cgeoportal_admin/views/layers_wmts.py +54 -32
- c2cgeoportal_admin/views/layertree.py +37 -28
- c2cgeoportal_admin/views/logged_views.py +83 -0
- c2cgeoportal_admin/views/logs.py +91 -0
- c2cgeoportal_admin/views/oauth2_clients.py +96 -0
- c2cgeoportal_admin/views/ogc_servers.py +192 -21
- c2cgeoportal_admin/views/restriction_areas.py +78 -25
- c2cgeoportal_admin/views/roles.py +88 -25
- c2cgeoportal_admin/views/themes.py +47 -35
- c2cgeoportal_admin/views/themes_ordering.py +44 -24
- c2cgeoportal_admin/views/treeitems.py +21 -17
- c2cgeoportal_admin/views/users.py +46 -26
- c2cgeoportal_admin/widgets.py +79 -28
- {c2cgeoportal_admin-2.5.0.100.dist-info → c2cgeoportal_admin-2.9rc44.dist-info}/METADATA +15 -13
- c2cgeoportal_admin-2.9rc44.dist-info/RECORD +97 -0
- {c2cgeoportal_admin-2.5.0.100.dist-info → c2cgeoportal_admin-2.9rc44.dist-info}/WHEEL +1 -1
- c2cgeoportal_admin-2.9rc44.dist-info/entry_points.txt +5 -0
- tests/__init__.py +36 -27
- tests/conftest.py +23 -24
- tests/test_edit_url.py +16 -19
- tests/test_functionalities.py +52 -14
- tests/test_home.py +0 -1
- tests/test_interface.py +35 -12
- tests/test_layer_groups.py +58 -32
- tests/test_layers_cog.py +243 -0
- tests/test_layers_vectortiles.py +46 -30
- tests/test_layers_wms.py +77 -82
- tests/test_layers_wmts.py +51 -30
- tests/test_layertree.py +107 -101
- tests/test_learn.py +1 -1
- 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 +4 -2
- tests/test_metadatas.py +79 -71
- tests/test_oauth2_clients.py +186 -0
- tests/test_ogc_servers.py +110 -28
- tests/test_restriction_areas.py +109 -20
- tests/test_role.py +142 -82
- tests/test_themes.py +75 -41
- tests/test_themes_ordering.py +1 -2
- tests/test_treegroup.py +2 -2
- tests/test_user.py +72 -70
- tests/themes_ordering.py +1 -2
- 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.9rc44.dist-info}/top_level.txt +0 -0
tests/test_interface.py
CHANGED
@@ -12,18 +12,18 @@ from . import AbstractViewsTests
|
|
12
12
|
def interface_test_data(dbsession, transact):
|
13
13
|
del transact
|
14
14
|
|
15
|
-
from c2cgeoportal_commons.models.main import Interface,
|
15
|
+
from c2cgeoportal_commons.models.main import Interface, LayerWMS, OGCServer, Theme
|
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
@@ -12,7 +12,7 @@ from .test_treegroup import TestTreeGroup
|
|
12
12
|
def layer_groups_test_data(dbsession, transact):
|
13
13
|
del transact
|
14
14
|
|
15
|
-
from c2cgeoportal_commons.models.main import LayerGroup,
|
15
|
+
from c2cgeoportal_commons.models.main import LayerGroup, LayergroupTreeitem, Metadata
|
16
16
|
|
17
17
|
metadatas_protos = [
|
18
18
|
("copyable", "true"),
|
@@ -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
|
]
|
@@ -90,15 +88,13 @@ class TestLayersGroups(TestTreeGroup):
|
|
90
88
|
assert "groups_02, groups_06" == row["parents_relation"]
|
91
89
|
assert "disclaimer: © le momo, copyable: true" == row["metadatas"]
|
92
90
|
|
93
|
-
@pytest.mark.skip(reason="use value to be defined")
|
94
|
-
def test_grid_filter_on_parents(self, test_app):
|
95
|
-
self.check_search(test_app, "groups_11", total=4)
|
96
|
-
|
97
91
|
def test_grid_search(self, test_app):
|
98
92
|
# search on metadatas
|
99
93
|
self.check_search(test_app, "copyable", total=8)
|
100
94
|
|
101
95
|
def test_edit(self, test_app, layer_groups_test_data, dbsession):
|
96
|
+
from c2cgeoportal_commons.models.main import Log, LogAction
|
97
|
+
|
102
98
|
group = layer_groups_test_data["groups"][1]
|
103
99
|
|
104
100
|
form = self.get_item(test_app, group.id).form
|
@@ -107,8 +103,6 @@ class TestLayersGroups(TestTreeGroup):
|
|
107
103
|
assert "hidden" == self.get_first_field_named(form, "id").attrs["type"]
|
108
104
|
assert group.name == self.get_first_field_named(form, "name").value
|
109
105
|
assert str(group.description or "") == self.get_first_field_named(form, "description").value
|
110
|
-
assert group.is_expanded is False
|
111
|
-
assert group.is_expanded == form["is_expanded"].checked
|
112
106
|
|
113
107
|
self.check_children(
|
114
108
|
form,
|
@@ -125,7 +119,6 @@ class TestLayersGroups(TestTreeGroup):
|
|
125
119
|
new_values = {
|
126
120
|
"name": "new_name",
|
127
121
|
"description": "new description",
|
128
|
-
"is_expanded": True,
|
129
122
|
}
|
130
123
|
for key, value in new_values.items():
|
131
124
|
self.set_first_field_named(form, key, value)
|
@@ -142,13 +135,21 @@ class TestLayersGroups(TestTreeGroup):
|
|
142
135
|
else:
|
143
136
|
assert str(value or "") == str(getattr(group, key) or "")
|
144
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
|
+
|
145
146
|
def test_post_new_with_children_invalid(self, test_app, layer_groups_test_data):
|
146
147
|
"""
|
147
148
|
Check there is no rendering error when validation fails.
|
148
149
|
"""
|
149
150
|
groups = layer_groups_test_data["groups"]
|
150
151
|
resp = test_app.post(
|
151
|
-
"{}/new"
|
152
|
+
f"{self._prefix}/new",
|
152
153
|
(
|
153
154
|
("_charset_", "UTF-8"),
|
154
155
|
("__formid__", "deform"),
|
@@ -167,9 +168,11 @@ class TestLayersGroups(TestTreeGroup):
|
|
167
168
|
assert "Required" == resp.html.select_one(".item-name .help-block").getText().strip()
|
168
169
|
|
169
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
|
+
|
170
173
|
groups = layer_groups_test_data["groups"]
|
171
174
|
resp = test_app.post(
|
172
|
-
"{}/new"
|
175
|
+
f"{self._prefix}/new",
|
173
176
|
(
|
174
177
|
("_charset_", "UTF-8"),
|
175
178
|
("__formid__", "deform"),
|
@@ -210,11 +213,21 @@ class TestLayersGroups(TestTreeGroup):
|
|
210
213
|
rel.treeitem_id for rel in group.children_relation
|
211
214
|
]
|
212
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
|
+
|
213
224
|
def test_post_with_ancestor(self, layer_groups_test_data, test_app):
|
214
|
-
"""
|
225
|
+
"""
|
226
|
+
Check that ancestors are refused to avoid cycles.
|
227
|
+
"""
|
215
228
|
groups = layer_groups_test_data["groups"]
|
216
229
|
resp = test_app.post(
|
217
|
-
"{}/{
|
230
|
+
f"{self._prefix}/{groups[3].id}",
|
218
231
|
(
|
219
232
|
("_charset_", "UTF-8"),
|
220
233
|
("__formid__", "deform"),
|
@@ -232,7 +245,7 @@ class TestLayersGroups(TestTreeGroup):
|
|
232
245
|
status=200,
|
233
246
|
)
|
234
247
|
assert (
|
235
|
-
"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"
|
236
249
|
== resp.html.select_one(".item-children_relation + .help-block").getText().strip()
|
237
250
|
)
|
238
251
|
|
@@ -241,7 +254,7 @@ class TestLayersGroups(TestTreeGroup):
|
|
241
254
|
|
242
255
|
group = layer_groups_test_data["groups"][1]
|
243
256
|
|
244
|
-
resp = test_app.get("{}/{}/duplicate"
|
257
|
+
resp = test_app.get(f"{self._prefix}/{group.id}/duplicate", status=200)
|
245
258
|
form = resp.form
|
246
259
|
|
247
260
|
group = dbsession.query(LayerGroup).filter(LayerGroup.id == group.id).one()
|
@@ -249,8 +262,6 @@ class TestLayersGroups(TestTreeGroup):
|
|
249
262
|
assert "" == self.get_first_field_named(form, "id").value
|
250
263
|
assert group.name == self.get_first_field_named(form, "name").value
|
251
264
|
assert str(group.description or "") == self.get_first_field_named(form, "description").value
|
252
|
-
assert group.is_expanded is False
|
253
|
-
assert group.is_expanded == form["is_expanded"].checked
|
254
265
|
|
255
266
|
self.check_children(
|
256
267
|
form,
|
@@ -267,7 +278,7 @@ class TestLayersGroups(TestTreeGroup):
|
|
267
278
|
duplicated = dbsession.query(LayerGroup).filter(LayerGroup.name == "duplicated").one()
|
268
279
|
|
269
280
|
assert str(duplicated.id) == re.match(
|
270
|
-
|
281
|
+
rf"http://localhost{self._prefix}/(.*)\?msg_col=submit_ok", resp.location
|
271
282
|
).group(1)
|
272
283
|
assert duplicated.id != group.id
|
273
284
|
assert duplicated.children_relation[0].id != group.children_relation[0].id
|
@@ -275,41 +286,56 @@ class TestLayersGroups(TestTreeGroup):
|
|
275
286
|
|
276
287
|
def test_unicity_validator(self, layer_groups_test_data, test_app):
|
277
288
|
group = layer_groups_test_data["groups"][1]
|
278
|
-
resp = test_app.get("{}/{}/duplicate"
|
289
|
+
resp = test_app.get(f"{self._prefix}/{group.id}/duplicate", status=200)
|
279
290
|
|
280
291
|
resp = resp.form.submit("submit")
|
281
292
|
|
282
|
-
self._check_submission_problem(resp, "{} is already used."
|
293
|
+
self._check_submission_problem(resp, f"{group.name} is already used.")
|
283
294
|
|
284
295
|
def test_delete(self, test_app, dbsession, layer_groups_test_data):
|
285
|
-
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
|
+
)
|
286
304
|
|
287
|
-
|
305
|
+
group = layer_groups_test_data["groups"][9]
|
288
306
|
|
289
307
|
assert (
|
290
308
|
3
|
291
|
-
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treegroup_id ==
|
309
|
+
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treegroup_id == group.id).count()
|
292
310
|
)
|
293
311
|
|
294
312
|
assert (
|
295
313
|
1
|
296
|
-
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treeitem_id ==
|
314
|
+
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treeitem_id == group.id).count()
|
297
315
|
)
|
298
316
|
|
299
|
-
test_app.delete("/admin/layer_groups/{}"
|
317
|
+
test_app.delete(f"/admin/layer_groups/{group.id}", status=200)
|
300
318
|
|
301
319
|
dbsession.expire_all()
|
302
320
|
|
303
|
-
assert dbsession.query(LayerGroup).get(
|
304
|
-
assert dbsession.query(TreeGroup).get(
|
305
|
-
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
|
306
324
|
|
307
325
|
assert (
|
308
326
|
0
|
309
|
-
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treegroup_id ==
|
327
|
+
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treegroup_id == group.id).count()
|
310
328
|
)
|
311
329
|
|
312
330
|
assert (
|
313
331
|
0
|
314
|
-
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treeitem_id ==
|
332
|
+
== dbsession.query(LayergroupTreeitem).filter(LayergroupTreeitem.treeitem_id == group.id).count()
|
315
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"
|