11.6 KB501 lines
Blame
1import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
2
3describe('Entity Relationship Diagram', () => {
4 it('should render a simple ER diagram', () => {
5 imgSnapshotTest(
6 `
7 erDiagram
8 CUSTOMER ||--o{ ORDER : places
9 ORDER ||--|{ LINE-ITEM : contains
10 `,
11 { logLevel: 1 }
12 );
13 });
14
15 it('should render an ER diagram with a recursive relationship', () => {
16 imgSnapshotTest(
17 `
18 erDiagram
19 CUSTOMER ||..o{ CUSTOMER : refers
20 CUSTOMER ||--o{ ORDER : places
21 ORDER ||--|{ LINE-ITEM : contains
22 `,
23 { logLevel: 1 }
24 );
25 });
26
27 it('should render an ER diagram with multiple relationships between the same two entities', () => {
28 imgSnapshotTest(
29 `
30 erDiagram
31 CUSTOMER ||--|{ ADDRESS : "invoiced at"
32 CUSTOMER ||--|{ ADDRESS : "receives goods at"
33 `,
34 { logLevel: 1 }
35 );
36 });
37
38 it('should render a cyclical ER diagram', () => {
39 imgSnapshotTest(
40 `
41 erDiagram
42 A ||--|{ B : likes
43 B ||--|{ C : likes
44 C ||--|{ A : likes
45 `,
46 { logLevel: 1 }
47 );
48 });
49
50 it('should render a not-so-simple ER diagram', () => {
51 imgSnapshotTest(
52 `
53 erDiagram
54 CUSTOMER }|..|{ DELIVERY-ADDRESS : has
55 CUSTOMER ||--o{ ORDER : places
56 CUSTOMER ||--o{ INVOICE : "liable for"
57 DELIVERY-ADDRESS ||--o{ ORDER : receives
58 INVOICE ||--|{ ORDER : covers
59 ORDER ||--|{ ORDER-ITEM : includes
60 PRODUCT-CATEGORY ||--|{ PRODUCT : contains
61 PRODUCT ||--o{ ORDER-ITEM : "ordered in"
62 `,
63 { logLevel: 1 }
64 );
65 });
66
67 it('should render multiple ER diagrams', () => {
68 imgSnapshotTest(
69 [
70 `
71 erDiagram
72 CUSTOMER ||--o{ ORDER : places
73 ORDER ||--|{ LINE-ITEM : contains
74 `,
75 `
76 erDiagram
77 CUSTOMER ||--o{ ORDER : places
78 ORDER ||--|{ LINE-ITEM : contains
79 `,
80 ],
81 { logLevel: 1 }
82 );
83 });
84
85 it('should render an ER diagram with blank or empty labels', () => {
86 imgSnapshotTest(
87 `
88 erDiagram
89 BOOK }|..|{ AUTHOR : ""
90 BOOK }|..|{ GENRE : " "
91 AUTHOR }|..|{ GENRE : " "
92 `,
93 { logLevel: 1 }
94 );
95 });
96
97 it('should render an ER diagrams when useMaxWidth is true (default)', () => {
98 renderGraph(
99 `
100 erDiagram
101 CUSTOMER ||--o{ ORDER : places
102 ORDER ||--|{ LINE-ITEM : contains
103 `,
104 { er: { useMaxWidth: true } }
105 );
106 cy.get('svg').should((svg) => {
107 expect(svg).to.have.attr('width', '100%');
108 // expect(svg).to.have.attr('height', '465');
109 const style = svg.attr('style');
110 expect(style).to.match(/^max-width: [\d.]+px;$/);
111 const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
112 // use within because the absolute value can be slightly different depending on the environment ±6%
113 expect(maxWidthValue).to.be.within(140 * 0.96, 140 * 1.06);
114 });
115 });
116
117 it('should render an ER when useMaxWidth is false', () => {
118 renderGraph(
119 `
120 erDiagram
121 CUSTOMER ||--o{ ORDER : places
122 ORDER ||--|{ LINE-ITEM : contains
123 `,
124 { er: { useMaxWidth: false } }
125 );
126 cy.get('svg').should((svg) => {
127 const width = parseFloat(svg.attr('width'));
128 // use within because the absolute value can be slightly different depending on the environment ±6%
129 expect(width).to.be.within(140 * 0.96, 140 * 1.06);
130 // expect(svg).to.have.attr('height', '465');
131 expect(svg).to.not.have.attr('style');
132 });
133 });
134
135 it('should render entities that have no relationships', () => {
136 renderGraph(
137 `
138 erDiagram
139 DEAD_PARROT
140 HERMIT
141 RECLUSE
142 SOCIALITE }o--o{ SOCIALITE : "interacts with"
143 RECLUSE }o--o{ SOCIALITE : avoids
144 `,
145 { er: { useMaxWidth: false } }
146 );
147 });
148
149 it('should render entities with and without attributes', () => {
150 renderGraph(
151 `
152 erDiagram
153 BOOK { string title }
154 AUTHOR }|..|{ BOOK : writes
155 BOOK { float price }
156 `,
157 { logLevel: 1 }
158 );
159 });
160
161 it('should render entities with generic and array attributes', () => {
162 renderGraph(
163 `
164 erDiagram
165 BOOK {
166 string title
167 string[] authors
168 type~T~ type
169 }
170 `,
171 { logLevel: 1 }
172 );
173 });
174
175 it('should render entities with length in attributes type', () => {
176 renderGraph(
177 `
178 erDiagram
179 CLUSTER {
180 varchar(99) name
181 string(255) description
182 }
183 `,
184 { logLevel: 1 }
185 );
186 });
187
188 it('should render entities and attributes with big and small entity names', () => {
189 renderGraph(
190 `
191 erDiagram
192 PRIVATE_FINANCIAL_INSTITUTION {
193 string name
194 int turnover
195 }
196 PRIVATE_FINANCIAL_INSTITUTION ||..|{ EMPLOYEE : employs
197 EMPLOYEE { bool officer_of_firm }
198 `,
199 { logLevel: 1 }
200 );
201 });
202
203 it('should render entities with attributes that begin with asterisk', () => {
204 imgSnapshotTest(
205 `
206 erDiagram
207 BOOK {
208 int *id
209 string name
210 varchar(99) summary
211 }
212 BOOK }o..o{ STORE : soldBy
213 STORE {
214 int *id
215 string name
216 varchar(50) address
217 }
218 `,
219 { loglevel: 1 }
220 );
221 });
222
223 it('should render entities with keys', () => {
224 renderGraph(
225 `
226 erDiagram
227 AUTHOR_WITH_LONG_ENTITY_NAME {
228 string name PK
229 }
230 AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
231 BOOK {
232 float price
233 string author FK
234 string title PK
235 }
236 `,
237 { logLevel: 1 }
238 );
239 });
240
241 it('should render entities with comments', () => {
242 renderGraph(
243 `
244 erDiagram
245 AUTHOR_WITH_LONG_ENTITY_NAME {
246 string name "comment"
247 }
248 AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
249 BOOK {
250 string author
251 string title "author comment"
252 float price "price comment"
253 }
254 `,
255 { logLevel: 1 }
256 );
257 });
258
259 it('should render entities with keys and comments', () => {
260 renderGraph(
261 `
262 erDiagram
263 AUTHOR_WITH_LONG_ENTITY_NAME {
264 string name PK "comment"
265 }
266 AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
267 BOOK {
268 string description
269 float price "price comment"
270 string title PK "title comment"
271 string author FK
272 }
273 `,
274 { logLevel: 1 }
275 );
276 });
277
278 it('should render entities with aliases', () => {
279 renderGraph(
280 `
281 erDiagram
282 T1 one or zero to one or more T2 : test
283 T2 one or many optionally to zero or one T3 : test
284 T3 zero or more to zero or many T4 : test
285 T4 many(0) to many(1) T5 : test
286 T5 many optionally to one T6 : test
287 T6 only one optionally to only one T1 : test
288 T4 0+ to 1+ T6 : test
289 T1 1 to 1 T3 : test
290 `,
291 { logLevel: 1 }
292 );
293 });
294
295 it('1433: should render a simple ER diagram with a title', () => {
296 imgSnapshotTest(
297 `---
298title: simple ER diagram
299---
300erDiagram
301CUSTOMER ||--o{ ORDER : places
302ORDER ||--|{ LINE-ITEM : contains
303`,
304 {}
305 );
306 });
307
308 it('should render entities with entity name aliases', () => {
309 imgSnapshotTest(
310 `
311 erDiagram
312 p[Person] {
313 varchar(64) firstName
314 varchar(64) lastName
315 }
316 c["Customer Account"] {
317 varchar(128) email
318 }
319 p ||--o| c : has
320 `,
321 { logLevel: 1 }
322 );
323 });
324
325 it('should render relationship labels with line breaks', () => {
326 imgSnapshotTest(
327 `
328 erDiagram
329 p[Person] {
330 string firstName
331 string lastName
332 }
333 a["Customer Account"] {
334 string email
335 }
336
337 b["Customer Account Secondary"] {
338 string email
339 }
340
341 c["Customer Account Tertiary"] {
342 string email
343 }
344
345 d["Customer Account Nth"] {
346 string email
347 }
348
349 p ||--o| a : "has<br />one"
350 p ||--o| b : "has<br />one<br />two"
351 p ||--o| c : "has<br />one<br/>two<br />three"
352 p ||--o| d : "has<br />one<br />two<br/>three<br />...<br/>Nth"
353 `,
354 { logLevel: 1 }
355 );
356 });
357
358 describe('Include char sequence "graph" in text (#6795)', () => {
359 it('has a label with char sequence "graph"', () => {
360 imgSnapshotTest(
361 `
362 erDiagram
363 p[Photograph] {
364 varchar(12) jobId
365 date dateCreated
366 }
367 `,
368 { flowchart: { defaultRenderer: 'elk' } }
369 );
370 });
371 });
372
373 describe('Special characters and numbers syntax', () => {
374 it('should render ER diagram with numeric entity names', () => {
375 imgSnapshotTest(
376 `
377 erDiagram
378 1 ||--|| ORDER : places
379 ORDER ||--|{ 2 : contains
380 2 ||--o{ 3.5 : references
381 `,
382 { logLevel: 1 }
383 );
384 });
385
386 it('should render ER diagram with "u" character in entity names and cardinality', () => {
387 imgSnapshotTest(
388 `
389 erDiagram
390 CUSTOMER ||--|| u : has
391 u ||--|| ORDER : places
392 PROJECT u--o{ TEAM_MEMBER : "parent"
393 `,
394 { logLevel: 1 }
395 );
396 });
397
398 it('should render ER diagram with decimal numbers in relationships', () => {
399 imgSnapshotTest(
400 `
401 erDiagram
402 2.5 ||--|| 1.5 : has
403 CUSTOMER ||--o{ 3.14 : references
404 1.0 ||--|{ ORDER : contains
405 `,
406 { logLevel: 1 }
407 );
408 });
409
410 it('should render ER diagram with numeric entity names and attributes', () => {
411 imgSnapshotTest(
412 `
413 erDiagram
414 1 {
415 string name
416 int value
417 }
418 1 ||--|| ORDER : places
419 ORDER {
420 float price
421 string description
422 }
423 `,
424 { logLevel: 1 }
425 );
426 });
427
428 it('should render complex ER diagram with mixed special entity names', () => {
429 imgSnapshotTest(
430 `
431 erDiagram
432 CUSTOMER ||--o{ 1 : places
433 1 ||--|{ u : contains
434 1.5
435 u ||--|| 2.5 : processes
436 2.5 {
437 string id
438 float value
439 }
440 u {
441 varchar(50) name
442 int count
443 }
444 `,
445 { logLevel: 1 }
446 );
447 });
448 it('should render ER diagram with standalone numeric entities', () => {
449 imgSnapshotTest(
450 `erDiagram
451 PRODUCT ||--o{ ORDER-ITEM : has
452 1.5
453 u
454 1
455 `,
456 { logLevel: 1 }
457 );
458 });
459 });
460
461 it('should render edge labels correctly when flowchart htmlLabels is false', () => {
462 imgSnapshotTest(
463 `
464 erDiagram
465 CUSTOMER ||--o{ ORDER : places
466 ORDER ||--|{ LINE-ITEM : contains
467 CUSTOMER ||--|{ ADDRESS : "invoiced at"
468 CUSTOMER ||--|{ ADDRESS : "receives goods at"
469 ORDER ||--o{ INVOICE : "liable for"
470 `,
471 { logLevel: 1, flowchart: { htmlLabels: false } }
472 );
473 });
474
475 it('should render ER diagram with "1" cardinality alias before relationship operators', () => {
476 imgSnapshotTest(
477 `
478 erDiagram
479 CUSTOMER 1--1 ORDER : "exactly one"
480 ORDER 1--o{ LINE-ITEM : "one to many"
481 PRODUCT 1--|{ CATEGORY : "one or more"
482 USER 1..1 PROFILE : "exactly one optional"
483 `,
484 { logLevel: 1 }
485 );
486 });
487
488 it('should render ER diagram with "1" cardinality using all 4 relationship operator styles', () => {
489 imgSnapshotTest(
490 `
491 erDiagram
492 A 1--1 B : "solid-solid"
493 C 1..1 D : "dotted-dotted"
494 E 1.-1 F : "dotted-solid"
495 G 1-.1 H : "solid-dotted"
496 `,
497 { logLevel: 1 }
498 );
499 });
500});
501