mirror of
				https://github.com/mermaid-js/mermaid.git
				synced 2025-10-25 00:44:10 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			461 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			461 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
 | |
| 
 | |
| describe('Entity Relationship Diagram', () => {
 | |
|   it('should render a simple ER diagram', () => {
 | |
|     imgSnapshotTest(
 | |
|       `
 | |
|     erDiagram
 | |
|         CUSTOMER ||--o{ ORDER : places
 | |
|         ORDER ||--|{ LINE-ITEM : contains
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render an ER diagram with a recursive relationship', () => {
 | |
|     imgSnapshotTest(
 | |
|       `
 | |
|     erDiagram
 | |
|         CUSTOMER ||..o{ CUSTOMER : refers
 | |
|         CUSTOMER ||--o{ ORDER : places
 | |
|         ORDER ||--|{ LINE-ITEM : contains
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render an ER diagram with multiple relationships between the same two entities', () => {
 | |
|     imgSnapshotTest(
 | |
|       `
 | |
|     erDiagram
 | |
|         CUSTOMER ||--|{ ADDRESS : "invoiced at"
 | |
|         CUSTOMER ||--|{ ADDRESS : "receives goods at"
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render a cyclical ER diagram', () => {
 | |
|     imgSnapshotTest(
 | |
|       `
 | |
|     erDiagram
 | |
|         A ||--|{ B : likes
 | |
|         B ||--|{ C : likes
 | |
|         C ||--|{ A : likes
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render a not-so-simple ER diagram', () => {
 | |
|     imgSnapshotTest(
 | |
|       `
 | |
|     erDiagram
 | |
|         CUSTOMER }|..|{ DELIVERY-ADDRESS : has
 | |
|         CUSTOMER ||--o{ ORDER : places
 | |
|         CUSTOMER ||--o{ INVOICE : "liable for"
 | |
|         DELIVERY-ADDRESS ||--o{ ORDER : receives
 | |
|         INVOICE ||--|{ ORDER : covers
 | |
|         ORDER ||--|{ ORDER-ITEM : includes
 | |
|         PRODUCT-CATEGORY ||--|{ PRODUCT : contains
 | |
|         PRODUCT ||--o{ ORDER-ITEM : "ordered in"
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render multiple ER diagrams', () => {
 | |
|     imgSnapshotTest(
 | |
|       [
 | |
|         `
 | |
|     erDiagram
 | |
|         CUSTOMER ||--o{ ORDER : places
 | |
|         ORDER ||--|{ LINE-ITEM : contains
 | |
|       `,
 | |
|         `
 | |
|     erDiagram
 | |
|         CUSTOMER ||--o{ ORDER : places
 | |
|         ORDER ||--|{ LINE-ITEM : contains
 | |
|       `,
 | |
|       ],
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render an ER diagram with blank or empty labels', () => {
 | |
|     imgSnapshotTest(
 | |
|       `
 | |
|     erDiagram
 | |
|         BOOK }|..|{ AUTHOR : ""
 | |
|         BOOK }|..|{ GENRE : " "
 | |
|         AUTHOR }|..|{ GENRE : "  "
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render an ER diagrams when useMaxWidth is true (default)', () => {
 | |
|     renderGraph(
 | |
|       `
 | |
|     erDiagram
 | |
|         CUSTOMER ||--o{ ORDER : places
 | |
|         ORDER ||--|{ LINE-ITEM : contains
 | |
|       `,
 | |
|       { er: { useMaxWidth: true } }
 | |
|     );
 | |
|     cy.get('svg').should((svg) => {
 | |
|       expect(svg).to.have.attr('width', '100%');
 | |
|       // expect(svg).to.have.attr('height', '465');
 | |
|       const style = svg.attr('style');
 | |
|       expect(style).to.match(/^max-width: [\d.]+px;$/);
 | |
|       const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
 | |
|       // use within because the absolute value can be slightly different depending on the environment ±6%
 | |
|       expect(maxWidthValue).to.be.within(140 * 0.96, 140 * 1.06);
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   it('should render an ER when useMaxWidth is false', () => {
 | |
|     renderGraph(
 | |
|       `
 | |
|     erDiagram
 | |
|         CUSTOMER ||--o{ ORDER : places
 | |
|         ORDER ||--|{ LINE-ITEM : contains
 | |
|       `,
 | |
|       { er: { useMaxWidth: false } }
 | |
|     );
 | |
|     cy.get('svg').should((svg) => {
 | |
|       const width = parseFloat(svg.attr('width'));
 | |
|       // use within because the absolute value can be slightly different depending on the environment ±6%
 | |
|       expect(width).to.be.within(140 * 0.96, 140 * 1.06);
 | |
|       // expect(svg).to.have.attr('height', '465');
 | |
|       expect(svg).to.not.have.attr('style');
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   it('should render entities that have no relationships', () => {
 | |
|     renderGraph(
 | |
|       `
 | |
|     erDiagram
 | |
|         DEAD_PARROT
 | |
|         HERMIT
 | |
|         RECLUSE
 | |
|         SOCIALITE }o--o{ SOCIALITE : "interacts with"
 | |
|         RECLUSE }o--o{ SOCIALITE : avoids
 | |
|       `,
 | |
|       { er: { useMaxWidth: false } }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render entities with and without attributes', () => {
 | |
|     renderGraph(
 | |
|       `
 | |
|     erDiagram
 | |
|         BOOK { string title }
 | |
|         AUTHOR }|..|{ BOOK : writes
 | |
|         BOOK { float price }
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render entities with generic and array attributes', () => {
 | |
|     renderGraph(
 | |
|       `
 | |
|     erDiagram
 | |
|         BOOK {
 | |
|           string title
 | |
|           string[] authors
 | |
|           type~T~ type
 | |
|         }
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render entities with length in attributes type', () => {
 | |
|     renderGraph(
 | |
|       `
 | |
|     erDiagram
 | |
|         CLUSTER {
 | |
|           varchar(99) name
 | |
|           string(255) description
 | |
|         }
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render entities and attributes with big and small entity names', () => {
 | |
|     renderGraph(
 | |
|       `
 | |
|     erDiagram
 | |
|         PRIVATE_FINANCIAL_INSTITUTION {
 | |
|           string name
 | |
|           int    turnover
 | |
|         }
 | |
|         PRIVATE_FINANCIAL_INSTITUTION ||..|{ EMPLOYEE : employs
 | |
|         EMPLOYEE { bool officer_of_firm }
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render entities with attributes that begin with asterisk', () => {
 | |
|     imgSnapshotTest(
 | |
|       `
 | |
|     erDiagram
 | |
|         BOOK {
 | |
|           int         *id
 | |
|           string      name
 | |
|           varchar(99) summary
 | |
|         }
 | |
|         BOOK }o..o{ STORE : soldBy
 | |
|         STORE {
 | |
|           int         *id
 | |
|           string      name
 | |
|           varchar(50) address
 | |
|         }
 | |
|         `,
 | |
|       { loglevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render entities with keys', () => {
 | |
|     renderGraph(
 | |
|       `
 | |
|     erDiagram
 | |
|       AUTHOR_WITH_LONG_ENTITY_NAME {
 | |
|         string name PK
 | |
|       }
 | |
|       AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
 | |
|       BOOK {
 | |
|           float price
 | |
|           string author FK
 | |
|           string title PK
 | |
|         }
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render entities with comments', () => {
 | |
|     renderGraph(
 | |
|       `
 | |
|     erDiagram
 | |
|       AUTHOR_WITH_LONG_ENTITY_NAME {
 | |
|         string name "comment"
 | |
|       }
 | |
|       AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
 | |
|       BOOK {
 | |
|           string author
 | |
|           string title "author comment"
 | |
|           float price "price comment"
 | |
|         }
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render entities with keys and comments', () => {
 | |
|     renderGraph(
 | |
|       `
 | |
|     erDiagram
 | |
|       AUTHOR_WITH_LONG_ENTITY_NAME {
 | |
|         string name PK "comment"
 | |
|       }
 | |
|       AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
 | |
|       BOOK {
 | |
|           string description
 | |
|           float price "price comment"
 | |
|           string title PK "title comment"
 | |
|           string author FK
 | |
|         }
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render entities with aliases', () => {
 | |
|     renderGraph(
 | |
|       `
 | |
|     erDiagram
 | |
|       T1 one or zero to one or more T2 : test
 | |
|       T2 one or many optionally to zero or one T3 : test
 | |
|       T3 zero or more to zero or many T4 : test
 | |
|       T4 many(0) to many(1) T5 : test
 | |
|       T5 many optionally to one T6 : test
 | |
|       T6 only one optionally to only one T1 : test
 | |
|       T4 0+ to 1+ T6 : test
 | |
|       T1 1 to 1 T3 : test
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('1433: should render a simple ER diagram with a title', () => {
 | |
|     imgSnapshotTest(
 | |
|       `---
 | |
| title: simple ER diagram
 | |
| ---
 | |
| erDiagram
 | |
| CUSTOMER ||--o{ ORDER : places
 | |
| ORDER ||--|{ LINE-ITEM : contains
 | |
| `,
 | |
|       {}
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render entities with entity name aliases', () => {
 | |
|     imgSnapshotTest(
 | |
|       `
 | |
|     erDiagram
 | |
|       p[Person] {
 | |
|         varchar(64) firstName
 | |
|         varchar(64) lastName
 | |
|       }
 | |
|       c["Customer Account"] {
 | |
|         varchar(128) email
 | |
|       }
 | |
|       p ||--o| c : has
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   it('should render relationship labels with line breaks', () => {
 | |
|     imgSnapshotTest(
 | |
|       `
 | |
|     erDiagram
 | |
|       p[Person] {
 | |
|           string firstName
 | |
|           string lastName
 | |
|       }
 | |
|       a["Customer Account"] {
 | |
|           string email
 | |
|       }
 | |
| 
 | |
|       b["Customer Account Secondary"] {
 | |
|         string email
 | |
|       }
 | |
|       
 | |
|       c["Customer Account Tertiary"] {
 | |
|         string email
 | |
|       }
 | |
|       
 | |
|       d["Customer Account Nth"] {
 | |
|         string email
 | |
|       }
 | |
| 
 | |
|       p ||--o| a : "has<br />one"
 | |
|       p ||--o| b : "has<br />one<br />two"
 | |
|       p ||--o| c : "has<br />one<br/>two<br />three"
 | |
|       p ||--o| d : "has<br />one<br />two<br/>three<br />...<br/>Nth"
 | |
|       `,
 | |
|       { logLevel: 1 }
 | |
|     );
 | |
|   });
 | |
| 
 | |
|   describe('Include char sequence "graph" in text (#6795)', () => {
 | |
|     it('has a label with char sequence "graph"', () => {
 | |
|       imgSnapshotTest(
 | |
|         `
 | |
|         erDiagram
 | |
|           p[Photograph] {
 | |
|             varchar(12) jobId
 | |
|             date dateCreated
 | |
|           }
 | |
|         `,
 | |
|         { flowchart: { defaultRenderer: 'elk' } }
 | |
|       );
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   describe('Special characters and numbers syntax', () => {
 | |
|     it('should render ER diagram with numeric entity names', () => {
 | |
|       imgSnapshotTest(
 | |
|         `
 | |
|         erDiagram
 | |
|           1 ||--|| ORDER : places
 | |
|           ORDER ||--|{ 2 : contains
 | |
|           2 ||--o{ 3.5 : references
 | |
|         `,
 | |
|         { logLevel: 1 }
 | |
|       );
 | |
|     });
 | |
| 
 | |
|     it('should render ER diagram with "u" character in entity names and cardinality', () => {
 | |
|       imgSnapshotTest(
 | |
|         `
 | |
|         erDiagram
 | |
|           CUSTOMER ||--|| u : has
 | |
|           u ||--|| ORDER : places
 | |
|           PROJECT u--o{ TEAM_MEMBER : "parent"
 | |
|         `,
 | |
|         { logLevel: 1 }
 | |
|       );
 | |
|     });
 | |
| 
 | |
|     it('should render ER diagram with decimal numbers in relationships', () => {
 | |
|       imgSnapshotTest(
 | |
|         `
 | |
|         erDiagram
 | |
|           2.5 ||--|| 1.5 : has
 | |
|           CUSTOMER ||--o{ 3.14 : references
 | |
|           1.0 ||--|{ ORDER : contains
 | |
|         `,
 | |
|         { logLevel: 1 }
 | |
|       );
 | |
|     });
 | |
| 
 | |
|     it('should render ER diagram with numeric entity names and attributes', () => {
 | |
|       imgSnapshotTest(
 | |
|         `
 | |
|         erDiagram
 | |
|           1 {
 | |
|             string name
 | |
|             int value
 | |
|           }
 | |
|           1 ||--|| ORDER : places
 | |
|           ORDER {
 | |
|             float price
 | |
|             string description
 | |
|           }
 | |
|         `,
 | |
|         { logLevel: 1 }
 | |
|       );
 | |
|     });
 | |
| 
 | |
|     it('should render complex ER diagram with mixed special entity names', () => {
 | |
|       imgSnapshotTest(
 | |
|         `
 | |
|         erDiagram
 | |
|           CUSTOMER ||--o{ 1 : places
 | |
|           1 ||--|{ u : contains
 | |
|           1.5
 | |
|           u ||--|| 2.5 : processes
 | |
|           2.5 {
 | |
|             string id
 | |
|             float value
 | |
|           }
 | |
|           u {
 | |
|             varchar(50) name
 | |
|             int count
 | |
|           }
 | |
|         `,
 | |
|         { logLevel: 1 }
 | |
|       );
 | |
|     });
 | |
|     it('should render ER diagram with numeric entity names and attributes', () => {
 | |
|       imgSnapshotTest(
 | |
|         `erDiagram
 | |
|          PRODUCT ||--o{ ORDER-ITEM : has
 | |
|          1.5
 | |
|          u
 | |
|          1
 | |
|         `,
 | |
|         { logLevel: 1 }
 | |
|       );
 | |
|     });
 | |
|   });
 | |
| });
 | 
