mirror of
https://github.com/safishamsi/graphify.git
synced 2026-10-13 15:40:05 +00:00
Co-Authored-By: Grok Bot <noreply@x.ai>
(cherry picked from commit 95dd5397cd)
85 lines
2.8 KiB
Python
85 lines
2.8 KiB
Python
"""graph.html light/dark/system theme toggle (#3894)."""
|
|
import re
|
|
|
|
import networkx as nx
|
|
|
|
from graphify.export import to_html
|
|
|
|
# Page-chrome colors graph.html hardcoded before #3894. The dark defaults must
|
|
# keep these exact values so the out-of-the-box look does not change.
|
|
DARK_DEFAULTS = {
|
|
"--bg": "#0f0f1a",
|
|
"--panel": "#1a1a2e",
|
|
"--border": "#2a2a4e",
|
|
"--input-border": "#3a3a5e",
|
|
"--text": "#e0e0e0",
|
|
"--text-2": "#aaa",
|
|
"--text-3": "#ccc",
|
|
"--muted": "#555",
|
|
"--count": "#666",
|
|
"--neighbor-border": "#333",
|
|
"--node-label": "#ffffff",
|
|
}
|
|
|
|
|
|
def _render(tmp_path):
|
|
G = nx.Graph()
|
|
G.add_node("a", label="Alpha", source_file="a.py", file_type="code")
|
|
G.add_node("b", label="Beta", source_file="b.py", file_type="code")
|
|
G.add_edge("a", "b", relation="calls", confidence="EXTRACTED")
|
|
out = tmp_path / "graph.html"
|
|
to_html(G, {0: ["a", "b"]}, str(out), community_labels={0: "Core"})
|
|
return out.read_text(encoding="utf-8")
|
|
|
|
|
|
def _block(html, selector):
|
|
m = re.search(re.escape(selector) + r"\s*\{([^}]*)\}", html)
|
|
assert m, f"missing CSS block {selector}"
|
|
return dict(re.findall(r"(--[\w-]+):\s*([^;]+);", m.group(1)))
|
|
|
|
|
|
def test_dark_defaults_match_previous_hardcoded_colors(tmp_path):
|
|
root = _block(_render(tmp_path), ":root")
|
|
for name, value in DARK_DEFAULTS.items():
|
|
assert root.get(name) == value, name
|
|
|
|
|
|
def test_light_override_defines_every_variable(tmp_path):
|
|
light = _block(_render(tmp_path), '[data-theme="light"]')
|
|
assert set(light) == set(DARK_DEFAULTS)
|
|
assert light["--bg"] != DARK_DEFAULTS["--bg"]
|
|
|
|
|
|
def test_chrome_styles_use_variables_not_hardcoded_dark_colors(tmp_path):
|
|
html = _render(tmp_path)
|
|
styles = html.split("</style>")[0].split("[data-theme=\"light\"]")[1].split("}", 1)[1]
|
|
for color in ("#0f0f1a", "#1a1a2e", "#2a2a4e", "#3a3a5e", "#e0e0e0"):
|
|
assert color not in styles, color
|
|
assert "background: var(--bg)" in styles
|
|
assert "background: var(--panel)" in styles
|
|
|
|
|
|
def test_toggle_control_and_persistence(tmp_path):
|
|
html = _render(tmp_path)
|
|
for choice in ("light", "dark", "system"):
|
|
assert f'data-theme-choice="{choice}"' in html
|
|
assert "graphify-theme" in html
|
|
assert "try { pref = localStorage.getItem('graphify-theme'); } catch (e) {}" in html
|
|
assert "try { localStorage.setItem(THEME_KEY, pref); } catch (e) {}" in html
|
|
assert "prefers-color-scheme: light" in html
|
|
assert "addEventListener('change'" in html
|
|
|
|
|
|
def test_theme_applied_in_head_before_first_paint(tmp_path):
|
|
html = _render(tmp_path)
|
|
head = html.split("</head>")[0]
|
|
assert "setAttribute('data-theme'" in head
|
|
# Unsaved preference falls back to dark, not the OS setting.
|
|
assert ": 'dark';" in head
|
|
|
|
|
|
def test_output_is_deterministic(tmp_path):
|
|
a = _render(tmp_path)
|
|
b = _render(tmp_path)
|
|
assert a == b
|