Skip to content

Commit d2e8e46

Browse files
Merge pull request #479 from nextmv-io/merschformann/dag-mermaid
Logs DAG as mermaid diagram for improved transparency
2 parents 1771a12 + badf17f commit d2e8e46

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed

golden/dag.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package golden
22

33
import (
44
"fmt"
5+
"strings"
56
"sync"
67
"testing"
78
)
@@ -43,6 +44,13 @@ func DagTest(t *testing.T, cases []DagTestCase) {
4344
t.Fatal(err)
4445
}
4546

47+
// Print the DAG as a Mermaid diagram for visualization.
48+
mermaid, err := dagToMermaid(cases)
49+
if err != nil {
50+
t.Fatal("error converting DAG to Mermaid format: ", err)
51+
}
52+
t.Logf("DAG diagram (mermaid):\n%s", mermaid)
53+
4654
open := cases
4755
done := make(map[string]bool)
4856

@@ -129,3 +137,57 @@ func validate(cases []DagTestCase) error {
129137

130138
return nil
131139
}
140+
141+
type mermaidNode struct {
142+
ID string
143+
Name string
144+
Needs []string
145+
}
146+
147+
// dagToMermaid converts a set of DAG test cases to a Mermaid diagram format.
148+
// This is useful for visualizing the dependencies between test cases.
149+
func dagToMermaid(cases []DagTestCase) (string, error) {
150+
// Convert each test case to a Mermaid node.
151+
nodesByName := make(map[string]mermaidNode)
152+
ct := 0
153+
for _, c := range cases {
154+
nodesByName[c.Name] = mermaidNode{
155+
ID: fmt.Sprintf("node%d", ct),
156+
Name: c.Name,
157+
}
158+
ct++
159+
}
160+
for _, c := range cases {
161+
n, ok := nodesByName[c.Name]
162+
if !ok {
163+
return "", fmt.Errorf("case %s not found in nodes", c.Name)
164+
}
165+
n.Needs = make([]string, 0, len(c.Needs))
166+
for _, need := range c.Needs {
167+
needNode, ok := nodesByName[need]
168+
if !ok {
169+
return "", fmt.Errorf("dependency %s not found for case %s", need, c.Name)
170+
}
171+
n.Needs = append(n.Needs, needNode.ID)
172+
}
173+
nodesByName[c.Name] = n
174+
}
175+
176+
// Init.
177+
sb := &strings.Builder{}
178+
sb.WriteString("graph TD\n")
179+
180+
// Add nodes themselves.
181+
for _, n := range nodesByName {
182+
fmt.Fprintf(sb, " %s[%s]\n", n.ID, n.Name)
183+
}
184+
185+
// Add dependency relationships.
186+
for _, n := range nodesByName {
187+
for _, needID := range n.Needs {
188+
fmt.Fprintf(sb, " %s --> %s\n", needID, n.ID)
189+
}
190+
}
191+
192+
return sb.String(), nil
193+
}

golden/dag_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Package testing holds tools for testing documentation code.
2+
package golden
3+
4+
import (
5+
"testing"
6+
)
7+
8+
func Test_dagToMermaid(t *testing.T) {
9+
tests := []struct {
10+
dagCases []DagTestCase
11+
name string
12+
}{
13+
{
14+
dagCases: []DagTestCase{
15+
{
16+
Name: "Case 1",
17+
Needs: []string{},
18+
},
19+
{
20+
Name: "Case 2",
21+
Needs: []string{"Case 1"},
22+
},
23+
{
24+
Name: "Case 3",
25+
Needs: []string{"Case 1", "Case 2"},
26+
},
27+
},
28+
name: "valid DAG",
29+
},
30+
}
31+
for _, tt := range tests {
32+
t.Run(tt.name, func(t *testing.T) {
33+
mermaid, err := dagToMermaid(tt.dagCases)
34+
if err != nil {
35+
t.Errorf("dagToMermaid() error = %v", err)
36+
return
37+
}
38+
t.Logf("DAG diagram (mermaid):\n%s", mermaid)
39+
})
40+
}
41+
}

0 commit comments

Comments
 (0)