""" Unit tests for GraphExporter. Tests DOT and Mermaid export with various graph shapes. """ import pytest from markitect.prompts.dependencies.models import DependencyGraph, EdgeType from markitect.prompts.visualization.graph import GraphExporter @pytest.fixture def empty_graph(): """Empty graph with no nodes.""" return DependencyGraph() @pytest.fixture def single_node_graph(): """Graph with a single isolated node.""" g = DependencyGraph() g._forward["node-a"] = set() g._reverse["node-a"] = set() return g @pytest.fixture def linear_graph(): """Linear chain: A -> B -> C.""" g = DependencyGraph() g.add_edge("A", "B", EdgeType.REQUIRES) g.add_edge("B", "C", EdgeType.GENERATES) return g @pytest.fixture def diamond_graph(): """Diamond: A -> B, A -> C, B -> D, C -> D.""" g = DependencyGraph() g.add_edge("A", "B", EdgeType.REQUIRES) g.add_edge("A", "C", EdgeType.REQUIRES) g.add_edge("B", "D", EdgeType.GENERATES) g.add_edge("C", "D", EdgeType.INCLUDES) return g class TestToDot: """Tests for to_dot export.""" def test_empty_graph(self, empty_graph): """Test DOT output for empty graph.""" dot = GraphExporter.to_dot(empty_graph) assert 'digraph "Dependencies"' in dot assert "rankdir=LR" in dot def test_single_node(self, single_node_graph): """Test DOT output with single node.""" dot = GraphExporter.to_dot(single_node_graph) assert "node_a" in dot assert 'label="node-a"' in dot def test_linear_graph(self, linear_graph): """Test DOT output for linear chain.""" dot = GraphExporter.to_dot(linear_graph) assert "A -> B" in dot assert "B -> C" in dot assert 'label="requires"' in dot assert 'label="generates"' in dot def test_diamond_graph(self, diamond_graph): """Test DOT output for diamond graph.""" dot = GraphExporter.to_dot(diamond_graph) assert "A -> B" in dot assert "A -> C" in dot assert "B -> D" in dot assert "C -> D" in dot def test_custom_title(self, linear_graph): """Test DOT output with custom title.""" dot = GraphExporter.to_dot(linear_graph, title="My Graph") assert 'digraph "My Graph"' in dot assert 'label="My Graph"' in dot def test_edge_styles(self, linear_graph): """Test DOT edge styles for different edge types.""" dot = GraphExporter.to_dot(linear_graph) assert 'style="solid"' in dot # REQUIRES assert 'style="dashed"' in dot # GENERATES def test_dot_is_valid_structure(self, diamond_graph): """Test DOT output has valid opening/closing braces.""" dot = GraphExporter.to_dot(diamond_graph) assert dot.startswith('digraph') assert dot.endswith("}") class TestToMermaid: """Tests for to_mermaid export.""" def test_empty_graph(self, empty_graph): """Test Mermaid output for empty graph.""" mermaid = GraphExporter.to_mermaid(empty_graph) assert "graph LR" in mermaid def test_single_node(self, single_node_graph): """Test Mermaid output with single node.""" mermaid = GraphExporter.to_mermaid(single_node_graph) assert "node-a" in mermaid def test_linear_graph(self, linear_graph): """Test Mermaid output for linear chain.""" mermaid = GraphExporter.to_mermaid(linear_graph) assert "A-->|requires|B" in mermaid assert "B-.->|generates|C" in mermaid def test_diamond_graph(self, diamond_graph): """Test Mermaid output for diamond graph.""" mermaid = GraphExporter.to_mermaid(diamond_graph) assert "A-->|requires|B" in mermaid assert "A-->|requires|C" in mermaid assert "B-.->|generates|D" in mermaid assert "C==>|includes|D" in mermaid def test_custom_title(self, linear_graph): """Test Mermaid output with custom title.""" mermaid = GraphExporter.to_mermaid(linear_graph, title="Build Graph") assert "Build Graph" in mermaid def test_edge_arrows(self, diamond_graph): """Test Mermaid edge arrows for different types.""" mermaid = GraphExporter.to_mermaid(diamond_graph) assert "-->" in mermaid # REQUIRES assert "-.->" in mermaid # GENERATES assert "==>" in mermaid # INCLUDES def test_mermaid_starts_with_graph(self, linear_graph): """Test Mermaid output starts with graph directive.""" mermaid = GraphExporter.to_mermaid(linear_graph) lines = mermaid.strip().split("\n") assert "graph LR" in lines[1]