1 package appendix_test
2
3 import (
4 "context"
5 "encoding/xml"
6 "io/ioutil"
7 "os"
8 "path/filepath"
9 "strings"
10 "testing"
11
12 "cdr.dev/slog"
13
14 tassert "github.com/stretchr/testify/assert"
15
16 "oss.terrastruct.com/util-go/assert"
17 "oss.terrastruct.com/util-go/diff"
18
19 "oss.terrastruct.com/d2/d2graph"
20 "oss.terrastruct.com/d2/d2layouts/d2dagrelayout"
21 "oss.terrastruct.com/d2/d2lib"
22 "oss.terrastruct.com/d2/d2renderers/d2svg"
23 "oss.terrastruct.com/d2/d2renderers/d2svg/appendix"
24 "oss.terrastruct.com/d2/lib/log"
25 "oss.terrastruct.com/d2/lib/textmeasure"
26 )
27
28 func TestAppendix(t *testing.T) {
29 t.Parallel()
30
31 tcs := []testCase{
32 {
33 name: "tooltip_wider_than_diagram",
34 script: `x: { tooltip: Total abstinence is easier than perfect moderation }
35 y: { tooltip: Gee, I feel kind of LIGHT in the head now,\nknowing I can't make my satellite dish PAYMENTS! }
36 x -> y
37 `,
38 },
39 {
40 name: "diagram_wider_than_tooltip",
41 script: `shape: sequence_diagram
42
43 customer
44 issuer
45 store: { tooltip: Like starbucks or something }
46 acquirer: { tooltip: I'm not sure what this is }
47 network
48 customer bank
49 store bank
50
51 customer: {shape: person}
52 customer bank: {
53 shape: image
54 icon: https://cdn-icons-png.flaticon.com/512/858/858170.png
55 }
56 store bank: {
57 shape: image
58 icon: https://cdn-icons-png.flaticon.com/512/858/858170.png
59 }
60
61 initial transaction: {
62 customer -> store: 1 banana please
63 store -> customer: '$10 dollars'
64 }
65 customer.internal -> customer.internal: "thinking: wow, inflation"
66 customer.internal -> customer bank: checks bank account
67 customer bank -> customer.internal: 'Savings: $11'
68 customer."An error in judgement is about to occur"
69 customer -> store: I can do that, here's my card
70 payment processor behind the scenes: {
71 store -> acquirer: Run this card
72 acquirer -> network: Process to card issuer
73 simplified: {
74 network -> issuer: Process this payment
75 issuer -> customer bank: '$10 debit'
76 acquirer -> store bank: '$10 credit'
77 }
78 }
79 `,
80 },
81 {
82 name: "links",
83 script: `x: { link: https://d2lang.com }
84 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! }
85 x -> y
86 `,
87 },
88 {
89 name: "links dark",
90 themeID: 200,
91 script: `x: { link: https://d2lang.com }
92 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! }
93 x -> y
94 `,
95 },
96 {
97 name: "internal-links",
98 script: `x: { link: layers.x }
99 layers: {
100 x: {
101 gooo
102 home.link: _
103 next.link: steps.next
104 steps: {
105 next: {
106 hi
107 }
108 }
109 }
110 }
111 `,
112 },
113 {
114 name: "tooltip_fill",
115 script: `x: { tooltip: Total abstinence is easier than perfect moderation }
116 y: { tooltip: Gee, I feel kind of LIGHT in the head now,\nknowing I can't make my satellite dish PAYMENTS! }
117 x -> y
118 style.fill: PaleVioletRed
119 `,
120 },
121 }
122 runa(t, tcs)
123 }
124
125 type testCase struct {
126 name string
127 themeID int64
128 script string
129 skip bool
130 }
131
132 func runa(t *testing.T, tcs []testCase) {
133 for _, tc := range tcs {
134 tc := tc
135 t.Run(tc.name, func(t *testing.T) {
136 if tc.skip {
137 t.Skip()
138 }
139 t.Parallel()
140
141 run(t, tc)
142 })
143 }
144 }
145
146 func run(t *testing.T, tc testCase) {
147 ctx := context.Background()
148 ctx = log.WithTB(ctx, t, nil)
149 ctx = log.Leveled(ctx, slog.LevelDebug)
150
151 ruler, err := textmeasure.NewRuler()
152 if !tassert.Nil(t, err) {
153 return
154 }
155
156 renderOpts := &d2svg.RenderOpts{
157 ThemeID: &tc.themeID,
158 }
159
160 layoutResolver := func(engine string) (d2graph.LayoutGraph, error) {
161 return d2dagrelayout.DefaultLayout, nil
162 }
163 diagram, _, err := d2lib.Compile(ctx, tc.script, &d2lib.CompileOptions{
164 Ruler: ruler,
165 LayoutResolver: layoutResolver,
166 }, renderOpts)
167 if !tassert.Nil(t, err) {
168 return
169 }
170
171 dataPath := filepath.Join("testdata", strings.TrimPrefix(t.Name(), "TestAppendix/"))
172 pathGotSVG := filepath.Join(dataPath, "sketch.got.svg")
173
174 svgBytes, err := d2svg.Render(diagram, renderOpts)
175 assert.Success(t, err)
176 svgBytes = appendix.Append(diagram, ruler, svgBytes)
177
178 err = os.MkdirAll(dataPath, 0755)
179 assert.Success(t, err)
180 err = ioutil.WriteFile(pathGotSVG, svgBytes, 0600)
181 assert.Success(t, err)
182 defer os.Remove(pathGotSVG)
183
184 var xmlParsed interface{}
185 err = xml.Unmarshal(svgBytes, &xmlParsed)
186 assert.Success(t, err)
187
188 err = diff.Testdata(filepath.Join(dataPath, "sketch"), ".svg", svgBytes)
189 assert.Success(t, err)
190 }
191
View as plain text