From ce5af6fbc5ffb14598bb9dd4cebd450406bb56ed Mon Sep 17 00:00:00 2001 From: safishamsi Date: Fri, 10 Jul 2026 20:24:25 +0100 Subject: [PATCH] test: guard to_html/sanitize_label against null source_file/label (#1775) The TypeError reported on 0.1.14 is already fixed on v8: sanitize_label coerces None ('if text is None: return ""') and the source_file call site guards with str(data.get("source_file") or ""). Add regression tests (unit + to_html integration with null label/source_file) so it can't silently regress. Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/test_export.py | 15 +++++++++++++++ tests/test_security.py | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/tests/test_export.py b/tests/test_export.py index 77233182..7194d8b7 100644 --- a/tests/test_export.py +++ b/tests/test_export.py @@ -639,3 +639,18 @@ def test_to_json_proceeds_on_empty_existing(tmp_path): assert to_json(_mkG(3), {}, str(p), force=False) is True data = json.loads(p.read_text()) assert len(data["nodes"]) == 3 + + +def test_to_html_handles_null_source_file_and_label(tmp_path): + """#1775: a node with source_file=None or label=None must not crash to_html + (synthetic/aggregate nodes legitimately carry null source_file; JSON `null` + survives .get()'s default). Regression guard — fixed via sanitize_label's + None-coercion + the str(source_file or "") call-site guard.""" + import networkx as nx + G = nx.Graph() + G.add_node("n1", label="Foo", source_file=None, community=0) + G.add_node("n2", label=None, source_file="a.py", community=0) + G.add_node("n3", label=None, source_file=None, community=0) + out = tmp_path / "graph.html" + to_html(G, {0: ["n1", "n2", "n3"]}, str(out)) + assert out.exists() and out.stat().st_size > 0 diff --git a/tests/test_security.py b/tests/test_security.py index 2f69be6b..74669f93 100644 --- a/tests/test_security.py +++ b/tests/test_security.py @@ -219,6 +219,12 @@ def test_sanitize_label_safe_passthrough(): assert sanitize_label("MyClass") == "MyClass" assert sanitize_label("extract_python") == "extract_python" +def test_sanitize_label_none_returns_empty(): + # #1775: a node with source_file=None / label=None (synthetic/aggregate + # nodes, or JSON `null`) must not raise — .get() returns None, not the + # default, when the key is present-but-null. + assert sanitize_label(None) == "" + # --------------------------------------------------------------------------- # check_graph_file_size_cap (#F4 — graph-load memory bomb protection)