159 lines
5.3 KiB
Python
159 lines
5.3 KiB
Python
import pytest
|
|
import tempfile
|
|
import subprocess
|
|
import json
|
|
from pathlib import Path
|
|
from src.graph.builder import GraphBuilder, GraphType, GraphNode, NodeType
|
|
from src.exporters.dot import DOTExporter
|
|
from src.exporters.json_exporter import JSONExporter
|
|
from src.exporters.png import PNGExporter
|
|
|
|
|
|
def graphviz_available():
|
|
try:
|
|
subprocess.run(["dot", "-V"], capture_output=True, check=True)
|
|
return True
|
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
return False
|
|
|
|
|
|
class TestDOTExporter:
|
|
def setup_method(self):
|
|
self.builder = GraphBuilder(GraphType.DIRECTED)
|
|
self.exporter = DOTExporter(self.builder)
|
|
|
|
def test_export_creates_file(self):
|
|
node = GraphNode(node_id="test", node_type=NodeType.FILE, name="test.py")
|
|
self.builder.add_node(node)
|
|
|
|
with tempfile.NamedTemporaryFile(suffix=".dot", delete=False) as f:
|
|
output_path = Path(f.name)
|
|
try:
|
|
self.exporter.export(output_path)
|
|
assert output_path.exists()
|
|
content = output_path.read_text()
|
|
assert "digraph codegraph" in content
|
|
assert "test" in content
|
|
finally:
|
|
output_path.unlink()
|
|
|
|
def test_get_string_returns_dot_format(self):
|
|
node = GraphNode(node_id="node1", node_type=NodeType.FILE, name="file.py")
|
|
self.builder.add_node(node)
|
|
|
|
content = self.exporter.get_string()
|
|
assert "digraph codegraph" in content
|
|
assert "node1" in content
|
|
|
|
def test_export_with_layout(self):
|
|
node = GraphNode(node_id="test", node_type=NodeType.FILE, name="test.py")
|
|
self.builder.add_node(node)
|
|
|
|
content = self.exporter.get_string(layout="circo")
|
|
assert "digraph codegraph" in content
|
|
|
|
def test_export_with_rankdir(self):
|
|
node = GraphNode(node_id="test", node_type=NodeType.FILE, name="test.py")
|
|
self.builder.add_node(node)
|
|
|
|
content = self.exporter.get_string(rankdir="LR")
|
|
assert "rankdir=LR" in content
|
|
|
|
|
|
class TestJSONExporter:
|
|
def setup_method(self):
|
|
self.builder = GraphBuilder(GraphType.DIRECTED)
|
|
self.exporter = JSONExporter(self.builder)
|
|
|
|
def test_export_creates_json_file(self):
|
|
node = GraphNode(node_id="test", node_type=NodeType.FILE, name="test.py")
|
|
self.builder.add_node(node)
|
|
|
|
with tempfile.NamedTemporaryFile(suffix=".json", delete=False) as f:
|
|
output_path = Path(f.name)
|
|
try:
|
|
self.exporter.export(output_path)
|
|
assert output_path.exists()
|
|
data = json.loads(output_path.read_text())
|
|
assert "nodes" in data
|
|
assert "edges" in data
|
|
finally:
|
|
output_path.unlink()
|
|
|
|
def test_get_string_returns_json(self):
|
|
node = GraphNode(node_id="test", node_type=NodeType.FILE, name="test.py")
|
|
self.builder.add_node(node)
|
|
|
|
content = self.exporter.get_string()
|
|
data = json.loads(content)
|
|
assert "nodes" in data
|
|
assert "edges" in data
|
|
|
|
def test_export_contains_correct_node_data(self):
|
|
node = GraphNode(
|
|
node_id="test_file",
|
|
node_type=NodeType.FILE,
|
|
name="test.py",
|
|
file_path=Path("/test.py"),
|
|
start_line=1,
|
|
end_line=10,
|
|
)
|
|
self.builder.add_node(node)
|
|
|
|
content = self.exporter.get_string()
|
|
data = json.loads(content)
|
|
assert len(data["nodes"]) == 1
|
|
assert data["nodes"][0]["name"] == "test.py"
|
|
assert data["nodes"][0]["type"] == "file"
|
|
|
|
def test_export_for_d3(self):
|
|
node = GraphNode(node_id="test", node_type=NodeType.FILE, name="test.py")
|
|
self.builder.add_node(node)
|
|
|
|
with tempfile.NamedTemporaryFile(suffix=".json", delete=False) as f:
|
|
output_path = Path(f.name)
|
|
try:
|
|
self.exporter.export_for_d3(output_path)
|
|
data = json.loads(output_path.read_text())
|
|
assert "nodes" in data
|
|
assert "links" in data
|
|
finally:
|
|
output_path.unlink()
|
|
|
|
def test_export_includes_statistics(self):
|
|
node = GraphNode(node_id="test", node_type=NodeType.FILE, name="test.py")
|
|
self.builder.add_node(node)
|
|
|
|
content = self.exporter.get_string()
|
|
data = json.loads(content)
|
|
assert "statistics" in data
|
|
assert data["statistics"]["total_nodes"] == 1
|
|
|
|
|
|
class TestPNGExporter:
|
|
def setup_method(self):
|
|
self.builder = GraphBuilder(GraphType.DIRECTED)
|
|
self.exporter = PNGExporter(self.builder)
|
|
|
|
@pytest.mark.skipif(not graphviz_available(), reason="Graphviz not installed")
|
|
def test_export_creates_png_file(self):
|
|
node = GraphNode(node_id="test", node_type=NodeType.FILE, name="test.py")
|
|
self.builder.add_node(node)
|
|
|
|
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as f:
|
|
output_path = Path(f.name)
|
|
try:
|
|
self.exporter.export(output_path)
|
|
assert output_path.exists()
|
|
content = output_path.read_bytes()
|
|
assert len(content) > 0
|
|
finally:
|
|
if output_path.exists():
|
|
output_path.unlink()
|
|
|
|
def test_get_available_layouts(self):
|
|
layouts = self.exporter.get_available_layouts()
|
|
assert "dot" in layouts
|
|
assert "circo" in layouts
|
|
assert "neato" in layouts
|