c2cgeoportal-admin 2.6.0__py3-none-any.whl → 2.7.1.156__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 (71) hide show
  1. c2cgeoportal_admin/__init__.py +17 -10
  2. c2cgeoportal_admin/lib/lingua_extractor.py +77 -0
  3. c2cgeoportal_admin/lib/ogcserver_synchronizer.py +166 -54
  4. c2cgeoportal_admin/py.typed +0 -0
  5. c2cgeoportal_admin/routes.py +4 -3
  6. c2cgeoportal_admin/schemas/dimensions.py +12 -10
  7. c2cgeoportal_admin/schemas/functionalities.py +62 -21
  8. c2cgeoportal_admin/schemas/interfaces.py +22 -18
  9. c2cgeoportal_admin/schemas/metadata.py +99 -46
  10. c2cgeoportal_admin/schemas/restriction_areas.py +21 -19
  11. c2cgeoportal_admin/schemas/roles.py +7 -5
  12. c2cgeoportal_admin/schemas/treegroup.py +37 -16
  13. c2cgeoportal_admin/schemas/treeitem.py +2 -3
  14. c2cgeoportal_admin/static/layertree.css +3 -4
  15. c2cgeoportal_admin/static/navbar.css +36 -35
  16. c2cgeoportal_admin/static/theme.css +16 -9
  17. c2cgeoportal_admin/subscribers.py +3 -3
  18. c2cgeoportal_admin/templates/layertree.jinja2 +31 -9
  19. c2cgeoportal_admin/templates/navigation_navbar.jinja2 +33 -0
  20. c2cgeoportal_admin/templates/ogcserver_synchronize.jinja2 +12 -0
  21. c2cgeoportal_admin/templates/widgets/functionality_fields.pt +51 -0
  22. c2cgeoportal_admin/templates/widgets/metadata.pt +7 -1
  23. c2cgeoportal_admin/views/dimension_layers.py +7 -6
  24. c2cgeoportal_admin/views/functionalities.py +31 -5
  25. c2cgeoportal_admin/views/home.py +5 -5
  26. c2cgeoportal_admin/views/interfaces.py +5 -7
  27. c2cgeoportal_admin/views/layer_groups.py +9 -11
  28. c2cgeoportal_admin/views/layers.py +8 -7
  29. c2cgeoportal_admin/views/layers_vectortiles.py +30 -10
  30. c2cgeoportal_admin/views/layers_wms.py +39 -35
  31. c2cgeoportal_admin/views/layers_wmts.py +39 -35
  32. c2cgeoportal_admin/views/layertree.py +35 -27
  33. c2cgeoportal_admin/views/oauth2_clients.py +26 -21
  34. c2cgeoportal_admin/views/ogc_servers.py +57 -29
  35. c2cgeoportal_admin/views/restriction_areas.py +11 -10
  36. c2cgeoportal_admin/views/roles.py +14 -11
  37. c2cgeoportal_admin/views/themes.py +15 -14
  38. c2cgeoportal_admin/views/themes_ordering.py +13 -8
  39. c2cgeoportal_admin/views/treeitems.py +12 -11
  40. c2cgeoportal_admin/views/users.py +7 -5
  41. c2cgeoportal_admin/widgets.py +17 -14
  42. {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.7.1.156.dist-info}/METADATA +15 -12
  43. c2cgeoportal_admin-2.7.1.156.dist-info/RECORD +92 -0
  44. {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.7.1.156.dist-info}/WHEEL +1 -1
  45. c2cgeoportal_admin-2.7.1.156.dist-info/entry_points.txt +5 -0
  46. tests/__init__.py +9 -9
  47. tests/conftest.py +2 -1
  48. tests/test_edit_url.py +11 -13
  49. tests/test_functionalities.py +23 -10
  50. tests/test_interface.py +7 -7
  51. tests/test_layer_groups.py +13 -17
  52. tests/test_layers_vectortiles.py +11 -13
  53. tests/test_layers_wms.py +25 -36
  54. tests/test_layers_wmts.py +15 -19
  55. tests/test_layertree.py +99 -15
  56. tests/test_lingua_extractor_config.py +66 -0
  57. tests/test_main.py +3 -1
  58. tests/test_metadatas.py +34 -20
  59. tests/test_oauth2_clients.py +4 -4
  60. tests/test_ogc_servers.py +21 -10
  61. tests/test_restriction_areas.py +10 -12
  62. tests/test_role.py +37 -35
  63. tests/test_themes.py +40 -33
  64. tests/test_themes_ordering.py +1 -1
  65. tests/test_treegroup.py +2 -2
  66. tests/test_user.py +15 -13
  67. tests/themes_ordering.py +1 -1
  68. c2cgeoportal_admin/templates/navigation_vertical.jinja2 +0 -33
  69. c2cgeoportal_admin-2.6.0.dist-info/RECORD +0 -89
  70. c2cgeoportal_admin-2.6.0.dist-info/entry_points.txt +0 -3
  71. {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.7.1.156.dist-info}/top_level.txt +0 -0
tests/test_layers_wms.py CHANGED
@@ -14,16 +14,16 @@ def layer_wms_test_data(dbsession, transact):
14
14
 
15
15
  from c2cgeoportal_commons.models.main import LayerWMS, OGCServer
16
16
 
17
- servers = [OGCServer(name="server_{}".format(i)) for i in range(0, 4)]
17
+ servers = [OGCServer(name=f"server_{i}") for i in range(0, 4)]
18
18
  for i, server in enumerate(servers):
19
- server.url = "http://wms.geo.admin.ch_{}".format(i)
19
+ server.url = f"http://wms.geo.admin.ch_{i}"
20
20
  server.image_type = "image/jpeg" if i % 2 == 0 else "image/png"
21
21
 
22
22
  def layer_builder(i):
23
- layer = LayerWMS(name="layer_wms_{}".format(i))
24
- layer.layer = "layer_{}".format(i)
23
+ layer = LayerWMS(name=f"layer_wms_{i}")
24
+ layer.layer = f"layer_{i}"
25
25
  layer.public = 1 == i % 2
26
- layer.geo_table = "geotable_{}".format(i)
26
+ layer.geo_table = f"geotable_{i}"
27
27
  layer.ogc_server = servers[i % 4]
28
28
  layer.style = "décontrasté"
29
29
  return layer
@@ -173,11 +173,11 @@ class TestLayerWMSViews(AbstractViewsTests):
173
173
  assert str(layer.time_widget) == form["time_widget"].value
174
174
 
175
175
  interfaces = layer_wms_test_data["interfaces"]
176
- assert set((interfaces[0].id, interfaces[2].id)) == set(i.id for i in layer.interfaces)
176
+ assert {interfaces[0].id, interfaces[2].id} == {i.id for i in layer.interfaces}
177
177
  self._check_interfaces(form, interfaces, layer)
178
178
 
179
179
  ras = layer_wms_test_data["restrictionareas"]
180
- assert set((ras[0].id, ras[2].id)) == set(i.id for i in layer.restrictionareas)
180
+ assert {ras[0].id, ras[2].id} == {i.id for i in layer.restrictionareas}
181
181
  self._check_restrictionsareas(form, ras, layer)
182
182
 
183
183
  new_values = {
@@ -200,7 +200,7 @@ class TestLayerWMSViews(AbstractViewsTests):
200
200
 
201
201
  resp = form.submit("submit")
202
202
  assert str(layer.id) == re.match(
203
- r"http://localhost{}/(.*)\?msg_col=submit_ok".format(self._prefix), resp.location
203
+ rf"http://localhost{self._prefix}/(.*)\?msg_col=submit_ok", resp.location
204
204
  ).group(1)
205
205
 
206
206
  dbsession.expire(layer)
@@ -209,10 +209,8 @@ class TestLayerWMSViews(AbstractViewsTests):
209
209
  assert value == getattr(layer, key)
210
210
  else:
211
211
  assert str(value or "") == str(getattr(layer, key) or "")
212
- assert set([interfaces[1].id, interfaces[3].id]) == set(
213
- [interface.id for interface in layer.interfaces]
214
- )
215
- assert set([ras[1].id, ras[3].id]) == set([ra.id for ra in layer.restrictionareas])
212
+ assert {interfaces[1].id, interfaces[3].id} == {interface.id for interface in layer.interfaces}
213
+ assert {ras[1].id, ras[3].id} == {ra.id for ra in layer.restrictionareas}
216
214
 
217
215
  def test_submit_new(self, dbsession, test_app, layer_wms_test_data):
218
216
  from c2cgeoportal_commons.models.main import LayerWMS
@@ -244,7 +242,7 @@ class TestLayerWMSViews(AbstractViewsTests):
244
242
 
245
243
  layer = layer_wms_test_data["layers"][3]
246
244
 
247
- resp = test_app.get("/admin/layers_wms/{}/duplicate".format(layer.id), status=200)
245
+ resp = test_app.get(f"/admin/layers_wms/{layer.id}/duplicate", status=200)
248
246
  form = resp.form
249
247
 
250
248
  assert "" == self.get_first_field_named(form, "id").value
@@ -260,11 +258,11 @@ class TestLayerWMSViews(AbstractViewsTests):
260
258
  assert str(layer.time_mode) == form["time_mode"].value
261
259
  assert str(layer.time_widget) == form["time_widget"].value
262
260
  interfaces = layer_wms_test_data["interfaces"]
263
- assert set((interfaces[3].id, interfaces[1].id)) == set(i.id for i in layer.interfaces)
261
+ assert {interfaces[3].id, interfaces[1].id} == {i.id for i in layer.interfaces}
264
262
  self._check_interfaces(form, interfaces, layer)
265
263
 
266
264
  ras = layer_wms_test_data["restrictionareas"]
267
- assert set((ras[3].id, ras[0].id)) == set(i.id for i in layer.restrictionareas)
265
+ assert {ras[3].id, ras[0].id} == {i.id for i in layer.restrictionareas}
268
266
  self._check_restrictionsareas(form, ras, layer)
269
267
 
270
268
  self._check_dimensions(resp.html, layer.dimensions, duplicated=True)
@@ -289,12 +287,9 @@ class TestLayerWMSViews(AbstractViewsTests):
289
287
  assert 0 == dbsession.query(LayerWMTS).filter(LayerWMTS.name == layer.name).count()
290
288
  assert 1 == dbsession.query(LayerWMS).filter(LayerWMS.name == layer.name).count()
291
289
 
292
- resp = test_app.post("/admin/layers_wms/{}/convert_to_wmts".format(layer.id), status=200)
290
+ resp = test_app.post(f"/admin/layers_wms/{layer.id}/convert_to_wmts", status=200)
293
291
  assert resp.json["success"]
294
- assert (
295
- "http://localhost/admin/layers_wmts/{}?msg_col=submit_ok".format(layer.id)
296
- == resp.json["redirect"]
297
- )
292
+ assert f"http://localhost/admin/layers_wmts/{layer.id}?msg_col=submit_ok" == resp.json["redirect"]
298
293
 
299
294
  assert 1 == dbsession.query(LayerWMTS).filter(LayerWMTS.name == layer.name).count()
300
295
  assert 0 == dbsession.query(LayerWMS).filter(LayerWMS.name == layer.name).count()
@@ -328,23 +323,17 @@ class TestLayerWMSViews(AbstractViewsTests):
328
323
  def test_convert_image_type_from_ogcserver(self, layer_wms_test_data, test_app):
329
324
  layer = layer_wms_test_data["layers"][3]
330
325
 
331
- resp = test_app.post("/admin/layers_wms/{}/convert_to_wmts".format(layer.id), status=200)
326
+ resp = test_app.post(f"/admin/layers_wms/{layer.id}/convert_to_wmts", status=200)
332
327
  assert resp.json["success"]
333
- assert (
334
- "http://localhost/admin/layers_wmts/{}?msg_col=submit_ok".format(layer.id)
335
- == resp.json["redirect"]
336
- )
328
+ assert f"http://localhost/admin/layers_wmts/{layer.id}?msg_col=submit_ok" == resp.json["redirect"]
337
329
 
338
330
  resp = test_app.get(resp.json["redirect"], status=200)
339
331
  assert "image/png" == resp.form["image_type"].value
340
332
 
341
333
  layer = layer_wms_test_data["layers"][2]
342
- resp = test_app.post("/admin/layers_wms/{}/convert_to_wmts".format(layer.id), status=200)
334
+ resp = test_app.post(f"/admin/layers_wms/{layer.id}/convert_to_wmts", status=200)
343
335
  assert resp.json["success"]
344
- assert (
345
- "http://localhost/admin/layers_wmts/{}?msg_col=submit_ok".format(layer.id)
346
- == resp.json["redirect"]
347
- )
336
+ assert f"http://localhost/admin/layers_wmts/{layer.id}?msg_col=submit_ok" == resp.json["redirect"]
348
337
 
349
338
  resp = test_app.get(resp.json["redirect"], status=200)
350
339
  assert "image/jpeg" == resp.form["image_type"].value
@@ -354,15 +343,15 @@ class TestLayerWMSViews(AbstractViewsTests):
354
343
 
355
344
  dbsession.delete(LayerWMTS.get_default(dbsession))
356
345
  layer = layer_wms_test_data["layers"][3]
357
- test_app.post("/admin/layers_wms/{}/convert_to_wmts".format(layer.id), status=200)
346
+ test_app.post(f"/admin/layers_wms/{layer.id}/convert_to_wmts", status=200)
358
347
 
359
348
  def test_unicity_validator(self, layer_wms_test_data, test_app):
360
349
  layer = layer_wms_test_data["layers"][2]
361
- resp = test_app.get("/admin/layers_wms/{}/duplicate".format(layer.id), status=200)
350
+ resp = test_app.get(f"/admin/layers_wms/{layer.id}/duplicate", status=200)
362
351
 
363
352
  resp = resp.form.submit("submit")
364
353
 
365
- self._check_submission_problem(resp, "{} is already used.".format(layer.name))
354
+ self._check_submission_problem(resp, f"{layer.name} is already used.")
366
355
 
367
356
  def test_unicity_validator_does_not_matter_amongst_cousin(self, layer_wms_test_data, test_app, dbsession):
368
357
  from c2cgeoportal_commons.models.main import LayerGroup, LayerWMS
@@ -372,7 +361,7 @@ class TestLayerWMSViews(AbstractViewsTests):
372
361
  assert dbsession.query(LayerWMS).filter(LayerWMS.name == "layer_group_0").one_or_none() is None
373
362
 
374
363
  layer = layer_wms_test_data["layers"][2]
375
- resp = test_app.get("/admin/layers_wms/{}/duplicate".format(layer.id), status=200)
364
+ resp = test_app.get(f"/admin/layers_wms/{layer.id}/duplicate", status=200)
376
365
  self.set_first_field_named(resp.form, "name", "layer_group_0")
377
366
  resp = resp.form.submit("submit")
378
367
 
@@ -386,7 +375,7 @@ class TestLayerWMSViews(AbstractViewsTests):
386
375
 
387
376
  layer_id = dbsession.query(LayerWMS.id).first().id
388
377
 
389
- test_app.delete("/admin/layers_wms/{}".format(layer_id), status=200)
378
+ test_app.delete(f"/admin/layers_wms/{layer_id}", status=200)
390
379
 
391
380
  assert dbsession.query(LayerWMS).get(layer_id) is None
392
381
  assert dbsession.query(Layer).get(layer_id) is None
@@ -417,5 +406,5 @@ class TestLayerWMSViews(AbstractViewsTests):
417
406
  "Errors have been highlighted below" == resp.html.select_one('div[class="error-msg-detail"]').text
418
407
  )
419
408
  assert ["WMS layer name"] == sorted(
420
- [(x.select_one("label").text.strip()) for x in resp.html.select("[class~='has-error']")]
409
+ (x.select_one("label").text.strip()) for x in resp.html.select("[class~='has-error']")
421
410
  )
tests/test_layers_wmts.py CHANGED
@@ -19,12 +19,12 @@ def layer_wmts_test_data(dbsession, transact):
19
19
  server.image_type = "image/png"
20
20
 
21
21
  def layer_builder(i):
22
- name = "layer_wmts_{}".format(i)
22
+ name = f"layer_wmts_{i}"
23
23
  layer = LayerWMTS(name=name)
24
24
  layer.layer = name
25
- layer.url = "https:///wms.geo.admin.ch_{}.org?service=wms&request=GetCapabilities".format(i)
25
+ layer.url = f"https:///wms.geo.admin.ch_{i}.org?service=wms&request=GetCapabilities"
26
26
  layer.public = 1 == i % 2
27
- layer.geo_table = "geotable_{}".format(i)
27
+ layer.geo_table = f"geotable_{i}"
28
28
  layer.image_type = "image/jpeg"
29
29
  layer.style = "décontrasté"
30
30
  return layer
@@ -121,11 +121,11 @@ class TestLayerWMTS(AbstractViewsTests):
121
121
  assert str(layer.image_type or "") == form["image_type"].value
122
122
 
123
123
  interfaces = layer_wmts_test_data["interfaces"]
124
- assert set((interfaces[0].id, interfaces[2].id)) == set(i.id for i in layer.interfaces)
124
+ assert {interfaces[0].id, interfaces[2].id} == {i.id for i in layer.interfaces}
125
125
  self._check_interfaces(form, interfaces, layer)
126
126
 
127
127
  ras = layer_wmts_test_data["restrictionareas"]
128
- assert set((ras[0].id, ras[2].id)) == set(i.id for i in layer.restrictionareas)
128
+ assert {ras[0].id, ras[2].id} == {i.id for i in layer.restrictionareas}
129
129
  self._check_restrictionsareas(form, ras, layer)
130
130
 
131
131
  new_values = {
@@ -148,7 +148,7 @@ class TestLayerWMTS(AbstractViewsTests):
148
148
 
149
149
  resp = form.submit("submit")
150
150
  assert str(layer.id) == re.match(
151
- r"http://localhost{}/(.*)\?msg_col=submit_ok".format(self._prefix), resp.location
151
+ rf"http://localhost{self._prefix}/(.*)\?msg_col=submit_ok", resp.location
152
152
  ).group(1)
153
153
 
154
154
  dbsession.expire(layer)
@@ -157,17 +157,15 @@ class TestLayerWMTS(AbstractViewsTests):
157
157
  assert value == getattr(layer, key)
158
158
  else:
159
159
  assert str(value or "") == str(getattr(layer, key) or "")
160
- assert set([interfaces[1].id, interfaces[3].id]) == set(
161
- [interface.id for interface in layer.interfaces]
162
- )
163
- assert set([ras[1].id, ras[3].id]) == set([ra.id for ra in layer.restrictionareas])
160
+ assert {interfaces[1].id, interfaces[3].id} == {interface.id for interface in layer.interfaces}
161
+ assert {ras[1].id, ras[3].id} == {ra.id for ra in layer.restrictionareas}
164
162
 
165
163
  def test_duplicate(self, layer_wmts_test_data, test_app, dbsession):
166
164
  from c2cgeoportal_commons.models.main import LayerWMTS
167
165
 
168
166
  layer = layer_wmts_test_data["layers"][3]
169
167
 
170
- resp = test_app.get("/admin/layers_wmts/{}/duplicate".format(layer.id), status=200)
168
+ resp = test_app.get(f"/admin/layers_wmts/{layer.id}/duplicate", status=200)
171
169
  form = resp.form
172
170
 
173
171
  assert "" == self.get_first_field_named(form, "id").value
@@ -196,7 +194,7 @@ class TestLayerWMTS(AbstractViewsTests):
196
194
 
197
195
  layer_id = dbsession.query(LayerWMTS.id).first().id
198
196
 
199
- test_app.delete("/admin/layers_wmts/{}".format(layer_id), status=200)
197
+ test_app.delete(f"/admin/layers_wmts/{layer_id}", status=200)
200
198
 
201
199
  assert dbsession.query(LayerWMTS).get(layer_id) is None
202
200
  assert dbsession.query(Layer).get(layer_id) is None
@@ -204,11 +202,11 @@ class TestLayerWMTS(AbstractViewsTests):
204
202
 
205
203
  def test_unicity_validator(self, layer_wmts_test_data, test_app):
206
204
  layer = layer_wmts_test_data["layers"][2]
207
- resp = test_app.get("/admin/layers_wmts/{}/duplicate".format(layer.id), status=200)
205
+ resp = test_app.get(f"/admin/layers_wmts/{layer.id}/duplicate", status=200)
208
206
 
209
207
  resp = resp.form.submit("submit")
210
208
 
211
- self._check_submission_problem(resp, "{} is already used.".format(layer.name))
209
+ self._check_submission_problem(resp, f"{layer.name} is already used.")
212
210
 
213
211
  def test_convert_common_fields_copied(self, layer_wmts_test_data, test_app, dbsession):
214
212
  from c2cgeoportal_commons.models.main import LayerWMS, LayerWMTS
@@ -218,10 +216,8 @@ class TestLayerWMTS(AbstractViewsTests):
218
216
  assert 0 == dbsession.query(LayerWMS).filter(LayerWMS.name == layer.name).count()
219
217
  assert 1 == dbsession.query(LayerWMTS).filter(LayerWMTS.name == layer.name).count()
220
218
 
221
- resp = test_app.post("/admin/layers_wmts/{}/convert_to_wms".format(layer.id), status=200)
222
- assert (
223
- "http://localhost/admin/layers_wms/{}?msg_col=submit_ok".format(layer.id) == resp.json["redirect"]
224
- )
219
+ resp = test_app.post(f"/admin/layers_wmts/{layer.id}/convert_to_wms", status=200)
220
+ assert f"http://localhost/admin/layers_wms/{layer.id}?msg_col=submit_ok" == resp.json["redirect"]
225
221
 
226
222
  assert 1 == dbsession.query(LayerWMS).filter(LayerWMS.name == layer.name).count()
227
223
  assert 0 == dbsession.query(LayerWMTS).filter(LayerWMTS.name == layer.name).count()
@@ -256,4 +252,4 @@ class TestLayerWMTS(AbstractViewsTests):
256
252
 
257
253
  dbsession.delete(LayerWMS.get_default(dbsession))
258
254
  layer = layer_wmts_test_data["layers"][3]
259
- test_app.post("/admin/layers_wmts/{}/convert_to_wms".format(layer.id), status=200)
255
+ test_app.post(f"/admin/layers_wmts/{layer.id}/convert_to_wms", status=200)
tests/test_layertree.py CHANGED
@@ -13,6 +13,7 @@ def layertree_test_data(dbsession, transact):
13
13
  del transact
14
14
 
15
15
  from c2cgeoportal_commons.models.main import (
16
+ Interface,
16
17
  LayerGroup,
17
18
  LayergroupTreeitem,
18
19
  LayerWMS,
@@ -21,26 +22,39 @@ def layertree_test_data(dbsession, transact):
21
22
  Theme,
22
23
  )
23
24
 
25
+ interface1 = Interface("interface1")
26
+ dbsession.add(interface1)
27
+ interface2 = Interface("interface2")
28
+ dbsession.add(interface2)
29
+
24
30
  layers_wms = []
25
31
  ogc_server = OGCServer(name="ogc_server")
26
32
  dbsession.add(ogc_server)
27
- for i in range(0, 10):
28
- layer_wms = LayerWMS(name="layer_wms_{}".format(i))
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]
29
39
  layer_wms.ogc_server = ogc_server
30
40
  layers_wms.append(layer_wms)
31
41
  dbsession.add(layer_wms)
32
42
 
33
43
  layers_wmts = []
34
- for i in range(0, 10):
35
- layer_wmts = LayerWMTS(name="layer_wmts_{}".format(i))
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]
36
50
  layer_wmts.url = "http://localhost/wmts"
37
51
  layer_wmts.layer = layer_wmts.name
38
52
  layers_wmts.append(layer_wmts)
39
53
  dbsession.add(layer_wmts)
40
54
 
41
55
  groups = []
42
- for i in range(0, 10):
43
- group = LayerGroup(name="layer_group_{}".format(i))
56
+ for i in range(10):
57
+ group = LayerGroup(name=f"layer_group_{i}")
44
58
  groups.append(group)
45
59
  dbsession.add(group)
46
60
 
@@ -51,10 +65,14 @@ def layertree_test_data(dbsession, transact):
51
65
  dbsession.add(LayergroupTreeitem(group=groups[9], item=groups[8], ordering=3))
52
66
 
53
67
  themes = []
54
- for i in range(0, 5):
55
- theme = Theme(name="theme_{}".format(i))
68
+ for i in range(5):
69
+ theme = Theme(name=f"theme_{i}")
56
70
  themes.append(theme)
57
71
  dbsession.add(theme)
72
+ if i == 1:
73
+ theme.interfaces = [interface1]
74
+ elif i > 1:
75
+ theme.interfaces = [interface1, interface2]
58
76
 
59
77
  dbsession.add(LayergroupTreeitem(group=theme, item=groups[i], ordering=0))
60
78
  dbsession.add(LayergroupTreeitem(group=theme, item=groups[i + 5], ordering=1))
@@ -74,6 +92,7 @@ def layertree_test_data(dbsession, transact):
74
92
  "layers_wms": layers_wms,
75
93
  "layers_wmts": layers_wmts,
76
94
  "ogc_servers": [ogc_server],
95
+ "interfaces": [interface1, interface2],
77
96
  }
78
97
  )
79
98
 
@@ -93,13 +112,13 @@ class TestLayerTreeView(AbstractViewsTests):
93
112
  def check_edit_action(self, test_app, nodes, table, item_id):
94
113
  node = next(n for n in nodes if n["id"] == item_id)
95
114
  action = next(a for a in node["actions"] if a["name"] == "edit")
96
- assert "http://localhost/admin/{}/{}".format(table, item_id) == action["url"]
115
+ assert f"http://localhost/admin/{table}/{item_id}" == action["url"]
97
116
  test_app.get(action["url"], status=200)
98
117
 
99
118
  def check_unlink_action(self, test_app, nodes, group_id, item_id):
100
119
  node = next(n for n in nodes if n["id"] == item_id)
101
120
  action = next(a for a in node["actions"] if a["name"] == "unlink")
102
- assert "http://localhost/admin/layertree/unlink/{}/{}".format(group_id, item_id) == action["url"]
121
+ assert f"http://localhost/admin/layertree/unlink/{group_id}/{item_id}" == action["url"]
103
122
  test_app.delete(action["url"], status=200)
104
123
 
105
124
  def check_translation(self, nodes, item):
@@ -111,7 +130,7 @@ class TestLayerTreeView(AbstractViewsTests):
111
130
  node = next(n for n in nodes if n["id"] == parent_id)
112
131
  action = next(a for a in node["actions"] if a["name"] == action_name)
113
132
  assert label == action["label"]
114
- assert "http://localhost/admin/{}/new?parent_id={}".format(route_table, parent_id) == action["url"]
133
+ assert f"http://localhost/admin/{route_table}/new?parent_id={parent_id}" == action["url"]
115
134
 
116
135
  form = test_app.get(action["url"], status=200).form
117
136
  assert form["parent_id"].value == str(parent_id)
@@ -150,12 +169,26 @@ class TestLayerTreeView(AbstractViewsTests):
150
169
  {"name": "new_name_from_layer_group"},
151
170
  )
152
171
 
153
- def test_groups(self, test_app, layertree_test_data):
172
+ def test_groups(self, test_app, layertree_test_data, dbsession):
154
173
  theme = layertree_test_data["themes"][0]
174
+
175
+ # Invert children order (to test ordering)
176
+ theme.children_relation[0].ordering = 1
177
+ theme.children_relation[1].ordering = 0
178
+ dbsession.flush()
179
+
155
180
  resp = self.get(test_app, "/children?group_id={0}&path=_{0}".format(theme.id), status=200)
156
181
  nodes = resp.json
157
182
  assert 2 == len(nodes)
158
183
 
184
+ # check groups are sorted by ordering
185
+ expected = [
186
+ relation.treeitem.name
187
+ for relation in sorted(theme.children_relation, key=lambda relation: relation.ordering)
188
+ ]
189
+ group_names = [node["name"] for node in nodes]
190
+ assert expected == group_names
191
+
159
192
  group = layertree_test_data["groups"][0]
160
193
  self.check_edit_action(test_app, nodes, "layer_groups", group.id)
161
194
  self.check_unlink_action(test_app, nodes, theme.id, group.id)
@@ -186,15 +219,29 @@ class TestLayerTreeView(AbstractViewsTests):
186
219
  },
187
220
  )
188
221
 
189
- def test_layers(self, test_app, layertree_test_data):
222
+ def test_layers(self, test_app, layertree_test_data, dbsession):
190
223
  theme = layertree_test_data["themes"][0]
191
224
  group = layertree_test_data["groups"][0]
225
+
226
+ # Invert children order (to test ordering)
227
+ group.children_relation[0].ordering = 1
228
+ group.children_relation[1].ordering = 0
229
+ dbsession.flush()
230
+
192
231
  resp = self.get(
193
232
  test_app, "/children?group_id={0}&path=_{1}_{0}".format(group.id, theme.id), status=200
194
233
  )
195
234
  nodes = resp.json
196
235
  assert len(nodes) == 2
197
236
 
237
+ # check layers are sorted by ordering
238
+ expected = [
239
+ relation.treeitem.name
240
+ for relation in sorted(group.children_relation, key=lambda relation: relation.ordering)
241
+ ]
242
+ layer_names = [node["name"] for node in nodes]
243
+ assert expected == layer_names
244
+
198
245
  layer_wms = layertree_test_data["layers_wms"][0]
199
246
  layer_wmts = layertree_test_data["layers_wmts"][0]
200
247
 
@@ -210,7 +257,7 @@ class TestLayerTreeView(AbstractViewsTests):
210
257
  def test_unlink(self, test_app, layertree_test_data, dbsession):
211
258
  group = layertree_test_data["groups"][0]
212
259
  item = layertree_test_data["layers_wms"][0]
213
- test_app.delete("/admin/layertree/unlink/{}/{}".format(group.id, item.id), status=200)
260
+ test_app.delete(f"/admin/layertree/unlink/{group.id}/{item.id}", status=200)
214
261
  dbsession.expire_all()
215
262
  assert item not in group.children
216
263
 
@@ -226,5 +273,42 @@ class TestLayerTreeView(AbstractViewsTests):
226
273
  (layers_wms[1].id, LayerWMS),
227
274
  (groups[1].id, LayerGroup),
228
275
  ):
229
- test_app.delete("/admin/layertree/delete/{}".format(item_id), status=200)
276
+ test_app.delete(f"/admin/layertree/delete/{item_id}", status=200)
230
277
  assert dbsession.query(model).get(item_id) is None
278
+
279
+ @pytest.mark.parametrize(
280
+ "params,expected",
281
+ [
282
+ ({}, ["theme_0", "theme_3", "theme_1", "theme_2", "theme_4"]),
283
+ ({"interface": "interface1"}, ["theme_3", "theme_1", "theme_2", "theme_4"]),
284
+ ({"interface": "interface2"}, ["theme_3", "theme_2", "theme_4"]),
285
+ ],
286
+ )
287
+ def test_themes_interfaces(self, test_app, layertree_test_data, params, expected):
288
+ resp = self.get(test_app, "/children", status=200, params=params)
289
+ nodes = resp.json
290
+ assert expected == [node["name"] for node in nodes if node["item_type"] == "theme"]
291
+
292
+ @pytest.mark.parametrize(
293
+ "interface,index,length",
294
+ [
295
+ (None, 0, 2),
296
+ (None, 1, 2),
297
+ (None, 2, 2),
298
+ ("interface1", 0, 0),
299
+ ("interface1", 1, 2),
300
+ ("interface1", 2, 2),
301
+ ("interface2", 0, 0),
302
+ ("interface2", 1, 0),
303
+ ("interface2", 2, 2),
304
+ ],
305
+ )
306
+ def test_layers_interface(self, test_app, layertree_test_data, interface, index, length):
307
+ theme = layertree_test_data["themes"][index]
308
+ group = layertree_test_data["groups"][index]
309
+ params = {"group_id": group.id, "path": f"_{theme.id}_{group.id}"}
310
+ if interface:
311
+ params["interface"] = interface
312
+ resp = self.get(test_app, "/children", status=200, params=params)
313
+ nodes = resp.json
314
+ assert length == len(nodes)
@@ -0,0 +1,66 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Copyright (c) 2022, Camptocamp SA
4
+ # All rights reserved.
5
+
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+
9
+ # 1. Redistributions of source code must retain the above copyright notice, this
10
+ # list of conditions and the following disclaimer.
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+
26
+ # The views and conclusions contained in the software and documentation are those
27
+ # of the authors and should not be interpreted as representing official policies,
28
+ # either expressed or implied, of the FreeBSD Project.
29
+
30
+ # pylint: disable=missing-docstring
31
+
32
+ from unittest.mock import Mock, mock_open, patch
33
+
34
+ import pytest
35
+ import yaml
36
+ from c2c.template.config import config as configuration
37
+
38
+ from c2cgeoportal_admin.lib.lingua_extractor import GeomapfishConfigExtractor
39
+
40
+ GMF_CONFIG = """
41
+ vars:
42
+ admin_interface:
43
+ available_metadata:
44
+ - name: metadata1
45
+ description: description1
46
+ translate: true
47
+ available_functionalities:
48
+ - name: functionality1
49
+ description: description2
50
+ """
51
+
52
+
53
+ class TestGeomapfishConfigExtractor:
54
+ @patch(
55
+ "c2cgeoportal_admin.lib.lingua_extractor.open",
56
+ mock_open(read_data=GMF_CONFIG),
57
+ )
58
+ def test_extract_config(self):
59
+ extractor = GeomapfishConfigExtractor()
60
+
61
+ options = Mock()
62
+ options.keywords = []
63
+
64
+ messages = list(extractor("config.yaml", options))
65
+
66
+ assert {msg.msgid for msg in messages} == {"description1", "description2"}
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
- """Test dev environment"""
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)