package appendix_test import ( "context" "encoding/xml" "io/ioutil" "os" "path/filepath" "strings" "testing" "cdr.dev/slog" tassert "github.com/stretchr/testify/assert" "oss.terrastruct.com/util-go/assert" "oss.terrastruct.com/util-go/diff" "oss.terrastruct.com/d2/d2graph" "oss.terrastruct.com/d2/d2layouts/d2dagrelayout" "oss.terrastruct.com/d2/d2lib" "oss.terrastruct.com/d2/d2renderers/d2svg" "oss.terrastruct.com/d2/d2renderers/d2svg/appendix" "oss.terrastruct.com/d2/lib/log" "oss.terrastruct.com/d2/lib/textmeasure" ) func TestAppendix(t *testing.T) { t.Parallel() tcs := []testCase{ { name: "tooltip_wider_than_diagram", script: `x: { tooltip: Total abstinence is easier than perfect moderation } y: { tooltip: Gee, I feel kind of LIGHT in the head now,\nknowing I can't make my satellite dish PAYMENTS! } x -> y `, }, { name: "diagram_wider_than_tooltip", script: `shape: sequence_diagram customer issuer store: { tooltip: Like starbucks or something } acquirer: { tooltip: I'm not sure what this is } network customer bank store bank customer: {shape: person} customer bank: { shape: image icon: https://cdn-icons-png.flaticon.com/512/858/858170.png } store bank: { shape: image icon: https://cdn-icons-png.flaticon.com/512/858/858170.png } initial transaction: { customer -> store: 1 banana please store -> customer: '$10 dollars' } customer.internal -> customer.internal: "thinking: wow, inflation" customer.internal -> customer bank: checks bank account customer bank -> customer.internal: 'Savings: $11' customer."An error in judgement is about to occur" customer -> store: I can do that, here's my card payment processor behind the scenes: { store -> acquirer: Run this card acquirer -> network: Process to card issuer simplified: { network -> issuer: Process this payment issuer -> customer bank: '$10 debit' acquirer -> store bank: '$10 credit' } } `, }, { name: "links", script: `x: { link: https://d2lang.com } y: { link: https://terrastruct.com; tooltip: Gee, I feel kind of LIGHT in the head now,\nknowing I can't make my satellite dish PAYMENTS! } x -> y `, }, { name: "links dark", themeID: 200, script: `x: { link: https://d2lang.com } y: { link: https://fosny.eu; tooltip: Gee, I feel kind of LIGHT in the head now,\nknowing I can't make my satellite dish PAYMENTS! } x -> y `, }, { name: "internal-links", script: `x: { link: layers.x } layers: { x: { gooo home.link: _ next.link: steps.next steps: { next: { hi } } } } `, }, { name: "tooltip_fill", script: `x: { tooltip: Total abstinence is easier than perfect moderation } y: { tooltip: Gee, I feel kind of LIGHT in the head now,\nknowing I can't make my satellite dish PAYMENTS! } x -> y style.fill: PaleVioletRed `, }, } runa(t, tcs) } type testCase struct { name string themeID int64 script string 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 !tassert.Nil(t, err) { return } renderOpts := &d2svg.RenderOpts{ ThemeID: &tc.themeID, } layoutResolver := func(engine string) (d2graph.LayoutGraph, error) { return d2dagrelayout.DefaultLayout, nil } diagram, _, err := d2lib.Compile(ctx, tc.script, &d2lib.CompileOptions{ Ruler: ruler, LayoutResolver: layoutResolver, }, renderOpts) if !tassert.Nil(t, err) { return } dataPath := filepath.Join("testdata", strings.TrimPrefix(t.Name(), "TestAppendix/")) pathGotSVG := filepath.Join(dataPath, "sketch.got.svg") svgBytes, err := d2svg.Render(diagram, renderOpts) assert.Success(t, err) svgBytes = appendix.Append(diagram, ruler, svgBytes) err = os.MkdirAll(dataPath, 0755) assert.Success(t, err) err = ioutil.WriteFile(pathGotSVG, svgBytes, 0600) assert.Success(t, err) defer os.Remove(pathGotSVG) var xmlParsed interface{} err = xml.Unmarshal(svgBytes, &xmlParsed) assert.Success(t, err) err = diff.Testdata(filepath.Join(dataPath, "sketch"), ".svg", svgBytes) assert.Success(t, err) }