eea.plotly 2.2__tar.gz → 2.3__tar.gz
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.
- {eea_plotly-2.2/eea.plotly.egg-info → eea_plotly-2.3}/PKG-INFO +6 -1
- {eea_plotly-2.2 → eea_plotly-2.3}/docs/HISTORY.txt +5 -0
- eea_plotly-2.3/eea/plotly/tests/test_utils.py +281 -0
- eea_plotly-2.3/eea/plotly/version.txt +1 -0
- {eea_plotly-2.2 → eea_plotly-2.3/eea.plotly.egg-info}/PKG-INFO +6 -1
- {eea_plotly-2.2 → eea_plotly-2.3}/eea.plotly.egg-info/SOURCES.txt +1 -0
- eea_plotly-2.2/eea/plotly/version.txt +0 -1
- {eea_plotly-2.2 → eea_plotly-2.3}/CONTRIBUTING.md +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/MANIFEST.in +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/README.rst +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/docs/LICENSE.GPL +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/docs/LICENSE.txt +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/__init__.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/README.txt +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/__init__.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/behaviors.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/browser/__init__.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/browser/configure.zcml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/browser/controlpanel.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/browser/preview.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/browser/preview_adapter/adapter.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/browser/preview_adapter/soer_miniature.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/browser/pt/visualization_view.pt +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/configure.zcml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/controlpanel.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/deserializer/blocks.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/deserializer/configure.zcml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/deserializer/dxcontent.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/deserializer/dxfields.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/interfaces.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/io_csv.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/io_json.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/__init__.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/bg/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/bg/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/cs/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/cs/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/da/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/da/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/de/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/de/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/eea.pot +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/el/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/el/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/en/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/en/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/es/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/es/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/et/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/et/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/eu/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/eu/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/fi/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/fi/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/fr/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/fr/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/hr/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/hr/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/hu/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/hu/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/is/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/is/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/it/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/it/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/kl/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/kl/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/lt/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/lt/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/lv/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/lv/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/mt/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/mt/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/nl/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/nl/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/no/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/no/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/pl/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/pl/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/plone-manual.pot +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/pt/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/pt/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/pt_BR/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/pt_BR/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/ro/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/ro/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/ru/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/ru/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/sk/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/sk/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/sl/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/sl/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/sv/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/sv/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/tr/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/tr/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/update.sh +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/zh_TW/LC_MESSAGES/eea.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/locales/zh_TW/LC_MESSAGES/plone.po +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/permissions.zcml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/profiles/default/browserlayer.xml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/profiles/default/controlpanel.json +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/profiles/default/controlpanel.xml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/profiles/default/metadata.xml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/profiles/default/registry.xml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/profiles/default/rolemap.xml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/profiles/default/types/visualization.xml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/profiles/default/types.xml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/profiles/uninstall/browserlayer.xml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/profiles/uninstall/controlpanel.xml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/profiles/uninstall/registry.xml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/profiles.zcml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/restapi/__init__.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/restapi/configure.zcml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/restapi/controlpanel/__init__.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/restapi/controlpanel/configure.zcml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/restapi/controlpanel/get.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/restapi/controlpanel/reset.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/restapi/visualization/configure.zcml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/restapi/visualization/get.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/serializer/blocks.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/serializer/configure.zcml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/serializer/dxfields.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/serializer/utils.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/setuphandlers.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/tests/__init__.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/tests/base.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/tests/test_doctests.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/upgrades/__init__.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/upgrades/configure.zcml +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea/plotly/utils.py +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea.plotly.egg-info/dependency_links.txt +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea.plotly.egg-info/entry_points.txt +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea.plotly.egg-info/namespace_packages.txt +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea.plotly.egg-info/not-zip-safe +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea.plotly.egg-info/requires.txt +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/eea.plotly.egg-info/top_level.txt +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/setup.cfg +0 -0
- {eea_plotly-2.2 → eea_plotly-2.3}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: eea.plotly
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3
|
|
4
4
|
Summary: volto-plotlycharts backend support
|
|
5
5
|
Home-page: https://github.com/eea/eea.plotly
|
|
6
6
|
Author: European Environment Agency: IDM2 A-Team
|
|
@@ -145,6 +145,11 @@ EEA_ - European Environment Agency (EU)
|
|
|
145
145
|
Changelog
|
|
146
146
|
=========
|
|
147
147
|
|
|
148
|
+
2.3 - (2026-04-14)
|
|
149
|
+
---------------------------
|
|
150
|
+
* Change: Add unit tests for utils, io_csv, and io_json modules
|
|
151
|
+
[avoinea]
|
|
152
|
+
|
|
148
153
|
2.2 - (2025-11-20)
|
|
149
154
|
---------------------------
|
|
150
155
|
* Change: better handle of backward compatibility, ref #293767
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
2.3 - (2026-04-14)
|
|
5
|
+
---------------------------
|
|
6
|
+
* Change: Add unit tests for utils, io_csv, and io_json modules
|
|
7
|
+
[avoinea]
|
|
8
|
+
|
|
4
9
|
2.2 - (2025-11-20)
|
|
5
10
|
---------------------------
|
|
6
11
|
* Change: better handle of backward compatibility, ref #293767
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"""Unit tests for eea.plotly utility modules
|
|
2
|
+
|
|
3
|
+
These tests cover pure functions that don't require Plone context:
|
|
4
|
+
- utils: setProperty, delProperty, sanitizeVisualization, getLink, getLinkHTML, isExpanded
|
|
5
|
+
- io_csv: CsvWriter, CsvReader
|
|
6
|
+
- io_json: JSONEncoder
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import unittest
|
|
10
|
+
import json
|
|
11
|
+
import decimal
|
|
12
|
+
import io
|
|
13
|
+
|
|
14
|
+
from eea.plotly.utils import (
|
|
15
|
+
setProperty,
|
|
16
|
+
delProperty,
|
|
17
|
+
sanitizeVisualization,
|
|
18
|
+
getLink,
|
|
19
|
+
getLinkHTML,
|
|
20
|
+
isExpanded,
|
|
21
|
+
)
|
|
22
|
+
from eea.plotly.io_csv import CsvWriter, CsvReader, NULL
|
|
23
|
+
from eea.plotly.io_json import JSONEncoder
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class TestSetProperty(unittest.TestCase):
|
|
27
|
+
"""Tests for setProperty function"""
|
|
28
|
+
|
|
29
|
+
def test_set_value_not_none(self):
|
|
30
|
+
obj = {}
|
|
31
|
+
setProperty(obj, "key", "value")
|
|
32
|
+
self.assertEqual(obj["key"], "value")
|
|
33
|
+
|
|
34
|
+
def test_set_value_none(self):
|
|
35
|
+
obj = {}
|
|
36
|
+
setProperty(obj, "key", None)
|
|
37
|
+
self.assertNotIn("key", obj)
|
|
38
|
+
|
|
39
|
+
def test_set_overwrites(self):
|
|
40
|
+
obj = {"key": "old"}
|
|
41
|
+
setProperty(obj, "key", "new")
|
|
42
|
+
self.assertEqual(obj["key"], "new")
|
|
43
|
+
|
|
44
|
+
def test_set_integer(self):
|
|
45
|
+
obj = {}
|
|
46
|
+
setProperty(obj, "count", 42)
|
|
47
|
+
self.assertEqual(obj["count"], 42)
|
|
48
|
+
|
|
49
|
+
def test_set_empty_string(self):
|
|
50
|
+
obj = {}
|
|
51
|
+
setProperty(obj, "key", "")
|
|
52
|
+
self.assertEqual(obj["key"], "")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class TestDelProperty(unittest.TestCase):
|
|
56
|
+
"""Tests for delProperty function"""
|
|
57
|
+
|
|
58
|
+
def test_delete_existing(self):
|
|
59
|
+
obj = {"key": "value"}
|
|
60
|
+
delProperty(obj, "key")
|
|
61
|
+
self.assertNotIn("key", obj)
|
|
62
|
+
|
|
63
|
+
def test_delete_nonexistent(self):
|
|
64
|
+
obj = {}
|
|
65
|
+
delProperty(obj, "key") # should not raise
|
|
66
|
+
|
|
67
|
+
def test_delete_other_keys_preserved(self):
|
|
68
|
+
obj = {"a": 1, "b": 2}
|
|
69
|
+
delProperty(obj, "a")
|
|
70
|
+
self.assertEqual(obj, {"b": 2})
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class TestSanitizeVisualization(unittest.TestCase):
|
|
74
|
+
"""Tests for sanitizeVisualization function"""
|
|
75
|
+
|
|
76
|
+
def test_empty_visualization(self):
|
|
77
|
+
result = sanitizeVisualization({})
|
|
78
|
+
self.assertEqual(result["data"], [])
|
|
79
|
+
self.assertEqual(result["layout"], {})
|
|
80
|
+
self.assertEqual(result["columns"], [])
|
|
81
|
+
self.assertEqual(result["dataSources"], {})
|
|
82
|
+
|
|
83
|
+
def test_with_data(self):
|
|
84
|
+
v = {"data": [{"x": [1, 2], "y": [3, 4]}]}
|
|
85
|
+
result = sanitizeVisualization(v)
|
|
86
|
+
self.assertEqual(result["data"], [{"x": [1, 2], "y": [3, 4]}])
|
|
87
|
+
|
|
88
|
+
def test_with_chart_data_backward_compat(self):
|
|
89
|
+
v = {"chartData": {"data": [{"x": [1]}], "layout": {"title": "test"}}}
|
|
90
|
+
result = sanitizeVisualization(v)
|
|
91
|
+
self.assertEqual(result["data"], [{"x": [1]}])
|
|
92
|
+
self.assertEqual(result["layout"], {"title": "test"})
|
|
93
|
+
|
|
94
|
+
def test_with_layout(self):
|
|
95
|
+
v = {"layout": {"title": "My Chart"}}
|
|
96
|
+
result = sanitizeVisualization(v)
|
|
97
|
+
self.assertEqual(result["layout"], {"title": "My Chart"})
|
|
98
|
+
|
|
99
|
+
def test_with_columns(self):
|
|
100
|
+
v = {"columns": [{"name": "col1"}]}
|
|
101
|
+
result = sanitizeVisualization(v)
|
|
102
|
+
self.assertEqual(result["columns"], [{"name": "col1"}])
|
|
103
|
+
|
|
104
|
+
def test_data_sources_merge(self):
|
|
105
|
+
v = {
|
|
106
|
+
"data_source": {"src1": "url1"},
|
|
107
|
+
"dataSources": {"src2": "url2"},
|
|
108
|
+
}
|
|
109
|
+
result = sanitizeVisualization(v)
|
|
110
|
+
self.assertEqual(result["dataSources"], {"src1": "url1", "src2": "url2"})
|
|
111
|
+
|
|
112
|
+
def test_optional_properties_set(self):
|
|
113
|
+
v = {
|
|
114
|
+
"provider_url": "https://example.com",
|
|
115
|
+
"variation": "bar",
|
|
116
|
+
"filters": {"field": "value"},
|
|
117
|
+
"id": "viz-1",
|
|
118
|
+
"type": "plotly",
|
|
119
|
+
"label": "My Viz",
|
|
120
|
+
}
|
|
121
|
+
result = sanitizeVisualization(v)
|
|
122
|
+
self.assertEqual(result["provider_url"], "https://example.com")
|
|
123
|
+
self.assertEqual(result["variation"], "bar")
|
|
124
|
+
self.assertEqual(result["filters"], {"field": "value"})
|
|
125
|
+
self.assertEqual(result["id"], "viz-1")
|
|
126
|
+
self.assertEqual(result["type"], "plotly")
|
|
127
|
+
self.assertEqual(result["label"], "My Viz")
|
|
128
|
+
|
|
129
|
+
def test_optional_properties_none_not_set(self):
|
|
130
|
+
v = {"provider_url": None, "variation": None}
|
|
131
|
+
result = sanitizeVisualization(v)
|
|
132
|
+
self.assertNotIn("provider_url", result)
|
|
133
|
+
self.assertNotIn("variation", result)
|
|
134
|
+
|
|
135
|
+
def test_default_empty_dict(self):
|
|
136
|
+
result = sanitizeVisualization()
|
|
137
|
+
self.assertIsNotNone(result)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class TestGetLink(unittest.TestCase):
|
|
141
|
+
"""Tests for getLink function"""
|
|
142
|
+
|
|
143
|
+
def test_localhost_link(self):
|
|
144
|
+
result = getLink("http://localhost:8080/Plone/page")
|
|
145
|
+
self.assertEqual(result, "/Plone/page")
|
|
146
|
+
|
|
147
|
+
def test_external_link(self):
|
|
148
|
+
result = getLink("https://example.com/page")
|
|
149
|
+
self.assertEqual(result, "https://example.com/page")
|
|
150
|
+
|
|
151
|
+
def test_relative_path(self):
|
|
152
|
+
result = getLink("/Plone/page")
|
|
153
|
+
self.assertEqual(result, "/Plone/page")
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class TestGetLinkHTML(unittest.TestCase):
|
|
157
|
+
"""Tests for getLinkHTML function"""
|
|
158
|
+
|
|
159
|
+
def test_with_text(self):
|
|
160
|
+
result = getLinkHTML("https://example.com", "Click here")
|
|
161
|
+
self.assertEqual(
|
|
162
|
+
result, '<a href="https://example.com" target="_blank">Click here</a>'
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
def test_without_text(self):
|
|
166
|
+
result = getLinkHTML("https://example.com")
|
|
167
|
+
self.assertEqual(
|
|
168
|
+
result,
|
|
169
|
+
'<a href="https://example.com" target="_blank">https://example.com</a>',
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
def test_empty_url(self):
|
|
173
|
+
result = getLinkHTML("")
|
|
174
|
+
self.assertEqual(result, "")
|
|
175
|
+
|
|
176
|
+
def test_none_url(self):
|
|
177
|
+
result = getLinkHTML(None)
|
|
178
|
+
self.assertIsNone(result)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class TestIsExpanded(unittest.TestCase):
|
|
182
|
+
"""Tests for isExpanded function"""
|
|
183
|
+
|
|
184
|
+
def test_expanded(self):
|
|
185
|
+
class FakeRequest:
|
|
186
|
+
form = {"expand.visualization": "1"}
|
|
187
|
+
|
|
188
|
+
self.assertTrue(isExpanded(FakeRequest()))
|
|
189
|
+
|
|
190
|
+
def test_not_expanded(self):
|
|
191
|
+
class FakeRequest:
|
|
192
|
+
form = {}
|
|
193
|
+
|
|
194
|
+
self.assertFalse(isExpanded(FakeRequest()))
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class TestCsvWriter(unittest.TestCase):
|
|
198
|
+
"""Tests for CsvWriter class"""
|
|
199
|
+
|
|
200
|
+
def test_write_row_with_none(self):
|
|
201
|
+
output = io.StringIO()
|
|
202
|
+
writer = CsvWriter(output)
|
|
203
|
+
writer.writerow(["a", None, "b"])
|
|
204
|
+
output.seek(0)
|
|
205
|
+
self.assertEqual(output.read().strip(), "a,NULL,b")
|
|
206
|
+
|
|
207
|
+
def test_write_row_no_none(self):
|
|
208
|
+
output = io.StringIO()
|
|
209
|
+
writer = CsvWriter(output)
|
|
210
|
+
writer.writerow(["a", "b", "c"])
|
|
211
|
+
output.seek(0)
|
|
212
|
+
self.assertEqual(output.read().strip(), "a,b,c")
|
|
213
|
+
|
|
214
|
+
def test_write_rows(self):
|
|
215
|
+
output = io.StringIO()
|
|
216
|
+
writer = CsvWriter(output)
|
|
217
|
+
writer.writerows([["a", None], [None, "b"]])
|
|
218
|
+
output.seek(0)
|
|
219
|
+
lines = output.read().strip().split("\n")
|
|
220
|
+
self.assertEqual(lines[0].strip(), "a,NULL")
|
|
221
|
+
self.assertEqual(lines[1].strip(), "NULL,b")
|
|
222
|
+
|
|
223
|
+
def test_write_empty_row(self):
|
|
224
|
+
output = io.StringIO()
|
|
225
|
+
writer = CsvWriter(output)
|
|
226
|
+
writer.writerow([])
|
|
227
|
+
output.seek(0)
|
|
228
|
+
self.assertEqual(output.read().strip(), "")
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
class TestCsvReader(unittest.TestCase):
|
|
232
|
+
"""Tests for CsvReader class"""
|
|
233
|
+
|
|
234
|
+
def test_read_row_with_null(self):
|
|
235
|
+
input_data = "a,NULL,b\n"
|
|
236
|
+
reader = CsvReader(io.StringIO(input_data))
|
|
237
|
+
rows = list(reader)
|
|
238
|
+
self.assertEqual(rows, [["a", None, "b"]])
|
|
239
|
+
|
|
240
|
+
def test_read_row_no_null(self):
|
|
241
|
+
input_data = "a,b,c\n"
|
|
242
|
+
reader = CsvReader(io.StringIO(input_data))
|
|
243
|
+
rows = list(reader)
|
|
244
|
+
self.assertEqual(rows, [["a", "b", "c"]])
|
|
245
|
+
|
|
246
|
+
def test_read_multiple_rows(self):
|
|
247
|
+
input_data = "a,b\nNULL,c\n"
|
|
248
|
+
reader = CsvReader(io.StringIO(input_data))
|
|
249
|
+
rows = list(reader)
|
|
250
|
+
self.assertEqual(len(rows), 2)
|
|
251
|
+
self.assertEqual(rows[0], ["a", "b"])
|
|
252
|
+
self.assertEqual(rows[1], [None, "c"])
|
|
253
|
+
|
|
254
|
+
def test_null_constant(self):
|
|
255
|
+
self.assertEqual(NULL, "NULL")
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
class TestJSONEncoder(unittest.TestCase):
|
|
259
|
+
"""Tests for JSONEncoder class"""
|
|
260
|
+
|
|
261
|
+
def test_encode_decimal(self):
|
|
262
|
+
result = json.dumps({"value": decimal.Decimal("3.14")}, cls=JSONEncoder)
|
|
263
|
+
self.assertEqual(result, '{"value": "3.14"}')
|
|
264
|
+
|
|
265
|
+
def test_encode_regular_types(self):
|
|
266
|
+
result = json.dumps({"int": 42, "str": "hello"}, cls=JSONEncoder)
|
|
267
|
+
self.assertEqual(result, '{"int": 42, "str": "hello"}')
|
|
268
|
+
|
|
269
|
+
def test_encode_nested_decimal(self):
|
|
270
|
+
data = {"chart": {"value": decimal.Decimal("10.5")}}
|
|
271
|
+
result = json.dumps(data, cls=JSONEncoder)
|
|
272
|
+
self.assertEqual(result, '{"chart": {"value": "10.5"}}')
|
|
273
|
+
|
|
274
|
+
def test_encode_list_with_decimal(self):
|
|
275
|
+
data = [1, decimal.Decimal("2.5"), 3]
|
|
276
|
+
result = json.dumps(data, cls=JSONEncoder)
|
|
277
|
+
self.assertEqual(result, '[1, "2.5", 3]')
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
if __name__ == "__main__":
|
|
281
|
+
unittest.main()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.3
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: eea.plotly
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3
|
|
4
4
|
Summary: volto-plotlycharts backend support
|
|
5
5
|
Home-page: https://github.com/eea/eea.plotly
|
|
6
6
|
Author: European Environment Agency: IDM2 A-Team
|
|
@@ -145,6 +145,11 @@ EEA_ - European Environment Agency (EU)
|
|
|
145
145
|
Changelog
|
|
146
146
|
=========
|
|
147
147
|
|
|
148
|
+
2.3 - (2026-04-14)
|
|
149
|
+
---------------------------
|
|
150
|
+
* Change: Add unit tests for utils, io_csv, and io_json modules
|
|
151
|
+
[avoinea]
|
|
152
|
+
|
|
148
153
|
2.2 - (2025-11-20)
|
|
149
154
|
---------------------------
|
|
150
155
|
* Change: better handle of backward compatibility, ref #293767
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2.2
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|