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.
Files changed (99) hide show
  1. c2cgeoportal_admin/__init__.py +44 -14
  2. c2cgeoportal_admin/lib/__init__.py +0 -0
  3. c2cgeoportal_admin/lib/lingva_extractor.py +77 -0
  4. c2cgeoportal_admin/lib/ogcserver_synchronizer.py +410 -0
  5. c2cgeoportal_admin/py.typed +0 -0
  6. c2cgeoportal_admin/routes.py +30 -11
  7. c2cgeoportal_admin/schemas/dimensions.py +17 -11
  8. c2cgeoportal_admin/schemas/functionalities.py +60 -22
  9. c2cgeoportal_admin/schemas/interfaces.py +27 -19
  10. c2cgeoportal_admin/schemas/metadata.py +122 -48
  11. c2cgeoportal_admin/schemas/restriction_areas.py +26 -20
  12. c2cgeoportal_admin/schemas/roles.py +13 -7
  13. c2cgeoportal_admin/schemas/treegroup.py +90 -20
  14. c2cgeoportal_admin/schemas/treeitem.py +3 -4
  15. c2cgeoportal_admin/static/layertree.css +26 -4
  16. c2cgeoportal_admin/static/navbar.css +59 -36
  17. c2cgeoportal_admin/static/theme.css +51 -11
  18. c2cgeoportal_admin/subscribers.py +3 -3
  19. c2cgeoportal_admin/templates/404.jinja2 +41 -2
  20. c2cgeoportal_admin/templates/edit.jinja2 +23 -0
  21. c2cgeoportal_admin/templates/home.jinja2 +23 -0
  22. c2cgeoportal_admin/templates/index.jinja2 +23 -0
  23. c2cgeoportal_admin/templates/layertree.jinja2 +55 -11
  24. c2cgeoportal_admin/templates/layout.jinja2 +23 -0
  25. c2cgeoportal_admin/templates/navigation_navbar.jinja2 +56 -0
  26. c2cgeoportal_admin/templates/ogcserver_synchronize.jinja2 +90 -0
  27. c2cgeoportal_admin/templates/widgets/child.pt +35 -3
  28. c2cgeoportal_admin/templates/widgets/children.pt +121 -92
  29. c2cgeoportal_admin/templates/widgets/dimension.pt +23 -0
  30. c2cgeoportal_admin/templates/widgets/dimensions.pt +23 -0
  31. c2cgeoportal_admin/templates/widgets/functionality_fields.pt +51 -0
  32. c2cgeoportal_admin/templates/widgets/layer_fields.pt +23 -0
  33. c2cgeoportal_admin/templates/widgets/layer_group_fields.pt +23 -0
  34. c2cgeoportal_admin/templates/widgets/layer_v1_fields.pt +23 -0
  35. c2cgeoportal_admin/templates/widgets/metadata.pt +30 -1
  36. c2cgeoportal_admin/templates/widgets/metadatas.pt +23 -0
  37. c2cgeoportal_admin/templates/widgets/ogcserver_fields.pt +23 -0
  38. c2cgeoportal_admin/templates/widgets/restriction_area_fields.pt +25 -9
  39. c2cgeoportal_admin/templates/widgets/role_fields.pt +52 -25
  40. c2cgeoportal_admin/templates/widgets/theme_fields.pt +23 -0
  41. c2cgeoportal_admin/templates/widgets/user_fields.pt +23 -0
  42. c2cgeoportal_admin/views/__init__.py +29 -0
  43. c2cgeoportal_admin/views/dimension_layers.py +14 -9
  44. c2cgeoportal_admin/views/functionalities.py +52 -18
  45. c2cgeoportal_admin/views/home.py +5 -5
  46. c2cgeoportal_admin/views/interfaces.py +29 -21
  47. c2cgeoportal_admin/views/layer_groups.py +36 -25
  48. c2cgeoportal_admin/views/layers.py +17 -13
  49. c2cgeoportal_admin/views/layers_cog.py +135 -0
  50. c2cgeoportal_admin/views/layers_vectortiles.py +62 -27
  51. c2cgeoportal_admin/views/layers_wms.py +61 -36
  52. c2cgeoportal_admin/views/layers_wmts.py +54 -32
  53. c2cgeoportal_admin/views/layertree.py +37 -28
  54. c2cgeoportal_admin/views/logged_views.py +83 -0
  55. c2cgeoportal_admin/views/logs.py +91 -0
  56. c2cgeoportal_admin/views/oauth2_clients.py +96 -0
  57. c2cgeoportal_admin/views/ogc_servers.py +192 -21
  58. c2cgeoportal_admin/views/restriction_areas.py +78 -25
  59. c2cgeoportal_admin/views/roles.py +88 -25
  60. c2cgeoportal_admin/views/themes.py +47 -35
  61. c2cgeoportal_admin/views/themes_ordering.py +44 -24
  62. c2cgeoportal_admin/views/treeitems.py +21 -17
  63. c2cgeoportal_admin/views/users.py +46 -26
  64. c2cgeoportal_admin/widgets.py +79 -28
  65. {c2cgeoportal_admin-2.5.0.100.dist-info → c2cgeoportal_admin-2.9rc44.dist-info}/METADATA +15 -13
  66. c2cgeoportal_admin-2.9rc44.dist-info/RECORD +97 -0
  67. {c2cgeoportal_admin-2.5.0.100.dist-info → c2cgeoportal_admin-2.9rc44.dist-info}/WHEEL +1 -1
  68. c2cgeoportal_admin-2.9rc44.dist-info/entry_points.txt +5 -0
  69. tests/__init__.py +36 -27
  70. tests/conftest.py +23 -24
  71. tests/test_edit_url.py +16 -19
  72. tests/test_functionalities.py +52 -14
  73. tests/test_home.py +0 -1
  74. tests/test_interface.py +35 -12
  75. tests/test_layer_groups.py +58 -32
  76. tests/test_layers_cog.py +243 -0
  77. tests/test_layers_vectortiles.py +46 -30
  78. tests/test_layers_wms.py +77 -82
  79. tests/test_layers_wmts.py +51 -30
  80. tests/test_layertree.py +107 -101
  81. tests/test_learn.py +1 -1
  82. tests/test_left_menu.py +0 -1
  83. tests/test_lingva_extractor_config.py +64 -0
  84. tests/test_logs.py +102 -0
  85. tests/test_main.py +4 -2
  86. tests/test_metadatas.py +79 -71
  87. tests/test_oauth2_clients.py +186 -0
  88. tests/test_ogc_servers.py +110 -28
  89. tests/test_restriction_areas.py +109 -20
  90. tests/test_role.py +142 -82
  91. tests/test_themes.py +75 -41
  92. tests/test_themes_ordering.py +1 -2
  93. tests/test_treegroup.py +2 -2
  94. tests/test_user.py +72 -70
  95. tests/themes_ordering.py +1 -2
  96. c2cgeoportal_admin/templates/navigation_vertical.jinja2 +0 -10
  97. c2cgeoportal_admin-2.5.0.100.dist-info/RECORD +0 -84
  98. c2cgeoportal_admin-2.5.0.100.dist-info/entry_points.txt +0 -3
  99. {c2cgeoportal_admin-2.5.0.100.dist-info → c2cgeoportal_admin-2.9rc44.dist-info}/top_level.txt +0 -0
tests/test_metadatas.py CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  import pytest
4
4
 
5
- from . import AbstractViewsTests, skip_if_ci
6
- from .selenium.page import IndexPage
5
+ from . import AbstractViewsTests
7
6
 
8
7
 
9
8
  @pytest.fixture(scope="function")
@@ -11,7 +10,7 @@ from .selenium.page import IndexPage
11
10
  def metadatas_test_data(dbsession, transact):
12
11
  del transact
13
12
 
14
- from c2cgeoportal_commons.models.main import LayerWMS, LayerWMTS, OGCServer, Metadata, Theme, LayerGroup
13
+ from c2cgeoportal_commons.models.main import LayerGroup, LayerWMS, LayerWMTS, Metadata, OGCServer, Theme
15
14
 
16
15
  ogc_server = OGCServer(name="ogc_server")
17
16
 
@@ -60,7 +59,6 @@ def metadatas_test_data(dbsession, transact):
60
59
 
61
60
  @pytest.mark.usefixtures("metadatas_test_data", "test_app")
62
61
  class TestMetadatasView(AbstractViewsTests):
63
-
64
62
  _prefix = "/admin/"
65
63
 
66
64
  def __metadata_ui_types(self):
@@ -77,7 +75,18 @@ class TestMetadatasView(AbstractViewsTests):
77
75
  "string",
78
76
  )
79
77
 
80
- def _check_metadatas(self, test_app, item, metadatas):
78
+ def expected_value(self, test_app, metadata):
79
+ if self.__metadata_ui_type(test_app, metadata.name) == "boolean":
80
+ if metadata.value == "true":
81
+ return True
82
+ if metadata.value == "false":
83
+ return False
84
+ return None
85
+ return metadata.value
86
+
87
+ def _check_metadatas(self, test_app, item, metadatas, model):
88
+ from c2cgeoportal_admin.schemas.metadata import metadata_definitions
89
+
81
90
  settings = test_app.app.registry.settings
82
91
  self._check_sequence(
83
92
  item,
@@ -88,13 +97,14 @@ class TestMetadatasView(AbstractViewsTests):
88
97
  "name": "name",
89
98
  "value": [
90
99
  {"text": s_m["name"], "value": s_m["name"], "selected": s_m["name"] == m.name}
91
- for s_m in sorted(
92
- settings["admin_interface"]["available_metadata"], key=lambda m: m["name"]
93
- )
100
+ for s_m in sorted(metadata_definitions(settings, model), key=lambda m: m["name"])
94
101
  ],
95
102
  "label": "Name",
96
103
  },
97
- {"name": self.__metadata_ui_type(test_app, m.name), "value": m.value},
104
+ {
105
+ "name": self.__metadata_ui_type(test_app, m.name),
106
+ "value": self.expected_value(test_app, m),
107
+ },
98
108
  {"name": "description", "value": m.description, "label": "Description"},
99
109
  ]
100
110
  for m in metadatas
@@ -120,7 +130,7 @@ class TestMetadatasView(AbstractViewsTests):
120
130
  resp = self._post_metadata(test_app, url, base_mapping, name, value, 200)
121
131
  assert (
122
132
  error_msg
123
- == resp.html.select_one(".item-{} .help-block".format(self.__metadata_ui_type(test_app, name)))
133
+ == resp.html.select_one(f".item-{self.__metadata_ui_type(test_app, name)} .help-block")
124
134
  .getText()
125
135
  .strip()
126
136
  )
@@ -144,6 +154,46 @@ class TestMetadatasView(AbstractViewsTests):
144
154
  '"number" is not a number',
145
155
  )
146
156
 
157
+ def test_get_true_boolean_metadata(self, metadatas_test_data, test_app):
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)
162
+
163
+ def test_get_false_boolean_metadata(self, metadatas_test_data, test_app):
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)
168
+
169
+ def test_post_true_boolean_metadata(self, test_app, metadatas_test_data, dbsession):
170
+ from c2cgeoportal_commons.models.main import LayerWMS
171
+
172
+ self._post_metadata(
173
+ test_app,
174
+ "/admin/layers_wms/new",
175
+ self._base_metadata_params(metadatas_test_data),
176
+ "_boolean",
177
+ "true",
178
+ 302,
179
+ )
180
+ layer = dbsession.query(LayerWMS).filter(LayerWMS.name == "new_name").one()
181
+ assert layer.get_metadata("_boolean")[0].value == "true"
182
+
183
+ def test_post_false_boolean_metadata(self, test_app, metadatas_test_data, dbsession):
184
+ from c2cgeoportal_commons.models.main import LayerWMS
185
+
186
+ self._post_metadata(
187
+ test_app,
188
+ "/admin/layers_wms/new",
189
+ self._base_metadata_params(metadatas_test_data),
190
+ "_boolean",
191
+ "false",
192
+ 302,
193
+ )
194
+ layer = dbsession.query(LayerWMS).filter(LayerWMS.name == "new_name").one()
195
+ assert layer.get_metadata("_boolean")[0].value == "false"
196
+
147
197
  def test_valid_float_metadata(self, test_app, metadatas_test_data):
148
198
  self._post_metadata(
149
199
  test_app,
@@ -257,85 +307,43 @@ class TestMetadatasView(AbstractViewsTests):
257
307
  302,
258
308
  )
259
309
 
260
- def _test_edit_treeitem(self, prefix, item, test_app):
261
- resp = self.get(test_app, "{}/{}".format(prefix, item.id))
262
- 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)
263
313
  resp.form.submit("submit", status=302)
264
314
 
265
315
  def test_layer_wms_metadatas(self, metadatas_test_data, test_app):
266
- self._test_edit_treeitem("layers_wms", metadatas_test_data["layer_wms"], test_app)
316
+ from c2cgeoportal_commons.models.main import LayerWMS
317
+
318
+ self._test_edit_treeitem("layers_wms", metadatas_test_data["layer_wms"], test_app, LayerWMS)
267
319
 
268
320
  def test_layer_wmts_metadatas(self, metadatas_test_data, test_app):
269
- self._test_edit_treeitem("layers_wmts", metadatas_test_data["layer_wmts"], test_app)
321
+ from c2cgeoportal_commons.models.main import LayerWMTS
322
+
323
+ self._test_edit_treeitem("layers_wmts", metadatas_test_data["layer_wmts"], test_app, LayerWMTS)
270
324
 
271
325
  def test_theme_metadatas(self, metadatas_test_data, test_app):
272
- self._test_edit_treeitem("themes", metadatas_test_data["theme"], test_app)
326
+ from c2cgeoportal_commons.models.main import Theme
327
+
328
+ self._test_edit_treeitem("themes", metadatas_test_data["theme"], test_app, Theme)
273
329
 
274
330
  def test_group_metadatas(self, metadatas_test_data, test_app):
275
- self._test_edit_treeitem("layer_groups", metadatas_test_data["group"], test_app)
331
+ from c2cgeoportal_commons.models.main import LayerGroup
332
+
333
+ self._test_edit_treeitem("layer_groups", metadatas_test_data["group"], test_app, LayerGroup)
276
334
 
277
335
  def test_undefined_metadata(self, metadatas_test_data, test_app):
278
- """Undefined metadata must be kept intact accross submissions"""
336
+ """
337
+ Undefined metadata must be kept intact across submissions.
338
+ """
279
339
  from c2cgeoportal_commons.models.main import Metadata
280
340
 
281
341
  layer = metadatas_test_data["layer_wms"]
282
342
  layer.metadatas = [Metadata("_undefined", "This is an undefined metadata")]
283
343
 
284
- resp = self.get(test_app, "layers_wms/{}".format(layer.id))
344
+ resp = self.get(test_app, f"layers_wms/{layer.id}")
285
345
  resp.form.submit("submit", status=302)
286
346
 
287
347
  metadata = layer.metadatas[0]
288
348
  assert metadata.name == "_undefined"
289
349
  assert metadata.value == "This is an undefined metadata"
290
-
291
-
292
- @skip_if_ci
293
- @pytest.mark.selenium
294
- @pytest.mark.usefixtures("selenium", "selenium_app", "metadatas_test_data")
295
- class TestMetadatasSelenium:
296
- def test_hidden_type_validator_does_not_take_precedence_over_visible(
297
- self, selenium, selenium_app, metadatas_test_data
298
- ):
299
- layer = metadatas_test_data["layer_wms"]
300
- selenium.get(selenium_app + "/admin/layers_wms/{}".format(layer.id))
301
- selenium.execute_script("window.scrollBy(0,3000)", "")
302
- selenium.find_element_by_xpath(
303
- """//div[contains(., "Metadatas")]
304
- /following-sibling::div[@class="panel-footer"]/a[@href="#"]"""
305
- ).click()
306
- selenium.execute_script("window.scrollBy(0,3000)", "")
307
- selenium.find_elements_by_xpath(
308
- """//div[contains(., "Metadatas")]//label[contains(., "Name")]
309
- /following-sibling::select/option[contains(.,"_int")]"""
310
- )[9].click()
311
- selenium.find_elements_by_xpath('//div[contains(., "Metadatas")]//input[@name="int"]')[9].send_keys(
312
- "AAA"
313
- )
314
-
315
- selenium.find_element_by_id("deformformsubmit").click()
316
-
317
- assert '"AAA" is not a number' == selenium.find_element_by_xpath('//p[@class="help-block"]').text
318
-
319
- selenium.find_elements_by_xpath(
320
- """//div[contains(., "Metadatas")]//label[contains(., "Name")]
321
- /following-sibling::select/option[contains(.,"_color")]"""
322
- )[9].click()
323
- selenium.find_elements_by_xpath('//div[contains(., "Metadatas")]//input[@name="string"]')[
324
- 9
325
- ].send_keys("BBB")
326
-
327
- selenium.find_element_by_id("deformformsubmit").click()
328
-
329
- assert (
330
- "Expecting hex format for color, e.g. #007DCD"
331
- == selenium.find_element_by_xpath('//p[@class="help-block"]').text
332
- )
333
-
334
- # have to check there are no side effects, especially that modifications held at template side
335
- # don't trigger "are you sure you want to leave alert"
336
- layer = metadatas_test_data["layer_wms"]
337
- IndexPage(selenium)
338
- selenium.get(selenium_app + "/admin/layers_wms/{}".format(layer.id))
339
-
340
- selenium.find_element_by_xpath('//a[contains(@href, "roles")]').click()
341
- assert selenium.current_url.endswith("/roles")
@@ -0,0 +1,186 @@
1
+ # pylint: disable=no-self-use,unsubscriptable-object
2
+
3
+ import re
4
+ from uuid import uuid4
5
+
6
+ import pyramid.httpexceptions
7
+ import pytest
8
+ from pyramid.testing import DummyRequest
9
+
10
+ from .test_treegroup import TestTreeGroup
11
+
12
+
13
+ @pytest.fixture(scope="function")
14
+ @pytest.mark.usefixtures("dbsession", "transact")
15
+ def oauth2_clients_test_data(dbsession, transact):
16
+ del transact
17
+
18
+ from c2cgeoportal_commons.models.static import OAuth2Client
19
+
20
+ clients = []
21
+ for i in range(23):
22
+ client = OAuth2Client()
23
+ client.client_id = str(uuid4())
24
+ client.secret = "1234"
25
+ client.redirect_uri = "http://127.0.0.1:7070/"
26
+
27
+ dbsession.add(client)
28
+ clients.append(client)
29
+
30
+ dbsession.flush()
31
+
32
+ yield {
33
+ "oauth2_clients": clients,
34
+ }
35
+
36
+
37
+ @pytest.mark.usefixtures("oauth2_clients_test_data", "test_app")
38
+ class TestOAuth2Client(TestTreeGroup):
39
+ _prefix = "/admin/oauth2_clients"
40
+
41
+ def test_index_rendering(self, test_app):
42
+ resp = self.get(test_app)
43
+
44
+ self.check_left_menu(resp, "OAuth2 Clients")
45
+
46
+ expected = [
47
+ ("actions", "", "false"),
48
+ ("id", "id", "true"),
49
+ ("client_id", "Client ID"),
50
+ ("secret", "Secret"),
51
+ ("redirect_uri", "Redirect URI"),
52
+ ]
53
+ self.check_grid_headers(resp, expected)
54
+
55
+ def test_grid_search(self, test_app, oauth2_clients_test_data):
56
+ self.check_search(test_app, "", total=23)
57
+
58
+ client = oauth2_clients_test_data["oauth2_clients"][0]
59
+ self.check_search(test_app, client.client_id, total=1)
60
+
61
+ def test_submit_new(self, dbsession, test_app, oauth2_clients_test_data):
62
+ from c2cgeoportal_commons.models.main import LogAction
63
+ from c2cgeoportal_commons.models.static import Log, OAuth2Client
64
+
65
+ resp = test_app.post(
66
+ "/admin/oauth2_clients/new",
67
+ (
68
+ ("_charset_", "UTF-8"),
69
+ ("__formid__", "deform"),
70
+ ("id", ""),
71
+ ("client_id", "qgis2"),
72
+ ("secret", "12345"),
73
+ ("redirect_uri", "http://127.0.0.1:7070/bis"),
74
+ ("formsubmit", "formsubmit"),
75
+ ),
76
+ status=302,
77
+ )
78
+
79
+ oauth2_client = dbsession.query(OAuth2Client).filter(OAuth2Client.client_id == "qgis2").one()
80
+ assert str(oauth2_client.id) == re.match(
81
+ r"http://localhost/admin/oauth2_clients/(.*)\?msg_col=submit_ok", resp.location
82
+ ).group(1)
83
+
84
+ assert oauth2_client.client_id == "qgis2"
85
+ assert oauth2_client.secret == "12345"
86
+ assert oauth2_client.redirect_uri == "http://127.0.0.1:7070/bis"
87
+
88
+ log = dbsession.query(Log).one()
89
+ assert log.date != None
90
+ assert log.action == LogAction.INSERT
91
+ assert log.element_type == "oauth2_client"
92
+ assert log.element_id == oauth2_client.id
93
+ assert log.element_name == oauth2_client.client_id
94
+ assert log.username == "test_user"
95
+
96
+ def test_edit_then_save(self, dbsession, test_app, oauth2_clients_test_data):
97
+ from c2cgeoportal_commons.models.main import LogAction
98
+ from c2cgeoportal_commons.models.static import Log
99
+
100
+ oauth2_client = oauth2_clients_test_data["oauth2_clients"][10]
101
+
102
+ dbsession.expire(oauth2_client)
103
+
104
+ form = self.get_item(test_app, oauth2_client.id).form
105
+
106
+ assert str(oauth2_client.id) == form["id"].value
107
+ assert oauth2_client.client_id == form["client_id"].value
108
+ assert oauth2_client.secret == form["secret"].value
109
+ assert oauth2_client.redirect_uri == form["redirect_uri"].value
110
+
111
+ form["client_id"] = "New client ID"
112
+ form["secret"] = "New secret"
113
+ form["redirect_uri"] = "New redirect URI"
114
+
115
+ resp = form.submit("submit")
116
+
117
+ assert str(oauth2_client.id) == re.match(
118
+ r"http://localhost/admin/oauth2_clients/(.*)\?msg_col=submit_ok", resp.location
119
+ ).group(1)
120
+
121
+ dbsession.expire(oauth2_client)
122
+
123
+ assert "New client ID" == oauth2_client.client_id
124
+ assert "New secret" == oauth2_client.secret
125
+ assert "New redirect URI" == oauth2_client.redirect_uri
126
+
127
+ log = dbsession.query(Log).one()
128
+ assert log.date != None
129
+ assert log.action == LogAction.UPDATE
130
+ assert log.element_type == "oauth2_client"
131
+ assert log.element_id == oauth2_client.id
132
+ assert log.element_name == oauth2_client.client_id
133
+ assert log.username == "test_user"
134
+
135
+ def test_duplicate(self, oauth2_clients_test_data, test_app, dbsession):
136
+ from c2cgeoportal_commons.models.static import OAuth2Client
137
+
138
+ oauth2_client_proto = oauth2_clients_test_data["oauth2_clients"][7]
139
+
140
+ resp = test_app.get(f"/admin/oauth2_clients/{oauth2_client_proto.id}/duplicate", status=200)
141
+ form = resp.form
142
+
143
+ assert "" == self.get_first_field_named(form, "id").value
144
+ assert oauth2_client_proto.client_id == form["client_id"].value
145
+ assert oauth2_client_proto.secret == form["secret"].value
146
+ assert oauth2_client_proto.redirect_uri == form["redirect_uri"].value
147
+ form["client_id"].value = "clone"
148
+ resp = form.submit("submit")
149
+
150
+ oauth2_client = dbsession.query(OAuth2Client).filter(OAuth2Client.client_id == "clone").one()
151
+ assert str(oauth2_client.id) == re.match(
152
+ r"http://localhost/admin/oauth2_clients/(.*)\?msg_col=submit_ok", resp.location
153
+ ).group(1)
154
+ assert oauth2_client_proto.id != oauth2_client.id
155
+
156
+ def test_delete(self, test_app, dbsession):
157
+ from c2cgeoportal_commons.models.main import LogAction
158
+ from c2cgeoportal_commons.models.static import Log, OAuth2Client
159
+
160
+ oauth2_client = dbsession.query(OAuth2Client).first()
161
+ test_app.delete(f"/admin/oauth2_clients/{oauth2_client.id}", status=200)
162
+ assert dbsession.query(OAuth2Client).get(oauth2_client.id) is None
163
+
164
+ log = dbsession.query(Log).one()
165
+ assert log.date != None
166
+ assert log.action == LogAction.DELETE
167
+ assert log.element_type == "oauth2_client"
168
+ assert log.element_id == oauth2_client.id
169
+ assert log.element_name == oauth2_client.client_id
170
+ assert log.username == "test_user"
171
+
172
+ def test_unicity_validator(self, oauth2_clients_test_data, test_app):
173
+ oauth2_client_proto = oauth2_clients_test_data["oauth2_clients"][7]
174
+ resp = test_app.get(f"/admin/oauth2_clients/{oauth2_client_proto.id}/duplicate", status=200)
175
+
176
+ resp = resp.form.submit("submit")
177
+
178
+ self._check_submission_problem(resp, f"{oauth2_client_proto.client_id} is already used.")
179
+
180
+ @pytest.mark.usefixtures("raise_db_error_on_query")
181
+ def test_grid_dberror(self, dbsession):
182
+ from c2cgeoportal_admin.views.oauth2_clients import OAuth2ClientViews
183
+
184
+ request = DummyRequest(dbsession=dbsession, params={"offset": 0, "limit": 10})
185
+ with pytest.raises(pyramid.httpexceptions.HTTPInternalServerError):
186
+ OAuth2ClientViews(request).grid()
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_{}".format(i), description="description_{}".format(i))
21
- server.url = "https://somebasicurl_{}.com".format(i)
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
- resp = test_app.post(
65
- "/admin/ogc_servers/new",
66
- {
67
- "name": "new_name",
68
- "description": "new description",
69
- "url": "www.randomurl.com",
70
- "type": "mapserver",
71
- "auth": "No auth",
72
- "image_type": "image/png",
73
- },
74
- status=302,
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
- def test_edit(self, test_app, ogc_server_test_data):
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/{}".format(ogc_server.id), status=200)
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
- assert form.submit().status_int == 302
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
- deleted_id = ogc_server.id
98
- test_app.delete("/admin/ogc_servers/{}".format(deleted_id), status=200)
99
- assert dbsession.query(OGCServer).get(deleted_id) is None
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".format(ogc_server.id), status=200)
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
- resp = form.submit("submit")
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,8 +143,62 @@ 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".format(ogc_server.id), status=200)
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.".format(ogc_server.name))
150
+ self._check_submission_problem(resp, f"{ogc_server.name} is already used.")
151
+
152
+ def test_check_success(self, ogc_server_test_data, test_app):
153
+ ogc_server = ogc_server_test_data["ogc_servers"][3]
154
+ ogc_server.url = "config://mapserver"
155
+ resp = test_app.get(f"/admin/ogc_servers/{ogc_server.id}/synchronize", status=200)
156
+
157
+ resp = resp.forms["form-check"].submit("check")
158
+
159
+ assert list(resp.html.find("div", class_="alert-success").stripped_strings) == [
160
+ "OGC Server has been successfully synchronized."
161
+ ]
162
+
163
+ def test_dry_run_success(self, ogc_server_test_data, test_app):
164
+ ogc_server = ogc_server_test_data["ogc_servers"][3]
165
+ ogc_server.url = "config://mapserver"
166
+ resp = test_app.get(f"/admin/ogc_servers/{ogc_server.id}/synchronize", status=200)
167
+
168
+ resp = resp.forms["form-dry-run"].submit("dry-run")
169
+
170
+ assert list(resp.html.find("div", class_="alert-success").stripped_strings) == [
171
+ "OGC Server has been successfully synchronized."
172
+ ]
173
+
174
+ def test_synchronize_success(self, ogc_server_test_data, test_app, dbsession):
175
+ from c2cgeoportal_commons.models.main import Log, LogAction
176
+
177
+ ogc_server = ogc_server_test_data["ogc_servers"][3]
178
+ ogc_server.url = "config://mapserver"
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
199
+
200
+ resp = form.submit("synchronize")
201
+
202
+ assert list(resp.html.find("div", class_="alert-success").stripped_strings) == [
203
+ "OGC Server has been successfully synchronized."
204
+ ]