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_layertree.py
CHANGED
@@ -3,10 +3,8 @@
|
|
3
3
|
from unittest.mock import patch
|
4
4
|
|
5
5
|
import pytest
|
6
|
-
from selenium.common.exceptions import NoSuchElementException
|
7
6
|
|
8
|
-
from . import AbstractViewsTests
|
9
|
-
from .selenium.page import LayertreePage
|
7
|
+
from . import AbstractViewsTests
|
10
8
|
|
11
9
|
|
12
10
|
@pytest.fixture(scope="function")
|
@@ -15,6 +13,7 @@ def layertree_test_data(dbsession, transact):
|
|
15
13
|
del transact
|
16
14
|
|
17
15
|
from c2cgeoportal_commons.models.main import (
|
16
|
+
Interface,
|
18
17
|
LayerGroup,
|
19
18
|
LayergroupTreeitem,
|
20
19
|
LayerWMS,
|
@@ -23,26 +22,39 @@ def layertree_test_data(dbsession, transact):
|
|
23
22
|
Theme,
|
24
23
|
)
|
25
24
|
|
25
|
+
interface1 = Interface("interface1")
|
26
|
+
dbsession.add(interface1)
|
27
|
+
interface2 = Interface("interface2")
|
28
|
+
dbsession.add(interface2)
|
29
|
+
|
26
30
|
layers_wms = []
|
27
31
|
ogc_server = OGCServer(name="ogc_server")
|
28
32
|
dbsession.add(ogc_server)
|
29
|
-
for i in range(
|
30
|
-
layer_wms = LayerWMS(name="layer_wms_{}"
|
33
|
+
for i in range(10):
|
34
|
+
layer_wms = LayerWMS(name=f"layer_wms_{i}")
|
35
|
+
if i == 1:
|
36
|
+
layer_wms.interfaces = [interface1]
|
37
|
+
elif i > 1:
|
38
|
+
layer_wms.interfaces = [interface1, interface2]
|
31
39
|
layer_wms.ogc_server = ogc_server
|
32
40
|
layers_wms.append(layer_wms)
|
33
41
|
dbsession.add(layer_wms)
|
34
42
|
|
35
43
|
layers_wmts = []
|
36
|
-
for i in range(
|
37
|
-
layer_wmts = LayerWMTS(name="layer_wmts_{}"
|
44
|
+
for i in range(10):
|
45
|
+
layer_wmts = LayerWMTS(name=f"layer_wmts_{i}")
|
46
|
+
if i == 1:
|
47
|
+
layer_wmts.interfaces = [interface1]
|
48
|
+
elif i > 1:
|
49
|
+
layer_wmts.interfaces = [interface1, interface2]
|
38
50
|
layer_wmts.url = "http://localhost/wmts"
|
39
51
|
layer_wmts.layer = layer_wmts.name
|
40
52
|
layers_wmts.append(layer_wmts)
|
41
53
|
dbsession.add(layer_wmts)
|
42
54
|
|
43
55
|
groups = []
|
44
|
-
for i in range(
|
45
|
-
group = LayerGroup(name="layer_group_{}"
|
56
|
+
for i in range(10):
|
57
|
+
group = LayerGroup(name=f"layer_group_{i}")
|
46
58
|
groups.append(group)
|
47
59
|
dbsession.add(group)
|
48
60
|
|
@@ -53,10 +65,14 @@ def layertree_test_data(dbsession, transact):
|
|
53
65
|
dbsession.add(LayergroupTreeitem(group=groups[9], item=groups[8], ordering=3))
|
54
66
|
|
55
67
|
themes = []
|
56
|
-
for i in range(
|
57
|
-
theme = Theme(name="theme_{}"
|
68
|
+
for i in range(5):
|
69
|
+
theme = Theme(name=f"theme_{i}")
|
58
70
|
themes.append(theme)
|
59
71
|
dbsession.add(theme)
|
72
|
+
if i == 1:
|
73
|
+
theme.interfaces = [interface1]
|
74
|
+
elif i > 1:
|
75
|
+
theme.interfaces = [interface1, interface2]
|
60
76
|
|
61
77
|
dbsession.add(LayergroupTreeitem(group=theme, item=groups[i], ordering=0))
|
62
78
|
dbsession.add(LayergroupTreeitem(group=theme, item=groups[i + 5], ordering=1))
|
@@ -76,6 +92,7 @@ def layertree_test_data(dbsession, transact):
|
|
76
92
|
"layers_wms": layers_wms,
|
77
93
|
"layers_wmts": layers_wmts,
|
78
94
|
"ogc_servers": [ogc_server],
|
95
|
+
"interfaces": [interface1, interface2],
|
79
96
|
}
|
80
97
|
)
|
81
98
|
|
@@ -86,7 +103,6 @@ def layertree_test_data(dbsession, transact):
|
|
86
103
|
)
|
87
104
|
@pytest.mark.usefixtures("layertree_test_data", "test_app")
|
88
105
|
class TestLayerTreeView(AbstractViewsTests):
|
89
|
-
|
90
106
|
_prefix = "/admin/layertree"
|
91
107
|
|
92
108
|
def test_index(self, test_app):
|
@@ -95,13 +111,13 @@ class TestLayerTreeView(AbstractViewsTests):
|
|
95
111
|
def check_edit_action(self, test_app, nodes, table, item_id):
|
96
112
|
node = next(n for n in nodes if n["id"] == item_id)
|
97
113
|
action = next(a for a in node["actions"] if a["name"] == "edit")
|
98
|
-
assert "http://localhost/admin/{}/{}"
|
114
|
+
assert f"http://localhost/admin/{table}/{item_id}" == action["url"]
|
99
115
|
test_app.get(action["url"], status=200)
|
100
116
|
|
101
117
|
def check_unlink_action(self, test_app, nodes, group_id, item_id):
|
102
118
|
node = next(n for n in nodes if n["id"] == item_id)
|
103
119
|
action = next(a for a in node["actions"] if a["name"] == "unlink")
|
104
|
-
assert "http://localhost/admin/layertree/unlink/{}/{}"
|
120
|
+
assert f"http://localhost/admin/layertree/unlink/{group_id}/{item_id}" == action["url"]
|
105
121
|
test_app.delete(action["url"], status=200)
|
106
122
|
|
107
123
|
def check_translation(self, nodes, item):
|
@@ -113,7 +129,7 @@ class TestLayerTreeView(AbstractViewsTests):
|
|
113
129
|
node = next(n for n in nodes if n["id"] == parent_id)
|
114
130
|
action = next(a for a in node["actions"] if a["name"] == action_name)
|
115
131
|
assert label == action["label"]
|
116
|
-
assert "http://localhost/admin/{}/new?parent_id={}"
|
132
|
+
assert f"http://localhost/admin/{route_table}/new?parent_id={parent_id}" == action["url"]
|
117
133
|
|
118
134
|
form = test_app.get(action["url"], status=200).form
|
119
135
|
assert form["parent_id"].value == str(parent_id)
|
@@ -152,12 +168,26 @@ class TestLayerTreeView(AbstractViewsTests):
|
|
152
168
|
{"name": "new_name_from_layer_group"},
|
153
169
|
)
|
154
170
|
|
155
|
-
def test_groups(self, test_app, layertree_test_data):
|
171
|
+
def test_groups(self, test_app, layertree_test_data, dbsession):
|
156
172
|
theme = layertree_test_data["themes"][0]
|
173
|
+
|
174
|
+
# Invert children order (to test ordering)
|
175
|
+
theme.children_relation[0].ordering = 1
|
176
|
+
theme.children_relation[1].ordering = 0
|
177
|
+
dbsession.flush()
|
178
|
+
|
157
179
|
resp = self.get(test_app, "/children?group_id={0}&path=_{0}".format(theme.id), status=200)
|
158
180
|
nodes = resp.json
|
159
181
|
assert 2 == len(nodes)
|
160
182
|
|
183
|
+
# check groups are sorted by ordering
|
184
|
+
expected = [
|
185
|
+
relation.treeitem.name
|
186
|
+
for relation in sorted(theme.children_relation, key=lambda relation: relation.ordering)
|
187
|
+
]
|
188
|
+
group_names = [node["name"] for node in nodes]
|
189
|
+
assert expected == group_names
|
190
|
+
|
161
191
|
group = layertree_test_data["groups"][0]
|
162
192
|
self.check_edit_action(test_app, nodes, "layer_groups", group.id)
|
163
193
|
self.check_unlink_action(test_app, nodes, theme.id, group.id)
|
@@ -188,15 +218,29 @@ class TestLayerTreeView(AbstractViewsTests):
|
|
188
218
|
},
|
189
219
|
)
|
190
220
|
|
191
|
-
def test_layers(self, test_app, layertree_test_data):
|
221
|
+
def test_layers(self, test_app, layertree_test_data, dbsession):
|
192
222
|
theme = layertree_test_data["themes"][0]
|
193
223
|
group = layertree_test_data["groups"][0]
|
224
|
+
|
225
|
+
# Invert children order (to test ordering)
|
226
|
+
group.children_relation[0].ordering = 1
|
227
|
+
group.children_relation[1].ordering = 0
|
228
|
+
dbsession.flush()
|
229
|
+
|
194
230
|
resp = self.get(
|
195
231
|
test_app, "/children?group_id={0}&path=_{1}_{0}".format(group.id, theme.id), status=200
|
196
232
|
)
|
197
233
|
nodes = resp.json
|
198
234
|
assert len(nodes) == 2
|
199
235
|
|
236
|
+
# check layers are sorted by ordering
|
237
|
+
expected = [
|
238
|
+
relation.treeitem.name
|
239
|
+
for relation in sorted(group.children_relation, key=lambda relation: relation.ordering)
|
240
|
+
]
|
241
|
+
layer_names = [node["name"] for node in nodes]
|
242
|
+
assert expected == layer_names
|
243
|
+
|
200
244
|
layer_wms = layertree_test_data["layers_wms"][0]
|
201
245
|
layer_wmts = layertree_test_data["layers_wmts"][0]
|
202
246
|
|
@@ -212,96 +256,58 @@ class TestLayerTreeView(AbstractViewsTests):
|
|
212
256
|
def test_unlink(self, test_app, layertree_test_data, dbsession):
|
213
257
|
group = layertree_test_data["groups"][0]
|
214
258
|
item = layertree_test_data["layers_wms"][0]
|
215
|
-
test_app.delete("/admin/layertree/unlink/{}/{
|
259
|
+
test_app.delete(f"/admin/layertree/unlink/{group.id}/{item.id}", status=200)
|
216
260
|
dbsession.expire_all()
|
217
261
|
assert item not in group.children
|
218
262
|
|
263
|
+
def test_delete(self, test_app, layertree_test_data, dbsession):
|
264
|
+
from c2cgeoportal_commons.models.main import LayerGroup, LayerWMS, LayerWMTS
|
219
265
|
|
220
|
-
@skip_if_ci
|
221
|
-
@pytest.mark.selenium
|
222
|
-
@pytest.mark.usefixtures("selenium", "selenium_app", "layertree_test_data")
|
223
|
-
class TestLayerTreeSelenium:
|
224
|
-
|
225
|
-
_prefix = "/layertree"
|
226
|
-
|
227
|
-
def test_unlink(self, dbsession, selenium, selenium_app, layertree_test_data):
|
228
|
-
from c2cgeoportal_commons.models.main import LayergroupTreeitem
|
229
|
-
|
230
|
-
themes = layertree_test_data["themes"]
|
231
|
-
groups = layertree_test_data["groups"]
|
232
|
-
layers_wms = layertree_test_data["layers_wms"]
|
233
|
-
layers_wmts = layertree_test_data["layers_wmts"]
|
234
|
-
|
235
|
-
selenium.get(selenium_app + self._prefix)
|
236
|
-
page = LayertreePage(selenium)
|
237
|
-
page.expand()
|
238
|
-
|
239
|
-
for group_id, item_id, path in (
|
240
|
-
(
|
241
|
-
groups[0].id,
|
242
|
-
layers_wmts[0].id,
|
243
|
-
"_{}_{}_{}".format(themes[0].id, groups[0].id, layers_wmts[0].id),
|
244
|
-
),
|
245
|
-
(
|
246
|
-
groups[0].id,
|
247
|
-
layers_wms[0].id,
|
248
|
-
"_{}_{}_{}".format(themes[0].id, groups[0].id, layers_wms[0].id),
|
249
|
-
),
|
250
|
-
(themes[0].id, groups[0].id, "_{}_{}".format(themes[0].id, groups[0].id)),
|
251
|
-
):
|
252
|
-
action_el = page.find_item_action(path, "unlink", 10)
|
253
|
-
expected_url = "{}/layertree/unlink/{}/{}".format(selenium_app, group_id, item_id)
|
254
|
-
assert expected_url == action_el.get_attribute("data-url")
|
255
|
-
page.click_and_confirm(action_el)
|
256
|
-
|
257
|
-
dbsession.expire_all()
|
258
|
-
link = (
|
259
|
-
dbsession.query(LayergroupTreeitem)
|
260
|
-
.filter(LayergroupTreeitem.treegroup_id == group_id)
|
261
|
-
.filter(LayergroupTreeitem.treeitem_id == item_id)
|
262
|
-
.one_or_none()
|
263
|
-
)
|
264
|
-
assert link is None
|
265
|
-
|
266
|
-
selenium.refresh()
|
267
|
-
page.wait_jquery_to_be_active()
|
268
|
-
page.find_item("_{}_{}_{}".format(themes[0].id, groups[5].id, layers_wmts[5].id), 10)
|
269
|
-
with pytest.raises(NoSuchElementException):
|
270
|
-
page.find_item(path)
|
271
|
-
|
272
|
-
@skip_if_ci
|
273
|
-
@pytest.mark.selenium
|
274
|
-
@pytest.mark.usefixtures("selenium", "selenium_app")
|
275
|
-
def test_delete(self, dbsession, selenium, selenium_app, layertree_test_data):
|
276
|
-
from c2cgeoportal_commons.models.main import LayerWMS, LayerWMTS, LayerGroup
|
277
|
-
|
278
|
-
themes = layertree_test_data["themes"]
|
279
266
|
groups = layertree_test_data["groups"]
|
280
267
|
layers_wms = layertree_test_data["layers_wms"]
|
281
268
|
layers_wmts = layertree_test_data["layers_wmts"]
|
282
269
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
for item_id, path, model in (
|
288
|
-
(layers_wmts[1].id, "_{}_{}_{}".format(themes[1].id, groups[1].id, layers_wmts[1].id), LayerWMTS),
|
289
|
-
(layers_wms[1].id, "_{}_{}_{}".format(themes[1].id, groups[1].id, layers_wms[1].id), LayerWMS),
|
290
|
-
(groups[1].id, "_{}_{}".format(themes[1].id, groups[1].id), LayerGroup),
|
270
|
+
for item_id, model in (
|
271
|
+
(layers_wmts[1].id, LayerWMTS),
|
272
|
+
(layers_wms[1].id, LayerWMS),
|
273
|
+
(groups[1].id, LayerGroup),
|
291
274
|
):
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
275
|
+
test_app.delete(f"/admin/layertree/delete/{item_id}", status=200)
|
276
|
+
assert dbsession.query(model).get(item_id) is None
|
277
|
+
|
278
|
+
@pytest.mark.parametrize(
|
279
|
+
"params,expected",
|
280
|
+
[
|
281
|
+
({}, ["theme_0", "theme_3", "theme_1", "theme_2", "theme_4"]),
|
282
|
+
({"interface": "interface1"}, ["theme_3", "theme_1", "theme_2", "theme_4"]),
|
283
|
+
({"interface": "interface2"}, ["theme_3", "theme_2", "theme_4"]),
|
284
|
+
],
|
285
|
+
)
|
286
|
+
def test_themes_interfaces(self, test_app, layertree_test_data, params, expected):
|
287
|
+
resp = self.get(test_app, "/children", status=200, params=params)
|
288
|
+
nodes = resp.json
|
289
|
+
assert expected == [node["name"] for node in nodes if node["item_type"] == "theme"]
|
290
|
+
|
291
|
+
@pytest.mark.parametrize(
|
292
|
+
"interface,index,length",
|
293
|
+
[
|
294
|
+
(None, 0, 2),
|
295
|
+
(None, 1, 2),
|
296
|
+
(None, 2, 2),
|
297
|
+
("interface1", 0, 0),
|
298
|
+
("interface1", 1, 2),
|
299
|
+
("interface1", 2, 2),
|
300
|
+
("interface2", 0, 0),
|
301
|
+
("interface2", 1, 0),
|
302
|
+
("interface2", 2, 2),
|
303
|
+
],
|
304
|
+
)
|
305
|
+
def test_layers_interface(self, test_app, layertree_test_data, interface, index, length):
|
306
|
+
theme = layertree_test_data["themes"][index]
|
307
|
+
group = layertree_test_data["groups"][index]
|
308
|
+
params = {"group_id": group.id, "path": f"_{theme.id}_{group.id}"}
|
309
|
+
if interface:
|
310
|
+
params["interface"] = interface
|
311
|
+
resp = self.get(test_app, "/children", status=200, params=params)
|
312
|
+
nodes = resp.json
|
313
|
+
assert length == len(nodes)
|
tests/test_learn.py
CHANGED
tests/test_left_menu.py
CHANGED
@@ -0,0 +1,64 @@
|
|
1
|
+
# Copyright (c) 2022-2024, Camptocamp SA
|
2
|
+
# All rights reserved.
|
3
|
+
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
8
|
+
# list of conditions and the following disclaimer.
|
9
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
# this list of conditions and the following disclaimer in the documentation
|
11
|
+
# and/or other materials provided with the distribution.
|
12
|
+
|
13
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
14
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
15
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
16
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
17
|
+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
18
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
19
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
20
|
+
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
21
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
22
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
23
|
+
|
24
|
+
# The views and conclusions contained in the software and documentation are those
|
25
|
+
# of the authors and should not be interpreted as representing official policies,
|
26
|
+
# either expressed or implied, of the FreeBSD Project.
|
27
|
+
|
28
|
+
# pylint: disable=missing-docstring
|
29
|
+
|
30
|
+
from unittest.mock import Mock, mock_open, patch
|
31
|
+
|
32
|
+
import pytest
|
33
|
+
import yaml
|
34
|
+
from c2c.template.config import config as configuration
|
35
|
+
|
36
|
+
from c2cgeoportal_admin.lib.lingva_extractor import GeomapfishConfigExtractor
|
37
|
+
|
38
|
+
GMF_CONFIG = """
|
39
|
+
vars:
|
40
|
+
admin_interface:
|
41
|
+
available_metadata:
|
42
|
+
- name: metadata1
|
43
|
+
description: description1
|
44
|
+
translate: true
|
45
|
+
available_functionalities:
|
46
|
+
- name: functionality1
|
47
|
+
description: description2
|
48
|
+
"""
|
49
|
+
|
50
|
+
|
51
|
+
class TestGeomapfishConfigExtractor:
|
52
|
+
@patch(
|
53
|
+
"c2cgeoportal_admin.lib.lingva_extractor.open",
|
54
|
+
mock_open(read_data=GMF_CONFIG),
|
55
|
+
)
|
56
|
+
def test_extract_config(self):
|
57
|
+
extractor = GeomapfishConfigExtractor()
|
58
|
+
|
59
|
+
options = Mock()
|
60
|
+
options.keywords = []
|
61
|
+
|
62
|
+
messages = list(extractor("config.yaml", options))
|
63
|
+
|
64
|
+
assert {msg.msgid for msg in messages} == {"description1", "description2"}
|
tests/test_logs.py
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# pylint: disable=no-self-use,unsubscriptable-object
|
2
|
+
|
3
|
+
import datetime
|
4
|
+
from datetime import timezone
|
5
|
+
|
6
|
+
import pytest
|
7
|
+
|
8
|
+
from . import AbstractViewsTests
|
9
|
+
|
10
|
+
|
11
|
+
@pytest.fixture(scope="function")
|
12
|
+
@pytest.mark.usefixtures("dbsession", "transact")
|
13
|
+
def logs_test_data(dbsession, transact):
|
14
|
+
del transact
|
15
|
+
|
16
|
+
from c2cgeoportal_commons.models.main import AbstractLog
|
17
|
+
from c2cgeoportal_commons.models.main import Log as MainLog
|
18
|
+
from c2cgeoportal_commons.models.main import LogAction
|
19
|
+
from c2cgeoportal_commons.models.static import Log as StaticLog
|
20
|
+
|
21
|
+
logs = []
|
22
|
+
for i in range(0, 5):
|
23
|
+
log = MainLog(
|
24
|
+
date=datetime.datetime.now(timezone.utc),
|
25
|
+
action=[LogAction.INSERT, LogAction.UPDATE, LogAction.DELETE][i % 3],
|
26
|
+
element_type="role",
|
27
|
+
element_id=i,
|
28
|
+
element_name=f"role_{i}",
|
29
|
+
element_url_table="roles",
|
30
|
+
username="testuser",
|
31
|
+
)
|
32
|
+
dbsession.add(log)
|
33
|
+
logs.append(log)
|
34
|
+
|
35
|
+
log = StaticLog(
|
36
|
+
date=datetime.datetime.now(timezone.utc),
|
37
|
+
action=[LogAction.INSERT, LogAction.UPDATE, LogAction.DELETE][i % 3],
|
38
|
+
element_type="user",
|
39
|
+
element_id=i,
|
40
|
+
element_name=f"user_{i}",
|
41
|
+
element_url_table="users",
|
42
|
+
username="testuser",
|
43
|
+
)
|
44
|
+
dbsession.add(log)
|
45
|
+
logs.append(log)
|
46
|
+
|
47
|
+
dbsession.flush()
|
48
|
+
|
49
|
+
yield {
|
50
|
+
"logs": logs,
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
@pytest.mark.usefixtures("logs_test_data", "test_app")
|
55
|
+
class TestLog(AbstractViewsTests):
|
56
|
+
_prefix = "/admin/logs"
|
57
|
+
|
58
|
+
def test_index_rendering(self, test_app):
|
59
|
+
resp = self.get(test_app)
|
60
|
+
|
61
|
+
self.check_left_menu(resp, "Logs")
|
62
|
+
|
63
|
+
expected = [
|
64
|
+
("actions", "", "false"),
|
65
|
+
("id", "id", "true"),
|
66
|
+
("date", "Date"),
|
67
|
+
("username", "Username"),
|
68
|
+
("action", "Action"),
|
69
|
+
("element_type", "Element type"),
|
70
|
+
("element_id", "Element identifier"),
|
71
|
+
("element_name", "Element name"),
|
72
|
+
]
|
73
|
+
self.check_grid_headers(resp, expected, new=False)
|
74
|
+
|
75
|
+
def test_grid_default_sort_on_date_desc(self, test_app, logs_test_data):
|
76
|
+
json = self.check_search(test_app)
|
77
|
+
expected_ids = [
|
78
|
+
log.id
|
79
|
+
for log in sorted(
|
80
|
+
logs_test_data["logs"],
|
81
|
+
key=lambda log: log.date,
|
82
|
+
reverse=True,
|
83
|
+
)
|
84
|
+
]
|
85
|
+
result_ids = [int(row["_id_"]) for row in json["rows"]]
|
86
|
+
assert result_ids == expected_ids
|
87
|
+
|
88
|
+
def test_grid_sort_on_element_type(self, test_app, logs_test_data):
|
89
|
+
json = self.check_search(test_app, sort="element_type")
|
90
|
+
expected_ids = [
|
91
|
+
log.id
|
92
|
+
for log in sorted(
|
93
|
+
logs_test_data["logs"],
|
94
|
+
key=lambda log: (log.element_type, -log.date.timestamp()),
|
95
|
+
)
|
96
|
+
]
|
97
|
+
result_ids = [int(row["_id_"]) for row in json["rows"]]
|
98
|
+
assert result_ids == expected_ids
|
99
|
+
|
100
|
+
def test_grid_search(self, test_app):
|
101
|
+
self.check_search(test_app, "role", total=5)
|
102
|
+
self.check_search(test_app, "user_2", total=1)
|
tests/test_main.py
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
-
from pyramid import testing
|
2
1
|
import pytest
|
2
|
+
from pyramid import testing
|
3
3
|
from webtest import TestApp as WebTestApp
|
4
4
|
|
5
5
|
|
6
6
|
@pytest.mark.usefixtures("app_env")
|
7
7
|
def test_main(app_env):
|
8
|
-
"""
|
8
|
+
"""
|
9
|
+
Test dev environment.
|
10
|
+
"""
|
9
11
|
config = testing.setUp(registry=app_env["registry"])
|
10
12
|
app = config.make_wsgi_app()
|
11
13
|
testapp = WebTestApp(app)
|