1 package d2ir_test
2
3 import (
4 "testing"
5
6 "oss.terrastruct.com/util-go/assert"
7 )
8
9 func testCompileFilters(t *testing.T) {
10 t.Parallel()
11
12 tca := []testCase{
13 {
14 name: "base",
15 run: func(t testing.TB) {
16 m, err := compile(t, `jacob: {
17 shape: circle
18 }
19 jeremy: {
20 shape: rectangle
21 }
22 *: {
23 &shape: rectangle
24 label: I'm a rectangle
25 }`)
26 assert.Success(t, err)
27 assertQuery(t, m, 1, 0, nil, "jacob")
28 assertQuery(t, m, 2, 0, nil, "jeremy")
29 assertQuery(t, m, 0, 0, "I'm a rectangle", "jeremy.label")
30 },
31 },
32 {
33 name: "order",
34 run: func(t testing.TB) {
35 m, err := compile(t, `jacob: {
36 shape: circle
37 }
38 jeremy: {
39 shape: rectangle
40 }
41 *: {
42 label: I'm a rectangle
43 &shape: rectangle
44 }`)
45 assert.Success(t, err)
46 assertQuery(t, m, 5, 0, nil, "")
47 assertQuery(t, m, 1, 0, nil, "jacob")
48 assertQuery(t, m, 2, 0, nil, "jeremy")
49 assertQuery(t, m, 0, 0, "I'm a rectangle", "jeremy.label")
50 },
51 },
52 {
53 name: "array",
54 run: func(t testing.TB) {
55 m, err := compile(t, `the-little-cannon: {
56 class: [server; deployed]
57 }
58 dino: {
59 class: [internal; deployed]
60 }
61 catapult: {
62 class: [jacob; server]
63 }
64
65 *: {
66 &class: server
67 style.multiple: true
68 }
69 `)
70 assert.Success(t, err)
71 assertQuery(t, m, 10, 0, nil, "")
72 assertQuery(t, m, 3, 0, nil, "the-little-cannon")
73 assertQuery(t, m, 1, 0, nil, "dino")
74 assertQuery(t, m, 3, 0, nil, "catapult")
75 },
76 },
77 {
78 name: "edge",
79 run: func(t testing.TB) {
80 m, err := compile(t, `x -> y: {
81 source-arrowhead.shape: diamond
82 target-arrowhead.shape: diamond
83 }
84 x -> y
85
86 (x -> *)[*]: {
87 &source-arrowhead.shape: diamond
88 &target-arrowhead.shape: diamond
89 label: diamond shape arrowheads
90 }
91 `)
92 assert.Success(t, err)
93 assertQuery(t, m, 7, 2, nil, "")
94 assertQuery(t, m, 5, 0, nil, "(x -> y)[0]")
95 assertQuery(t, m, 0, 0, "diamond shape arrowheads", "(x -> y)[0].label")
96 assertQuery(t, m, 0, 0, nil, "(x -> y)[1]")
97 },
98 },
99 {
100 name: "label-filter/1",
101 run: func(t testing.TB) {
102 m, err := compile(t, `
103 x
104 y
105 p: p
106 a -> z: delta
107
108 *.style.opacity: 0.1
109 *: {
110 &label: x
111 style.opacity: 1
112 }
113 *: {
114 &label: p
115 style.opacity: 0.5
116 }
117 (* -> *)[*]: {
118 &label: delta
119 target-arrowhead.shape: diamond
120 }
121 `)
122 assert.Success(t, err)
123 assertQuery(t, m, 17, 1, nil, "")
124 assertQuery(t, m, 0, 0, 1, "x.style.opacity")
125 assertQuery(t, m, 0, 0, 0.1, "y.style.opacity")
126 assertQuery(t, m, 0, 0, 0.5, "p.style.opacity")
127 assertQuery(t, m, 0, 0, 0.1, "a.style.opacity")
128 assertQuery(t, m, 0, 0, 0.1, "z.style.opacity")
129 assertQuery(t, m, 0, 0, "diamond", "(a -> z).target-arrowhead.shape")
130 },
131 },
132 {
133 name: "label-filter/2",
134 run: func(t testing.TB) {
135 m, err := compile(t, `
136 (* -> *)[*].style.opacity: 0.1
137
138 (* -> *)[*]: {
139 &label: hi
140 style.opacity: 1
141 }
142
143 x -> y: hi
144 x -> y
145 `)
146 assert.Success(t, err)
147 assertQuery(t, m, 6, 2, nil, "")
148 assertQuery(t, m, 2, 0, "hi", "(x -> y)[0]")
149 assertQuery(t, m, 0, 0, 1, "(x -> y)[0].style.opacity")
150 assertQuery(t, m, 0, 0, 0.1, "(x -> y)[1].style.opacity")
151 },
152 },
153 {
154 name: "lazy-filter",
155 run: func(t testing.TB) {
156 m, err := compile(t, `
157 *: {
158 &label: a
159 style.fill: yellow
160 }
161
162 a
163 # if i remove this line, the glob applies as expected
164 b
165 b.label: a
166 `)
167 assert.Success(t, err)
168 assertQuery(t, m, 7, 0, nil, "")
169 assertQuery(t, m, 0, 0, "yellow", "a.style.fill")
170 assertQuery(t, m, 0, 0, "yellow", "b.style.fill")
171 },
172 },
173 {
174 name: "primary-filter",
175 run: func(t testing.TB) {
176 m, err := compile(t, `
177 parent: {
178 a -> b1
179 a -> b2
180 a -> b3
181
182 b1 -> c1
183 b1 -> c2
184
185 c1: {
186 c1-child.class: hidden
187 }
188
189 c2: {
190 C2-child.class: hidden
191 }
192 c2.class: hidden
193 b2.class: hidden
194 }
195
196 classes: {
197 hidden: {
198 style: {
199 fill: red
200 }
201 }
202 }
203
204 # Error
205 **: null {
206 &class: hidden
207 }
208 `)
209 assert.Success(t, err)
210 assertQuery(t, m, 9, 3, nil, "")
211 },
212 },
213 }
214
215 runa(t, tca)
216
217 t.Run("errors", func(t *testing.T) {
218 tca := []testCase{
219 {
220 name: "bad-syntax",
221 run: func(t testing.TB) {
222 _, err := compile(t, `jacob.style: {
223 fill: red
224 multiple: true
225 }
226
227 *.&style: {
228 fill: red
229 multiple: true
230 }
231 `)
232 assert.ErrorString(t, err, `TestCompile/filters/errors/bad-syntax.d2:6:3: unexpected text after map key
233 TestCompile/filters/errors/bad-syntax.d2:9:1: unexpected map termination character } in file map`)
234 },
235 },
236 {
237 name: "outside-glob",
238 run: func(t testing.TB) {
239 _, err := compile(t, `jacob.style: {
240 fill: red
241 multiple: true
242 }
243 &a
244 `)
245 assert.ErrorString(t, err, `TestCompile/filters/errors/outside-glob.d2:5:1: glob filters cannot be used outside globs`)
246 },
247 },
248 {
249 name: "no-glob",
250 run: func(t testing.TB) {
251 _, err := compile(t, `jacob.style: {
252 fill: red
253 multiple: true
254 }
255
256 jasmine.style: {
257 &fill: red
258 multiple: false
259 }
260 `)
261 assert.ErrorString(t, err, `TestCompile/filters/errors/no-glob.d2:7:3: glob filters cannot be used outside globs`)
262 },
263 },
264 {
265 name: "composite",
266 run: func(t testing.TB) {
267 _, err := compile(t, `jacob.style: {
268 fill: red
269 multiple: true
270 }
271 *: {
272 &style: {
273 fill: red
274 multiple: true
275 }
276 }
277 `)
278 assert.ErrorString(t, err, `TestCompile/filters/errors/composite.d2:6:2: glob filters cannot be composites`)
279 },
280 },
281 }
282 runa(t, tca)
283 })
284 }
285
View as plain text