d2/e2etests/e2e_test.go
Anmol Sethi c4ef432daf
Move textmeasure into lib
It's not a d2renderer.
2022-12-01 06:51:17 -08:00

173 lines
3.4 KiB
Go

package e2etests
import (
"context"
"encoding/xml"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"cdr.dev/slog"
"github.com/stretchr/testify/assert"
"oss.terrastruct.com/diff"
"oss.terrastruct.com/d2/d2graph"
"oss.terrastruct.com/d2/d2layouts/d2dagrelayout"
"oss.terrastruct.com/d2/d2layouts/d2elklayout"
"oss.terrastruct.com/d2/d2lib"
"oss.terrastruct.com/d2/d2renderers/d2svg"
"oss.terrastruct.com/d2/d2target"
xdiff "oss.terrastruct.com/d2/lib/diff"
"oss.terrastruct.com/d2/lib/log"
"oss.terrastruct.com/d2/lib/textmeasure"
)
func TestE2E(t *testing.T) {
t.Parallel()
t.Run("sanity", testSanity)
t.Run("stable", testStable)
t.Run("regression", testRegression)
t.Run("todo", testTodo)
}
func testSanity(t *testing.T) {
tcs := []testCase{
{
name: "basic",
script: `a -> b
`,
},
{
name: "1 to 2",
script: `a -> b
a -> c
`,
},
{
name: "child to child",
script: `a.b -> c.d
`,
},
{
name: "connection label",
script: `a -> b: hello
`,
},
}
runa(t, tcs)
}
type testCase struct {
name string
script string
assertions func(t *testing.T, diagram *d2target.Diagram)
skip bool
}
func runa(t *testing.T, tcs []testCase) {
for _, tc := range tcs {
tc := tc
t.Run(tc.name, func(t *testing.T) {
if tc.skip {
t.Skip()
}
t.Parallel()
run(t, tc)
})
}
}
func run(t *testing.T, tc testCase) {
ctx := context.Background()
ctx = log.WithTB(ctx, t, nil)
ctx = log.Leveled(ctx, slog.LevelDebug)
ruler, err := textmeasure.NewRuler()
if !assert.Nil(t, err) {
return
}
layoutsTested := []string{"dagre", "elk"}
for _, layoutName := range layoutsTested {
var layout func(context.Context, *d2graph.Graph) error
if layoutName == "dagre" {
layout = d2dagrelayout.Layout
} else if layoutName == "elk" {
layout = d2elklayout.Layout
}
diagram, _, err := d2lib.Compile(ctx, tc.script, &d2lib.CompileOptions{
UTF16: true,
Ruler: ruler,
ThemeID: 0,
Layout: layout,
})
if !assert.Nil(t, err) {
return
}
if tc.assertions != nil {
t.Run("assertions", func(t *testing.T) {
tc.assertions(t, diagram)
})
}
dataPath := filepath.Join("testdata", strings.TrimPrefix(t.Name(), "TestE2E/"), layoutName)
pathGotSVG := filepath.Join(dataPath, "sketch.got.svg")
pathExpSVG := filepath.Join(dataPath, "sketch.exp.svg")
svgBytes, err := d2svg.Render(diagram)
if err != nil {
t.Fatal(err)
}
var xmlParsed interface{}
if err := xml.Unmarshal(svgBytes, &xmlParsed); err != nil {
t.Fatalf("invalid SVG: %v", err)
}
err = diff.Testdata(filepath.Join(dataPath, "board"), diagram)
if err != nil {
ioutil.WriteFile(pathGotSVG, svgBytes, 0600)
t.Fatal(err)
}
if os.Getenv("SKIP_SVG_CHECK") == "" {
err = xdiff.TestdataGeneric(filepath.Join(dataPath, "sketch"), ".svg", svgBytes)
if err != nil {
ioutil.WriteFile(pathGotSVG, svgBytes, 0600)
t.Fatal(err)
}
}
err = ioutil.WriteFile(pathExpSVG, svgBytes, 0600)
if err != nil {
t.Fatal(err)
}
os.Remove(filepath.Join(dataPath, "sketch.got.svg"))
}
}
func getShape(t *testing.T, diagram *d2target.Diagram, id string) d2target.Shape {
for _, shape := range diagram.Shapes {
if shape.ID == id {
return shape
}
}
t.Fatalf(`Shape "%s" not found`, id)
return d2target.Shape{}
}
func mdTestScript(md string) string {
return fmt.Sprintf(`
md: |md
%s
|
a -> md -> b
`, md)
}