Files
hermes-webui/tests/test_issue484_json_tree_viewer.py
T
bergeouss 49a2a424d5 feat: collapsible JSON/YAML tree viewer (#484)
- Fenced code blocks with json/yaml lang get Tree/Raw toggle
- Recursive DOM builder (_buildTreeDOM) with type-colored values
  (green strings, blue numbers, amber booleans, muted nulls)
- Auto-collapse at depth 2+, default tree for >=10 lines blocks
- YAML parsing via js-yaml (lazy, CDN-loaded)
- CSS: tree-view, tree-node, collapsible, type-colored classes
- i18n: tree_view, raw_view keys in all 7 locales
- 14 tests: renderer, types, collapse, CSS, i18n

Closes #484
2026-04-29 04:34:26 +00:00

104 lines
4.2 KiB
Python

"""Tests for issue #484 — collapsible JSON/YAML tree viewer."""
import pytest
class TestTreeRenderer:
"""Fenced JSON/YAML blocks should get a tree view toggle."""
def test_json_blocks_get_tree_wrapper(self):
with open("static/ui.js", "r", encoding="utf-8") as f:
content = f.read()
assert "code-tree-wrap" in content
assert "data-raw" in content
assert "data-lang" in content
def test_json_yaml_lang_detection(self):
with open("static/ui.js", "r", encoding="utf-8") as f:
content = f.read()
assert "lang==='json'||lang==='yaml'" in content
def test_initTreeViews_function_exists(self):
with open("static/ui.js", "r", encoding="utf-8") as f:
content = f.read()
assert "function initTreeViews()" in content
def test_buildTreeDOM_function_exists(self):
with open("static/ui.js", "r", encoding="utf-8") as f:
content = f.read()
assert "function _buildTreeDOM(val, depth)" in content
def test_initTreeViews_called_in_post_render(self):
with open("static/ui.js", "r", encoding="utf-8") as f:
content = f.read()
count = content.count("initTreeViews()")
assert count >= 2, f"initTreeViews() called {count} times, expected >= 2"
def test_tree_handles_all_value_types(self):
"""_buildTreeDOM should handle null, boolean, number, string, array, object."""
with open("static/ui.js", "r", encoding="utf-8") as f:
content = f.read()
for cls in ("tree-null", "tree-bool", "tree-num", "tree-str", "tree-array", "tree-object"):
assert cls in content, f"Missing type class: {cls}"
def test_tree_collapse_support(self):
"""Tree nodes should be collapsible with collapsed/expanded states."""
with open("static/ui.js", "r", encoding="utf-8") as f:
content = f.read()
assert "tree-collapsed" in content
assert "tree-collapsible" in content
assert "classList.toggle" in content
def test_tree_depth_auto_collapse(self):
"""Nested levels beyond depth 2 should be collapsed by default."""
with open("static/ui.js", "r", encoding="utf-8") as f:
content = f.read()
assert "depth>=2" in content
def test_toggle_button_uses_i18n(self):
with open("static/ui.js", "r", encoding="utf-8") as f:
content = f.read()
assert "t('raw_view')" in content
assert "t('tree_view')" in content
def test_yaml_support_via_jsyaml(self):
"""YAML should be parsed via jsyaml if available."""
with open("static/ui.js", "r", encoding="utf-8") as f:
content = f.read()
assert "jsyaml" in content
def test_short_json_defaults_to_raw(self):
"""Blocks under 10 lines should default to raw view."""
with open("static/ui.js", "r", encoding="utf-8") as f:
content = f.read()
assert "lineCount>=10" in content
class TestTreeCSS:
"""CSS classes for tree viewer."""
def test_tree_css_classes_exist(self):
with open("static/style.css", "r", encoding="utf-8") as f:
content = f.read()
for cls in (".code-tree-wrap", ".tree-view", ".tree-hidden", ".tree-toggle-btn",
".tree-node", ".tree-collapsible", ".tree-children", ".tree-collapsed",
".tree-key", ".tree-str", ".tree-num", ".tree-bool", ".tree-null",
".tree-comma", ".tree-item"):
assert cls in content, f"Missing CSS: {cls}"
def test_tree_colors_match_types(self):
with open("static/style.css", "r", encoding="utf-8") as f:
content = f.read()
# Green strings, blue numbers, amber booleans
assert "#4ade80" in content # tree-str green
assert "#60a5fa" in content # tree-key/tree-num blue
assert "#fbbf24" in content # tree-bool amber
class TestTreeI18n:
def test_i18n_keys_present(self):
with open("static/i18n.js", "r", encoding="utf-8") as f:
content = f.read()
for key in ("tree_view", "raw_view"):
count = content.count(key)
assert count >= 7, f"{key} found {count} times, expected >= 7"