"""Regression tests for graph.json deserialization integrity.""" from __future__ import annotations import json from pathlib import Path import networkx as nx from networkx.readwrite import node_link_data from ctx.core.graph import resolve_graph def _write_graph_file(tmp_path: Path, content: bytes | str) -> Path: path = tmp_path / "graph.json" if isinstance(content, str): path.write_text(content, encoding="utf-8") else: path.write_bytes(content) return path class TestLoadGraphIntegrity: """load_graph must return an empty graph rather than raise on bad input.""" def test_file_not_found_returns_empty_graph(self, tmp_path: Path) -> None: missing = tmp_path / "nonexistent" / "graph.json" graph = resolve_graph.load_graph(path=missing) assert isinstance(graph, nx.Graph) assert graph.number_of_nodes() == 0 def test_invalid_encoding_returns_empty_graph(self, tmp_path: Path) -> None: path = _write_graph_file(tmp_path, b"\xff\xfe{bad encoding\x00") graph = resolve_graph.load_graph(path=path) assert graph.number_of_nodes() == 0 def test_truncated_json_returns_empty_graph(self, tmp_path: Path) -> None: path = _write_graph_file(tmp_path, '{"nodes": [{"id": "skill:foo"') graph = resolve_graph.load_graph(path=path) assert graph.number_of_nodes() == 0 def test_missing_nodes_key_returns_empty_graph(self, tmp_path: Path) -> None: path = _write_graph_file(tmp_path, json.dumps({"links": []})) graph = resolve_graph.load_graph(path=path) assert graph.number_of_nodes() == 0 def test_missing_links_key_returns_empty_graph(self, tmp_path: Path) -> None: path = _write_graph_file(tmp_path, json.dumps({"nodes": []})) graph = resolve_graph.load_graph(path=path) assert graph.number_of_nodes() == 0 def test_wrong_schema_type_returns_empty_graph(self, tmp_path: Path) -> None: path = _write_graph_file(tmp_path, json.dumps([{"id": "skill:foo"}])) graph = resolve_graph.load_graph(path=path) assert graph.number_of_nodes() == 0 def test_null_json_returns_empty_graph(self, tmp_path: Path) -> None: path = _write_graph_file(tmp_path, "null") graph = resolve_graph.load_graph(path=path) assert graph.number_of_nodes() == 0 def test_valid_graph_loads_correctly(self, tmp_path: Path) -> None: source_graph = nx.Graph() source_graph.add_node( "skill:fastapi-pro", label="fastapi-pro", type="skill", tags=["python"], ) source_graph.add_node( "skill:docker-expert", label="docker-expert", type="skill", tags=["docker"], ) source_graph.add_edge("skill:fastapi-pro", "skill:docker-expert", weight=1.0) path = _write_graph_file(tmp_path, json.dumps(node_link_data(source_graph))) graph = resolve_graph.load_graph(path=path) assert graph.number_of_nodes() == 2 assert graph.number_of_edges() == 1