d2/d2layouts/d2sequence/layout_test.go

168 lines
4.9 KiB
Go
Raw Normal View History

package d2sequence
import (
"context"
"testing"
"oss.terrastruct.com/d2/d2graph"
"oss.terrastruct.com/d2/lib/geo"
"oss.terrastruct.com/d2/lib/log"
)
2022-11-29 01:06:37 +00:00
func TestBasicSequenceDiagram(t *testing.T) {
// ┌────────┐ ┌────────┐
// │ n1 │ │ n2 │
// └────┬───┘ └────┬───┘
// │ │
// ├───────────────────────►
// │ │
// ◄───────────────────────┤
// │ │
// ├───────────────────────►
// │ │
// ◄───────────────────────┤
// │ │
g := d2graph.NewGraph(nil)
2022-11-29 01:06:37 +00:00
n1 := g.Root.EnsureChild([]string{"n1"})
n1.Box = geo.NewBox(nil, 100, 100)
n2 := g.Root.EnsureChild([]string{"n2"})
n2.Box = geo.NewBox(nil, 30, 30)
g.Edges = []*d2graph.Edge{
{
2022-11-29 01:06:37 +00:00
Src: n1,
Dst: n2,
},
{
2022-11-29 01:06:37 +00:00
Src: n2,
Dst: n1,
},
{
2022-11-29 01:06:37 +00:00
Src: n1,
Dst: n2,
},
{
2022-11-29 01:06:37 +00:00
Src: n2,
Dst: n1,
},
}
nEdges := len(g.Edges)
ctx := log.WithTB(context.Background(), t, nil)
Layout(ctx, g)
2022-11-28 19:11:38 +00:00
// asserts that actors were placed in the expected x order and at y=0
actors := []*d2graph.Object{
g.Objects[0],
g.Objects[1],
}
2022-11-28 19:11:38 +00:00
for i := 1; i < len(actors); i++ {
if actors[i].TopLeft.X < actors[i-1].TopLeft.X {
t.Fatalf("expected actor[%d].TopLeft.X > actor[%d].TopLeft.X", i, i-1)
}
2022-11-28 19:11:38 +00:00
actorBottom := actors[i].TopLeft.Y + actors[i].Height
prevActorBottom := actors[i-1].TopLeft.Y + actors[i-1].Height
if actorBottom != prevActorBottom {
t.Fatalf("expected actor[%d] and actor[%d] to be at the same bottom y", i, i-1)
}
}
2022-11-28 19:11:38 +00:00
nExpectedEdges := nEdges + len(actors)
if len(g.Edges) != nExpectedEdges {
t.Fatalf("expected %d edges, got %d", nExpectedEdges, len(g.Edges))
}
2022-11-28 19:11:38 +00:00
// assert that edges were placed in y order and have the endpoints at their actors
// uses `nEdges` because Layout creates some vertical edges to represent the actor lifeline
for i := 0; i < nEdges; i++ {
edge := g.Edges[i]
if len(edge.Route) != 2 {
t.Fatalf("expected edge[%d] to have only 2 points", i)
}
if edge.Route[0].Y != edge.Route[1].Y {
t.Fatalf("expected edge[%d] to be a horizontal line", i)
}
if edge.Route[0].X != edge.Src.Center().X {
2022-11-28 19:11:38 +00:00
t.Fatalf("expected edge[%d] source endpoint to be at the middle of the source actor", i)
}
if edge.Route[1].X != edge.Dst.Center().X {
2022-11-28 19:11:38 +00:00
t.Fatalf("expected edge[%d] target endpoint to be at the middle of the target actor", i)
}
if i > 0 {
prevEdge := g.Edges[i-1]
if edge.Route[0].Y < prevEdge.Route[0].Y {
t.Fatalf("expected edge[%d].TopLeft.Y > edge[%d].TopLeft.Y", i, i-1)
}
}
}
lastSequenceEdge := g.Edges[nEdges-1]
for i := nEdges; i < nExpectedEdges; i++ {
edge := g.Edges[i]
if len(edge.Route) != 2 {
t.Fatalf("expected edge[%d] to have only 2 points", i)
}
if edge.Route[0].X != edge.Route[1].X {
t.Fatalf("expected edge[%d] to be a vertical line", i)
}
if edge.Route[0].X != edge.Src.Center().X {
2022-11-28 19:11:38 +00:00
t.Fatalf("expected edge[%d] x to be at the actor center", i)
}
if edge.Route[0].Y != edge.Src.Height+edge.Src.TopLeft.Y {
2022-11-28 19:11:38 +00:00
t.Fatalf("expected edge[%d] to start at the bottom of the source actor", i)
}
if edge.Route[1].Y < lastSequenceEdge.Route[0].Y {
t.Fatalf("expected edge[%d] to end after the last sequence edge", i)
}
}
}
2022-11-29 01:06:37 +00:00
func TestLifespanSequenceDiagram(t *testing.T) {
// ┌─────┐ ┌─────┐
// │ a │ │ b │
// └──┬──┘ └──┬──┘
// ├┐────────────────────►┌┤
// t1 ││ ││ t1
// ├┘◄────────────────────└┤
// ├┐──────────────────────►
// t2 ││ │
// ├┘◄─────────────────────┤
g := d2graph.NewGraph(nil)
a := g.Root.EnsureChild([]string{"a"})
a.Box = geo.NewBox(nil, 100, 100)
a_t1 := a.EnsureChild([]string{"t1"})
a_t2 := a.EnsureChild([]string{"t2"})
b := g.Root.EnsureChild([]string{"b"})
b.Box = geo.NewBox(nil, 30, 30)
b_t1 := b.EnsureChild([]string{"t1"})
g.Edges = []*d2graph.Edge{
{
Src: a_t1,
Dst: b_t1,
}, {
Src: b_t1,
Dst: a_t1,
}, {
Src: a_t2,
Dst: b,
}, {
Src: b,
Dst: a_t2,
},
}
ctx := log.WithTB(context.Background(), t, nil)
Layout(ctx, g)
if a.Center().X != a_t1.Center().X {
t.Fatal("expected a_t1.X = a.X")
}
if a.Center().X != a_t2.Center().X {
t.Fatal("expected a_t2.X = a.X")
}
if b.Center().X != b_t1.Center().X {
t.Fatal("expected b_t1.X = b.X")
}
}