c2cgeoportal-admin 2.6.0__py3-none-any.whl → 2.8.1.180__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 +32 -10
- c2cgeoportal_admin/lib/lingua_extractor.py +77 -0
- c2cgeoportal_admin/lib/ogcserver_synchronizer.py +168 -56
- c2cgeoportal_admin/py.typed +0 -0
- c2cgeoportal_admin/routes.py +7 -4
- c2cgeoportal_admin/schemas/dimensions.py +12 -10
- c2cgeoportal_admin/schemas/functionalities.py +62 -21
- c2cgeoportal_admin/schemas/interfaces.py +22 -18
- c2cgeoportal_admin/schemas/metadata.py +100 -47
- c2cgeoportal_admin/schemas/restriction_areas.py +21 -19
- c2cgeoportal_admin/schemas/roles.py +7 -5
- c2cgeoportal_admin/schemas/treegroup.py +38 -17
- c2cgeoportal_admin/schemas/treeitem.py +2 -3
- c2cgeoportal_admin/static/layertree.css +3 -4
- c2cgeoportal_admin/static/navbar.css +36 -35
- c2cgeoportal_admin/static/theme.css +16 -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 +7 -6
- c2cgeoportal_admin/views/functionalities.py +33 -6
- c2cgeoportal_admin/views/home.py +5 -5
- c2cgeoportal_admin/views/interfaces.py +7 -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 +41 -35
- c2cgeoportal_admin/views/layers_wmts.py +41 -35
- c2cgeoportal_admin/views/layertree.py +36 -28
- c2cgeoportal_admin/views/logged_views.py +80 -0
- c2cgeoportal_admin/views/logs.py +90 -0
- c2cgeoportal_admin/views/oauth2_clients.py +30 -22
- c2cgeoportal_admin/views/ogc_servers.py +119 -37
- c2cgeoportal_admin/views/restriction_areas.py +13 -11
- c2cgeoportal_admin/views/roles.py +16 -12
- c2cgeoportal_admin/views/themes.py +15 -14
- c2cgeoportal_admin/views/themes_ordering.py +13 -8
- c2cgeoportal_admin/views/treeitems.py +14 -12
- c2cgeoportal_admin/views/users.py +12 -7
- c2cgeoportal_admin/widgets.py +17 -14
- {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.8.1.180.dist-info}/METADATA +17 -8
- c2cgeoportal_admin-2.8.1.180.dist-info/RECORD +95 -0
- {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.8.1.180.dist-info}/WHEEL +1 -1
- c2cgeoportal_admin-2.8.1.180.dist-info/entry_points.txt +6 -0
- tests/__init__.py +11 -12
- tests/conftest.py +2 -1
- 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_vectortiles.py +43 -20
- 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_lingua_extractor_config.py +64 -0
- tests/test_logs.py +103 -0
- tests/test_main.py +3 -1
- tests/test_metadatas.py +34 -21
- tests/test_oauth2_clients.py +37 -9
- tests/test_ogc_servers.py +84 -35
- tests/test_restriction_areas.py +38 -15
- tests/test_role.py +68 -41
- tests/test_themes.py +71 -37
- tests/test_themes_ordering.py +1 -2
- tests/test_treegroup.py +2 -2
- tests/test_user.py +48 -17
- 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.8.1.180.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,64 @@
|
|
1
|
+
# Copyright (c) 2022-2023, 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.lingua_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.lingua_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,103 @@
|
|
1
|
+
# pylint: disable=no-self-use,unsubscriptable-object
|
2
|
+
|
3
|
+
import datetime
|
4
|
+
|
5
|
+
import pytest
|
6
|
+
import pytz
|
7
|
+
from pyramid.testing import DummyRequest
|
8
|
+
|
9
|
+
from . import AbstractViewsTests
|
10
|
+
|
11
|
+
|
12
|
+
@pytest.fixture(scope="function")
|
13
|
+
@pytest.mark.usefixtures("dbsession", "transact")
|
14
|
+
def logs_test_data(dbsession, transact):
|
15
|
+
del transact
|
16
|
+
|
17
|
+
from c2cgeoportal_commons.models.main import AbstractLog
|
18
|
+
from c2cgeoportal_commons.models.main import Log as MainLog
|
19
|
+
from c2cgeoportal_commons.models.main import LogAction
|
20
|
+
from c2cgeoportal_commons.models.static import Log as StaticLog
|
21
|
+
|
22
|
+
logs = []
|
23
|
+
for i in range(0, 5):
|
24
|
+
log = MainLog(
|
25
|
+
date=datetime.datetime.now(pytz.utc),
|
26
|
+
action=[LogAction.INSERT, LogAction.UPDATE, LogAction.DELETE][i % 3],
|
27
|
+
element_type="role",
|
28
|
+
element_id=i,
|
29
|
+
element_name=f"role_{i}",
|
30
|
+
element_url_table="roles",
|
31
|
+
username="testuser",
|
32
|
+
)
|
33
|
+
dbsession.add(log)
|
34
|
+
logs.append(log)
|
35
|
+
|
36
|
+
log = StaticLog(
|
37
|
+
date=datetime.datetime.now(pytz.utc),
|
38
|
+
action=[LogAction.INSERT, LogAction.UPDATE, LogAction.DELETE][i % 3],
|
39
|
+
element_type="user",
|
40
|
+
element_id=i,
|
41
|
+
element_name=f"user_{i}",
|
42
|
+
element_url_table="users",
|
43
|
+
username="testuser",
|
44
|
+
)
|
45
|
+
dbsession.add(log)
|
46
|
+
logs.append(log)
|
47
|
+
|
48
|
+
dbsession.flush()
|
49
|
+
|
50
|
+
yield {
|
51
|
+
"logs": logs,
|
52
|
+
}
|
53
|
+
|
54
|
+
|
55
|
+
@pytest.mark.usefixtures("logs_test_data", "test_app")
|
56
|
+
class TestLog(AbstractViewsTests):
|
57
|
+
_prefix = "/admin/logs"
|
58
|
+
|
59
|
+
def test_index_rendering(self, test_app):
|
60
|
+
resp = self.get(test_app)
|
61
|
+
|
62
|
+
self.check_left_menu(resp, "Logs")
|
63
|
+
|
64
|
+
expected = [
|
65
|
+
("actions", "", "false"),
|
66
|
+
("id", "id", "true"),
|
67
|
+
("date", "Date"),
|
68
|
+
("username", "Username"),
|
69
|
+
("action", "Action"),
|
70
|
+
("element_type", "Element type"),
|
71
|
+
("element_id", "Element identifier"),
|
72
|
+
("element_name", "Element name"),
|
73
|
+
]
|
74
|
+
self.check_grid_headers(resp, expected, new=False)
|
75
|
+
|
76
|
+
def test_grid_default_sort_on_date_desc(self, test_app, logs_test_data):
|
77
|
+
json = self.check_search(test_app)
|
78
|
+
expected_ids = [
|
79
|
+
log.id
|
80
|
+
for log in sorted(
|
81
|
+
logs_test_data["logs"],
|
82
|
+
key=lambda log: log.date,
|
83
|
+
reverse=True,
|
84
|
+
)
|
85
|
+
]
|
86
|
+
result_ids = [int(row["_id_"]) for row in json["rows"]]
|
87
|
+
assert result_ids == expected_ids
|
88
|
+
|
89
|
+
def test_grid_sort_on_element_type(self, test_app, logs_test_data):
|
90
|
+
json = self.check_search(test_app, sort="element_type")
|
91
|
+
expected_ids = [
|
92
|
+
log.id
|
93
|
+
for log in sorted(
|
94
|
+
logs_test_data["logs"],
|
95
|
+
key=lambda log: (log.element_type, -log.date.timestamp()),
|
96
|
+
)
|
97
|
+
]
|
98
|
+
result_ids = [int(row["_id_"]) for row in json["rows"]]
|
99
|
+
assert result_ids == expected_ids
|
100
|
+
|
101
|
+
def test_grid_search(self, test_app):
|
102
|
+
self.check_search(test_app, "role", total=5)
|
103
|
+
self.check_search(test_app, "user_2", total=1)
|
tests/test_main.py
CHANGED
@@ -5,7 +5,9 @@ from webtest import TestApp as WebTestApp
|
|
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)
|
tests/test_metadatas.py
CHANGED
@@ -59,7 +59,6 @@ def metadatas_test_data(dbsession, transact):
|
|
59
59
|
|
60
60
|
@pytest.mark.usefixtures("metadatas_test_data", "test_app")
|
61
61
|
class TestMetadatasView(AbstractViewsTests):
|
62
|
-
|
63
62
|
_prefix = "/admin/"
|
64
63
|
|
65
64
|
def __metadata_ui_types(self):
|
@@ -85,7 +84,9 @@ class TestMetadatasView(AbstractViewsTests):
|
|
85
84
|
return None
|
86
85
|
return metadata.value
|
87
86
|
|
88
|
-
def _check_metadatas(self, test_app, item, metadatas):
|
87
|
+
def _check_metadatas(self, test_app, item, metadatas, model):
|
88
|
+
from c2cgeoportal_admin.schemas.metadata import metadata_definitions
|
89
|
+
|
89
90
|
settings = test_app.app.registry.settings
|
90
91
|
self._check_sequence(
|
91
92
|
item,
|
@@ -96,9 +97,7 @@ class TestMetadatasView(AbstractViewsTests):
|
|
96
97
|
"name": "name",
|
97
98
|
"value": [
|
98
99
|
{"text": s_m["name"], "value": s_m["name"], "selected": s_m["name"] == m.name}
|
99
|
-
for s_m in sorted(
|
100
|
-
settings["admin_interface"]["available_metadata"], key=lambda m: m["name"]
|
101
|
-
)
|
100
|
+
for s_m in sorted(metadata_definitions(settings, model), key=lambda m: m["name"])
|
102
101
|
],
|
103
102
|
"label": "Name",
|
104
103
|
},
|
@@ -131,7 +130,7 @@ class TestMetadatasView(AbstractViewsTests):
|
|
131
130
|
resp = self._post_metadata(test_app, url, base_mapping, name, value, 200)
|
132
131
|
assert (
|
133
132
|
error_msg
|
134
|
-
== resp.html.select_one(".item-{
|
133
|
+
== resp.html.select_one(f".item-{self.__metadata_ui_type(test_app, name)} .help-block")
|
135
134
|
.getText()
|
136
135
|
.strip()
|
137
136
|
)
|
@@ -156,12 +155,16 @@ class TestMetadatasView(AbstractViewsTests):
|
|
156
155
|
)
|
157
156
|
|
158
157
|
def test_get_true_boolean_metadata(self, metadatas_test_data, test_app):
|
159
|
-
|
160
|
-
|
158
|
+
from c2cgeoportal_commons.models.main import LayerWMS
|
159
|
+
|
160
|
+
metadatas_test_data["layer_wms"].get_metadata("_boolean")[0].value = "true"
|
161
|
+
self._test_edit_treeitem("layers_wms", metadatas_test_data["layer_wms"], test_app, LayerWMS)
|
161
162
|
|
162
163
|
def test_get_false_boolean_metadata(self, metadatas_test_data, test_app):
|
163
|
-
|
164
|
-
|
164
|
+
from c2cgeoportal_commons.models.main import LayerWMS
|
165
|
+
|
166
|
+
metadatas_test_data["layer_wms"].get_metadata("_boolean")[0].value = "false"
|
167
|
+
self._test_edit_treeitem("layers_wms", metadatas_test_data["layer_wms"], test_app, LayerWMS)
|
165
168
|
|
166
169
|
def test_post_true_boolean_metadata(self, test_app, metadatas_test_data, dbsession):
|
167
170
|
from c2cgeoportal_commons.models.main import LayerWMS
|
@@ -175,7 +178,7 @@ class TestMetadatasView(AbstractViewsTests):
|
|
175
178
|
302,
|
176
179
|
)
|
177
180
|
layer = dbsession.query(LayerWMS).filter(LayerWMS.name == "new_name").one()
|
178
|
-
assert layer.
|
181
|
+
assert layer.get_metadata("_boolean")[0].value == "true"
|
179
182
|
|
180
183
|
def test_post_false_boolean_metadata(self, test_app, metadatas_test_data, dbsession):
|
181
184
|
from c2cgeoportal_commons.models.main import LayerWMS
|
@@ -189,7 +192,7 @@ class TestMetadatasView(AbstractViewsTests):
|
|
189
192
|
302,
|
190
193
|
)
|
191
194
|
layer = dbsession.query(LayerWMS).filter(LayerWMS.name == "new_name").one()
|
192
|
-
assert layer.
|
195
|
+
assert layer.get_metadata("_boolean")[0].value == "false"
|
193
196
|
|
194
197
|
def test_valid_float_metadata(self, test_app, metadatas_test_data):
|
195
198
|
self._post_metadata(
|
@@ -304,31 +307,41 @@ class TestMetadatasView(AbstractViewsTests):
|
|
304
307
|
302,
|
305
308
|
)
|
306
309
|
|
307
|
-
def _test_edit_treeitem(self, prefix, item, test_app):
|
308
|
-
resp = self.get(test_app, "{}/{
|
309
|
-
self._check_metadatas(test_app, resp.html.select_one(".item-metadatas"), item.metadatas)
|
310
|
+
def _test_edit_treeitem(self, prefix, item, test_app, model):
|
311
|
+
resp = self.get(test_app, f"{prefix}/{item.id}")
|
312
|
+
self._check_metadatas(test_app, resp.html.select_one(".item-metadatas"), item.metadatas, model)
|
310
313
|
resp.form.submit("submit", status=302)
|
311
314
|
|
312
315
|
def test_layer_wms_metadatas(self, metadatas_test_data, test_app):
|
313
|
-
|
316
|
+
from c2cgeoportal_commons.models.main import LayerWMS
|
317
|
+
|
318
|
+
self._test_edit_treeitem("layers_wms", metadatas_test_data["layer_wms"], test_app, LayerWMS)
|
314
319
|
|
315
320
|
def test_layer_wmts_metadatas(self, metadatas_test_data, test_app):
|
316
|
-
|
321
|
+
from c2cgeoportal_commons.models.main import LayerWMTS
|
322
|
+
|
323
|
+
self._test_edit_treeitem("layers_wmts", metadatas_test_data["layer_wmts"], test_app, LayerWMTS)
|
317
324
|
|
318
325
|
def test_theme_metadatas(self, metadatas_test_data, test_app):
|
319
|
-
|
326
|
+
from c2cgeoportal_commons.models.main import Theme
|
327
|
+
|
328
|
+
self._test_edit_treeitem("themes", metadatas_test_data["theme"], test_app, Theme)
|
320
329
|
|
321
330
|
def test_group_metadatas(self, metadatas_test_data, test_app):
|
322
|
-
|
331
|
+
from c2cgeoportal_commons.models.main import LayerGroup
|
332
|
+
|
333
|
+
self._test_edit_treeitem("layer_groups", metadatas_test_data["group"], test_app, LayerGroup)
|
323
334
|
|
324
335
|
def test_undefined_metadata(self, metadatas_test_data, test_app):
|
325
|
-
"""
|
336
|
+
"""
|
337
|
+
Undefined metadata must be kept intact across submissions.
|
338
|
+
"""
|
326
339
|
from c2cgeoportal_commons.models.main import Metadata
|
327
340
|
|
328
341
|
layer = metadatas_test_data["layer_wms"]
|
329
342
|
layer.metadatas = [Metadata("_undefined", "This is an undefined metadata")]
|
330
343
|
|
331
|
-
resp = self.get(test_app, "layers_wms/{
|
344
|
+
resp = self.get(test_app, f"layers_wms/{layer.id}")
|
332
345
|
resp.form.submit("submit", status=302)
|
333
346
|
|
334
347
|
metadata = layer.metadatas[0]
|
tests/test_oauth2_clients.py
CHANGED
@@ -35,7 +35,6 @@ def oauth2_clients_test_data(dbsession, transact):
|
|
35
35
|
|
36
36
|
@pytest.mark.usefixtures("oauth2_clients_test_data", "test_app")
|
37
37
|
class TestOAuth2Client(TestTreeGroup):
|
38
|
-
|
39
38
|
_prefix = "/admin/oauth2_clients"
|
40
39
|
|
41
40
|
def test_index_rendering(self, test_app):
|
@@ -59,7 +58,8 @@ class TestOAuth2Client(TestTreeGroup):
|
|
59
58
|
self.check_search(test_app, client.client_id, total=1)
|
60
59
|
|
61
60
|
def test_submit_new(self, dbsession, test_app, oauth2_clients_test_data):
|
62
|
-
from c2cgeoportal_commons.models.
|
61
|
+
from c2cgeoportal_commons.models.main import LogAction
|
62
|
+
from c2cgeoportal_commons.models.static import Log, OAuth2Client
|
63
63
|
|
64
64
|
resp = test_app.post(
|
65
65
|
"/admin/oauth2_clients/new",
|
@@ -84,7 +84,18 @@ class TestOAuth2Client(TestTreeGroup):
|
|
84
84
|
assert oauth2_client.secret == "12345"
|
85
85
|
assert oauth2_client.redirect_uri == "http://127.0.0.1:7070/bis"
|
86
86
|
|
87
|
+
log = dbsession.query(Log).one()
|
88
|
+
assert log.date != None
|
89
|
+
assert log.action == LogAction.INSERT
|
90
|
+
assert log.element_type == "oauth2_client"
|
91
|
+
assert log.element_id == oauth2_client.id
|
92
|
+
assert log.element_name == oauth2_client.client_id
|
93
|
+
assert log.username == "test_user"
|
94
|
+
|
87
95
|
def test_edit_then_save(self, dbsession, test_app, oauth2_clients_test_data):
|
96
|
+
from c2cgeoportal_commons.models.main import LogAction
|
97
|
+
from c2cgeoportal_commons.models.static import Log
|
98
|
+
|
88
99
|
oauth2_client = oauth2_clients_test_data["oauth2_clients"][10]
|
89
100
|
|
90
101
|
dbsession.expire(oauth2_client)
|
@@ -112,12 +123,20 @@ class TestOAuth2Client(TestTreeGroup):
|
|
112
123
|
assert "New secret" == oauth2_client.secret
|
113
124
|
assert "New redirect URI" == oauth2_client.redirect_uri
|
114
125
|
|
126
|
+
log = dbsession.query(Log).one()
|
127
|
+
assert log.date != None
|
128
|
+
assert log.action == LogAction.UPDATE
|
129
|
+
assert log.element_type == "oauth2_client"
|
130
|
+
assert log.element_id == oauth2_client.id
|
131
|
+
assert log.element_name == oauth2_client.client_id
|
132
|
+
assert log.username == "test_user"
|
133
|
+
|
115
134
|
def test_duplicate(self, oauth2_clients_test_data, test_app, dbsession):
|
116
135
|
from c2cgeoportal_commons.models.static import OAuth2Client
|
117
136
|
|
118
137
|
oauth2_client_proto = oauth2_clients_test_data["oauth2_clients"][7]
|
119
138
|
|
120
|
-
resp = test_app.get("/admin/oauth2_clients/{}/duplicate"
|
139
|
+
resp = test_app.get(f"/admin/oauth2_clients/{oauth2_client_proto.id}/duplicate", status=200)
|
121
140
|
form = resp.form
|
122
141
|
|
123
142
|
assert "" == self.get_first_field_named(form, "id").value
|
@@ -134,19 +153,28 @@ class TestOAuth2Client(TestTreeGroup):
|
|
134
153
|
assert oauth2_client_proto.id != oauth2_client.id
|
135
154
|
|
136
155
|
def test_delete(self, test_app, dbsession):
|
137
|
-
from c2cgeoportal_commons.models.
|
156
|
+
from c2cgeoportal_commons.models.main import LogAction
|
157
|
+
from c2cgeoportal_commons.models.static import Log, OAuth2Client
|
158
|
+
|
159
|
+
oauth2_client = dbsession.query(OAuth2Client).first()
|
160
|
+
test_app.delete(f"/admin/oauth2_clients/{oauth2_client.id}", status=200)
|
161
|
+
assert dbsession.query(OAuth2Client).get(oauth2_client.id) is None
|
138
162
|
|
139
|
-
|
140
|
-
|
141
|
-
assert
|
163
|
+
log = dbsession.query(Log).one()
|
164
|
+
assert log.date != None
|
165
|
+
assert log.action == LogAction.DELETE
|
166
|
+
assert log.element_type == "oauth2_client"
|
167
|
+
assert log.element_id == oauth2_client.id
|
168
|
+
assert log.element_name == oauth2_client.client_id
|
169
|
+
assert log.username == "test_user"
|
142
170
|
|
143
171
|
def test_unicity_validator(self, oauth2_clients_test_data, test_app):
|
144
172
|
oauth2_client_proto = oauth2_clients_test_data["oauth2_clients"][7]
|
145
|
-
resp = test_app.get("/admin/oauth2_clients/{}/duplicate"
|
173
|
+
resp = test_app.get(f"/admin/oauth2_clients/{oauth2_client_proto.id}/duplicate", status=200)
|
146
174
|
|
147
175
|
resp = resp.form.submit("submit")
|
148
176
|
|
149
|
-
self._check_submission_problem(resp, "{} is already used."
|
177
|
+
self._check_submission_problem(resp, f"{oauth2_client_proto.client_id} is already used.")
|
150
178
|
|
151
179
|
@pytest.mark.usefixtures("raise_db_error_on_query")
|
152
180
|
def test_grid_dberror(self, dbsession):
|
tests/test_ogc_servers.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# pylint: disable=no-self-use
|
2
2
|
|
3
3
|
import re
|
4
|
+
from unittest.mock import patch
|
4
5
|
|
5
6
|
import pytest
|
6
7
|
|
@@ -17,8 +18,8 @@ def ogc_server_test_data(dbsession, transact):
|
|
17
18
|
auth = ["No auth", "Standard auth", "Geoserver auth", "Proxy"]
|
18
19
|
servers = []
|
19
20
|
for i in range(0, 8):
|
20
|
-
server = OGCServer(name="server_{}"
|
21
|
-
server.url = "https://somebasicurl_{}.com"
|
21
|
+
server = OGCServer(name=f"server_{i}", description=f"description_{i}")
|
22
|
+
server.url = f"https://somebasicurl_{i}.com"
|
22
23
|
server.image_type = "image/jpeg" if i % 2 == 0 else "image/png"
|
23
24
|
server.auth = auth[i % 4]
|
24
25
|
dbsession.add(server)
|
@@ -31,7 +32,6 @@ def ogc_server_test_data(dbsession, transact):
|
|
31
32
|
|
32
33
|
@pytest.mark.usefixtures("ogc_server_test_data", "test_app")
|
33
34
|
class TestOGCServer(AbstractViewsTests):
|
34
|
-
|
35
35
|
_prefix = "/admin/ogc_servers"
|
36
36
|
|
37
37
|
def test_index_rendering(self, test_app):
|
@@ -59,54 +59,82 @@ class TestOGCServer(AbstractViewsTests):
|
|
59
59
|
self.check_search(test_app, "server_0", total=1)
|
60
60
|
|
61
61
|
def test_submit_new(self, dbsession, test_app):
|
62
|
-
from c2cgeoportal_commons.models.main import OGCServer
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
62
|
+
from c2cgeoportal_commons.models.main import Log, LogAction, OGCServer
|
63
|
+
|
64
|
+
with patch("c2cgeoportal_admin.views.ogc_servers.OGCServerViews._update_cache"):
|
65
|
+
resp = test_app.post(
|
66
|
+
"/admin/ogc_servers/new",
|
67
|
+
{
|
68
|
+
"name": "new_name",
|
69
|
+
"description": "new description",
|
70
|
+
"url": "www.randomurl.com",
|
71
|
+
"type": "mapserver",
|
72
|
+
"auth": "No auth",
|
73
|
+
"image_type": "image/png",
|
74
|
+
},
|
75
|
+
status=302,
|
76
|
+
)
|
76
77
|
ogc_server = dbsession.query(OGCServer).filter(OGCServer.name == "new_name").one()
|
77
78
|
assert str(ogc_server.id) == re.match(
|
78
79
|
r"http://localhost/admin/ogc_servers/(.*)\?msg_col=submit_ok", resp.location
|
79
80
|
).group(1)
|
80
81
|
assert ogc_server.name == "new_name"
|
81
82
|
|
82
|
-
|
83
|
+
log = dbsession.query(Log).one()
|
84
|
+
assert log.date != None
|
85
|
+
assert log.action == LogAction.INSERT
|
86
|
+
assert log.element_type == "ogc_server"
|
87
|
+
assert log.element_id == ogc_server.id
|
88
|
+
assert log.element_name == ogc_server.name
|
89
|
+
assert log.username == "test_user"
|
90
|
+
|
91
|
+
def test_edit(self, test_app, ogc_server_test_data, dbsession):
|
92
|
+
from c2cgeoportal_commons.models.main import Log, LogAction
|
93
|
+
|
83
94
|
ogc_server = ogc_server_test_data["ogc_servers"][0]
|
84
|
-
resp = test_app.get("/admin/ogc_servers/{
|
95
|
+
resp = test_app.get(f"/admin/ogc_servers/{ogc_server.id}", status=200)
|
85
96
|
form = resp.form
|
86
97
|
assert str(ogc_server.id) == self.get_first_field_named(form, "id").value
|
87
98
|
assert "hidden" == self.get_first_field_named(form, "id").attrs["type"]
|
88
99
|
assert ogc_server.name == form["name"].value
|
89
100
|
form["description"] = "new_description"
|
90
|
-
|
101
|
+
with patch("c2cgeoportal_admin.views.ogc_servers.OGCServerViews._update_cache"):
|
102
|
+
assert form.submit().status_int == 302
|
91
103
|
assert ogc_server.description == "new_description"
|
92
104
|
|
105
|
+
log = dbsession.query(Log).one()
|
106
|
+
assert log.date != None
|
107
|
+
assert log.action == LogAction.UPDATE
|
108
|
+
assert log.element_type == "ogc_server"
|
109
|
+
assert log.element_id == ogc_server.id
|
110
|
+
assert log.element_name == ogc_server.name
|
111
|
+
assert log.username == "test_user"
|
112
|
+
|
93
113
|
def test_delete(self, test_app, ogc_server_test_data, dbsession):
|
94
|
-
from c2cgeoportal_commons.models.main import OGCServer
|
114
|
+
from c2cgeoportal_commons.models.main import Log, LogAction, OGCServer
|
95
115
|
|
96
116
|
ogc_server = ogc_server_test_data["ogc_servers"][0]
|
97
|
-
|
98
|
-
|
99
|
-
|
117
|
+
test_app.delete(f"/admin/ogc_servers/{ogc_server.id}", status=200)
|
118
|
+
assert dbsession.query(OGCServer).get(ogc_server.id) is None
|
119
|
+
|
120
|
+
log = dbsession.query(Log).one()
|
121
|
+
assert log.date != None
|
122
|
+
assert log.action == LogAction.DELETE
|
123
|
+
assert log.element_type == "ogc_server"
|
124
|
+
assert log.element_id == ogc_server.id
|
125
|
+
assert log.element_name == ogc_server.name
|
126
|
+
assert log.username == "test_user"
|
100
127
|
|
101
128
|
def test_duplicate(self, ogc_server_test_data, test_app, dbsession):
|
102
129
|
from c2cgeoportal_commons.models.main import OGCServer
|
103
130
|
|
104
131
|
ogc_server = ogc_server_test_data["ogc_servers"][3]
|
105
|
-
resp = test_app.get("/admin/ogc_servers/{}/duplicate"
|
132
|
+
resp = test_app.get(f"/admin/ogc_servers/{ogc_server.id}/duplicate", status=200)
|
106
133
|
form = resp.form
|
107
134
|
assert "" == self.get_first_field_named(form, "id").value
|
108
135
|
self.set_first_field_named(form, "name", "clone")
|
109
|
-
|
136
|
+
with patch("c2cgeoportal_admin.views.ogc_servers.OGCServerViews._update_cache"):
|
137
|
+
resp = form.submit("submit")
|
110
138
|
assert resp.status_int == 302
|
111
139
|
server = dbsession.query(OGCServer).filter(OGCServer.name == "clone").one()
|
112
140
|
assert str(server.id) == re.match(
|
@@ -115,18 +143,18 @@ class TestOGCServer(AbstractViewsTests):
|
|
115
143
|
|
116
144
|
def test_unicity_validator(self, ogc_server_test_data, test_app):
|
117
145
|
ogc_server = ogc_server_test_data["ogc_servers"][3]
|
118
|
-
resp = test_app.get("/admin/ogc_servers/{}/duplicate"
|
146
|
+
resp = test_app.get(f"/admin/ogc_servers/{ogc_server.id}/duplicate", status=200)
|
119
147
|
|
120
148
|
resp = resp.form.submit("submit")
|
121
149
|
|
122
|
-
self._check_submission_problem(resp, "{} is already used."
|
150
|
+
self._check_submission_problem(resp, f"{ogc_server.name} is already used.")
|
123
151
|
|
124
152
|
def test_check_success(self, ogc_server_test_data, test_app):
|
125
153
|
ogc_server = ogc_server_test_data["ogc_servers"][3]
|
126
154
|
ogc_server.url = "config://mapserver"
|
127
|
-
resp = test_app.get("/admin/ogc_servers/{}/synchronize"
|
155
|
+
resp = test_app.get(f"/admin/ogc_servers/{ogc_server.id}/synchronize", status=200)
|
128
156
|
|
129
|
-
resp = resp.forms["form-check"].submit("
|
157
|
+
resp = resp.forms["form-check"].submit("check")
|
130
158
|
|
131
159
|
assert list(resp.html.find("div", class_="alert-success").stripped_strings) == [
|
132
160
|
"OGC Server has been successfully synchronized."
|
@@ -135,20 +163,41 @@ class TestOGCServer(AbstractViewsTests):
|
|
135
163
|
def test_dry_run_success(self, ogc_server_test_data, test_app):
|
136
164
|
ogc_server = ogc_server_test_data["ogc_servers"][3]
|
137
165
|
ogc_server.url = "config://mapserver"
|
138
|
-
resp = test_app.get("/admin/ogc_servers/{}/synchronize"
|
166
|
+
resp = test_app.get(f"/admin/ogc_servers/{ogc_server.id}/synchronize", status=200)
|
139
167
|
|
140
|
-
resp = resp.forms["form-dry-run"].submit("
|
168
|
+
resp = resp.forms["form-dry-run"].submit("dry-run")
|
141
169
|
|
142
170
|
assert list(resp.html.find("div", class_="alert-success").stripped_strings) == [
|
143
171
|
"OGC Server has been successfully synchronized."
|
144
172
|
]
|
145
173
|
|
146
|
-
def test_synchronize_success(self, ogc_server_test_data, test_app):
|
174
|
+
def test_synchronize_success(self, ogc_server_test_data, test_app, dbsession):
|
175
|
+
from c2cgeoportal_commons.models.main import Log, LogAction
|
176
|
+
|
147
177
|
ogc_server = ogc_server_test_data["ogc_servers"][3]
|
148
178
|
ogc_server.url = "config://mapserver"
|
149
|
-
resp = test_app.get("/admin/ogc_servers/{}/synchronize"
|
179
|
+
resp = test_app.get(f"/admin/ogc_servers/{ogc_server.id}/synchronize", status=200)
|
180
|
+
|
181
|
+
resp = resp.forms["form-synchronize"].submit("synchronize")
|
182
|
+
|
183
|
+
log = dbsession.query(Log).one()
|
184
|
+
assert log.date != None
|
185
|
+
assert log.action == LogAction.SYNCHRONIZE
|
186
|
+
assert log.element_type == "ogc_server"
|
187
|
+
assert log.element_id == ogc_server.id
|
188
|
+
assert log.element_name == ogc_server.name
|
189
|
+
assert log.username == "test_user"
|
190
|
+
|
191
|
+
assert list(resp.html.find("div", class_="alert-success").stripped_strings) == [
|
192
|
+
"OGC Server has been successfully synchronized."
|
193
|
+
]
|
194
|
+
|
195
|
+
form = resp.forms["form-synchronize"]
|
196
|
+
form["force-parents"].checked = True
|
197
|
+
form["force-ordering"].checked = True
|
198
|
+
form["clean"].checked = True
|
150
199
|
|
151
|
-
resp =
|
200
|
+
resp = form.submit("synchronize")
|
152
201
|
|
153
202
|
assert list(resp.html.find("div", class_="alert-success").stripped_strings) == [
|
154
203
|
"OGC Server has been successfully synchronized."
|