mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-08-22 09:46:42 +02:00
Add e2e tests on all diagrams
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
/* eslint-env jest */
|
/* eslint-env jest */
|
||||||
|
/* global cy */
|
||||||
import { Base64 } from 'js-base64';
|
import { Base64 } from 'js-base64';
|
||||||
|
|
||||||
export const mermaidUrl = (graphStr, options, api) => {
|
export const mermaidUrl = (graphStr, options, api) => {
|
||||||
|
@@ -354,7 +354,7 @@ describe('Class diagram', () => {
|
|||||||
cy.get('svg');
|
cy.get('svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('17: should render a class diagrams when useMaxWidth is true (default)', () => {
|
it('17: should render a class diagram when useMaxWidth is true (default)', () => {
|
||||||
renderGraph(
|
renderGraph(
|
||||||
`
|
`
|
||||||
classDiagram
|
classDiagram
|
||||||
@@ -369,12 +369,18 @@ describe('Class diagram', () => {
|
|||||||
{ class: { useMaxWidth: true } }
|
{ class: { useMaxWidth: true } }
|
||||||
);
|
);
|
||||||
cy.get('svg')
|
cy.get('svg')
|
||||||
.should('have.attr', 'width', '100%')
|
.should((svg) => {
|
||||||
.should('have.attr', 'height', '218')
|
expect(svg).to.have.attr('width', '100%');
|
||||||
.should('have.attr', 'style', 'max-width: 162.28125px;')
|
expect(svg).to.have.attr('height', '218');
|
||||||
|
const style = svg.attr('style');
|
||||||
|
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||||
|
const maxWidthValue = parseInt(style.match(/[\d.]+/g).join(''));
|
||||||
|
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||||
|
expect(maxWidthValue).to.be.within(160 * .95, 160 * 1.05);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('18: should render a class diagrams when useMaxWidth is false', () => {
|
it('18: should render a class diagram when useMaxWidth is false', () => {
|
||||||
renderGraph(
|
renderGraph(
|
||||||
`
|
`
|
||||||
classDiagram
|
classDiagram
|
||||||
@@ -389,8 +395,12 @@ describe('Class diagram', () => {
|
|||||||
{ class: { useMaxWidth: false } }
|
{ class: { useMaxWidth: false } }
|
||||||
);
|
);
|
||||||
cy.get('svg')
|
cy.get('svg')
|
||||||
.should('have.attr', 'width', '162.28125')
|
.should((svg) => {
|
||||||
.should('have.attr', 'height', '218')
|
const width = parseFloat(svg.attr('width'));
|
||||||
.should('not.have.attr', 'style')
|
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||||
|
expect(width).to.be.within(160 * .95, 160 * 1.05);
|
||||||
|
expect(svg).to.have.attr('height', '218');
|
||||||
|
expect(svg).to.not.have.attr('style');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-env jest */
|
/* eslint-env jest */
|
||||||
import { imgSnapshotTest } from '../../helpers/util';
|
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
|
||||||
|
|
||||||
describe('Entity Relationship Diagram', () => {
|
describe('Entity Relationship Diagram', () => {
|
||||||
it('should render a simple ER diagram', () => {
|
it('should render a simple ER diagram', () => {
|
||||||
@@ -101,4 +101,44 @@ describe('Entity Relationship Diagram', () => {
|
|||||||
);
|
);
|
||||||
cy.get('svg');
|
cy.get('svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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 ±5%
|
||||||
|
expect(maxWidthValue).to.be.within(140 * .95, 140 * 1.05);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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 ±5%
|
||||||
|
expect(width).to.be.within(140 * .95, 140 * 1.05);
|
||||||
|
expect(svg).to.have.attr('height', '465');
|
||||||
|
expect(svg).to.not.have.attr('style');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-env jest */
|
/* eslint-env jest */
|
||||||
import { imgSnapshotTest } from '../../helpers/util';
|
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
|
||||||
|
|
||||||
describe('Flowchart v2', () => {
|
describe('Flowchart v2', () => {
|
||||||
it('1: should render a simple flowchart', () => {
|
it('1: should render a simple flowchart', () => {
|
||||||
@@ -47,7 +47,7 @@ describe('Flowchart v2', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Length of edges', () => {
|
it('4: Length of edges', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`flowchart TD
|
`flowchart TD
|
||||||
L1 --- L2
|
L1 --- L2
|
||||||
@@ -64,7 +64,7 @@ describe('Flowchart v2', () => {
|
|||||||
{ flowchart: { diagramPadding: 0 } }
|
{ flowchart: { diagramPadding: 0 } }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('36: should render escaped without html labels', () => {
|
it('5: should render escaped without html labels', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`flowchart TD
|
`flowchart TD
|
||||||
a["<strong>Haiya</strong>"]---->b
|
a["<strong>Haiya</strong>"]---->b
|
||||||
@@ -72,13 +72,57 @@ describe('Flowchart v2', () => {
|
|||||||
{htmlLabels: false, flowchart: {htmlLabels: false}}
|
{htmlLabels: false, flowchart: {htmlLabels: false}}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('37: should render non-escaped with html labels', () => {
|
it('6: should render non-escaped with html labels', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`flowchart TD
|
`flowchart TD
|
||||||
a["<strong>Haiya</strong>"]===>b
|
a["<strong>Haiya</strong>"]===>b
|
||||||
`,
|
`,
|
||||||
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
|
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
|
||||||
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
it('7: should render a flowchart when useMaxWidth is true (default)', () => {
|
||||||
|
renderGraph(
|
||||||
|
`flowchart TD
|
||||||
|
A[Christmas] -->|Get money| B(Go shopping)
|
||||||
|
B --> C{Let me think}
|
||||||
|
C -->|One| D[Laptop]
|
||||||
|
C -->|Two| E[iPhone]
|
||||||
|
C -->|Three| F[fa:fa-car Car]
|
||||||
|
`,
|
||||||
|
{ flowchart: { useMaxWidth: true } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
expect(svg).to.have.attr('width', '100%');
|
||||||
|
expect(svg).to.have.attr('height');
|
||||||
|
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
expect(height).to.be.within(446 * .95, 446 * 1.05);
|
||||||
|
const style = svg.attr('style');
|
||||||
|
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||||
|
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||||
|
expect(maxWidthValue).to.be.within(300 * .95, 300 * 1.05);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('8: should render a flowchart when useMaxWidth is false', () => {
|
||||||
|
renderGraph(
|
||||||
|
`flowchart TD
|
||||||
|
A[Christmas] -->|Get money| B(Go shopping)
|
||||||
|
B --> C{Let me think}
|
||||||
|
C -->|One| D[Laptop]
|
||||||
|
C -->|Two| E[iPhone]
|
||||||
|
C -->|Three| F[fa:fa-car Car]
|
||||||
|
`,
|
||||||
|
{ flowchart: { useMaxWidth: false } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
const width = parseFloat(svg.attr('width'));
|
||||||
|
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||||
|
expect(height).to.be.within(446 * .95, 446 * 1.05);
|
||||||
|
expect(width).to.be.within(300 * .95, 300 * 1.05);
|
||||||
|
expect(svg).to.not.have.attr('style');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-env jest */
|
/* eslint-env jest */
|
||||||
import { imgSnapshotTest } from '../../helpers/util';
|
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
|
||||||
|
|
||||||
describe('Flowchart', () => {
|
describe('Flowchart', () => {
|
||||||
it('1: should render a simple flowchart no htmlLabels', () => {
|
it('1: should render a simple flowchart no htmlLabels', () => {
|
||||||
@@ -731,4 +731,49 @@ describe('Flowchart', () => {
|
|||||||
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
|
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
it('38: should render a flowchart when useMaxWidth is true (default)', () => {
|
||||||
|
renderGraph(
|
||||||
|
`graph TD
|
||||||
|
A[Christmas] -->|Get money| B(Go shopping)
|
||||||
|
B --> C{Let me think}
|
||||||
|
C -->|One| D[Laptop]
|
||||||
|
C -->|Two| E[iPhone]
|
||||||
|
C -->|Three| F[fa:fa-car Car]
|
||||||
|
`,
|
||||||
|
{ flowchart: { useMaxWidth: true } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
expect(svg).to.have.attr('width', '100%');
|
||||||
|
expect(svg).to.have.attr('height');
|
||||||
|
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
expect(height).to.be.within(446 * .95, 446 * 1.05);
|
||||||
|
const style = svg.attr('style');
|
||||||
|
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||||
|
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||||
|
expect(maxWidthValue).to.be.within(300 * .95, 300 * 1.05);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('39: should render a flowchart when useMaxWidth is false', () => {
|
||||||
|
renderGraph(
|
||||||
|
`graph TD
|
||||||
|
A[Christmas] -->|Get money| B(Go shopping)
|
||||||
|
B --> C{Let me think}
|
||||||
|
C -->|One| D[Laptop]
|
||||||
|
C -->|Two| E[iPhone]
|
||||||
|
C -->|Three| F[fa:fa-car Car]
|
||||||
|
`,
|
||||||
|
{ flowchart: { useMaxWidth: false } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
const width = parseFloat(svg.attr('width'));
|
||||||
|
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||||
|
expect(height).to.be.within(446 * .95, 446 * 1.05);
|
||||||
|
expect(width).to.be.within(300 * .95, 300 * 1.05);
|
||||||
|
expect(svg).to.not.have.attr('style');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-env jest */
|
/* eslint-env jest */
|
||||||
import { imgSnapshotTest } from '../../helpers/util.js';
|
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||||
|
|
||||||
describe('Gantt diagram', () => {
|
describe('Gantt diagram', () => {
|
||||||
beforeEach(()=>{
|
beforeEach(()=>{
|
||||||
@@ -163,4 +163,99 @@ describe('Gantt diagram', () => {
|
|||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should render a gantt diagram when useMaxWidth is true (default)', () => {
|
||||||
|
renderGraph(
|
||||||
|
`
|
||||||
|
gantt
|
||||||
|
dateFormat YYYY-MM-DD
|
||||||
|
axisFormat %d/%m
|
||||||
|
title Adding GANTT diagram to mermaid
|
||||||
|
excludes weekdays 2014-01-10
|
||||||
|
|
||||||
|
section A section
|
||||||
|
Completed task :done, des1, 2014-01-06,2014-01-08
|
||||||
|
Active task :active, des2, 2014-01-09, 3d
|
||||||
|
Future task : des3, after des2, 5d
|
||||||
|
Future task2 : des4, after des3, 5d
|
||||||
|
|
||||||
|
section Critical tasks
|
||||||
|
Completed task in the critical line :crit, done, 2014-01-06,24h
|
||||||
|
Implement parser and jison :crit, done, after des1, 2d
|
||||||
|
Create tests for parser :crit, active, 3d
|
||||||
|
Future task in critical line :crit, 5d
|
||||||
|
Create tests for renderer :2d
|
||||||
|
Add to mermaid :1d
|
||||||
|
|
||||||
|
section Documentation
|
||||||
|
Describe gantt syntax :active, a1, after des1, 3d
|
||||||
|
Add gantt diagram to demo page :after a1 , 20h
|
||||||
|
Add another diagram to demo page :doc1, after a1 , 48h
|
||||||
|
|
||||||
|
section Last section
|
||||||
|
Describe gantt syntax :after doc1, 3d
|
||||||
|
Add gantt diagram to demo page : 20h
|
||||||
|
Add another diagram to demo page : 48h
|
||||||
|
`,
|
||||||
|
{ gantt: { useMaxWidth: true } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
expect(svg).to.have.attr('width', '100%');
|
||||||
|
expect(svg).to.have.attr('height');
|
||||||
|
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
expect(height).to.be.within(484 * .95, 484 * 1.05);
|
||||||
|
const style = svg.attr('style');
|
||||||
|
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||||
|
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||||
|
expect(maxWidthValue).to.be.within(984 * .95, 984 * 1.05);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render a gantt diagram when useMaxWidth is false', () => {
|
||||||
|
renderGraph(
|
||||||
|
`
|
||||||
|
gantt
|
||||||
|
dateFormat YYYY-MM-DD
|
||||||
|
axisFormat %d/%m
|
||||||
|
title Adding GANTT diagram to mermaid
|
||||||
|
excludes weekdays 2014-01-10
|
||||||
|
|
||||||
|
section A section
|
||||||
|
Completed task :done, des1, 2014-01-06,2014-01-08
|
||||||
|
Active task :active, des2, 2014-01-09, 3d
|
||||||
|
Future task : des3, after des2, 5d
|
||||||
|
Future task2 : des4, after des3, 5d
|
||||||
|
|
||||||
|
section Critical tasks
|
||||||
|
Completed task in the critical line :crit, done, 2014-01-06,24h
|
||||||
|
Implement parser and jison :crit, done, after des1, 2d
|
||||||
|
Create tests for parser :crit, active, 3d
|
||||||
|
Future task in critical line :crit, 5d
|
||||||
|
Create tests for renderer :2d
|
||||||
|
Add to mermaid :1d
|
||||||
|
|
||||||
|
section Documentation
|
||||||
|
Describe gantt syntax :active, a1, after des1, 3d
|
||||||
|
Add gantt diagram to demo page :after a1 , 20h
|
||||||
|
Add another diagram to demo page :doc1, after a1 , 48h
|
||||||
|
|
||||||
|
section Last section
|
||||||
|
Describe gantt syntax :after doc1, 3d
|
||||||
|
Add gantt diagram to demo page : 20h
|
||||||
|
Add another diagram to demo page : 48h
|
||||||
|
`,
|
||||||
|
{ gantt: { useMaxWidth: false } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
const width = parseFloat(svg.attr('width'));
|
||||||
|
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||||
|
expect(height).to.be.within(484 * .95, 484 * 1.05);
|
||||||
|
expect(width).to.be.within(984 * .95, 984 * 1.05);
|
||||||
|
expect(svg).to.not.have.attr('style');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-env jest */
|
/* eslint-env jest */
|
||||||
import { imgSnapshotTest } from '../../helpers/util.js';
|
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||||
|
|
||||||
describe('User journey diagram', () => {
|
describe('User journey diagram', () => {
|
||||||
it('Simple test', () => {
|
it('Simple test', () => {
|
||||||
@@ -28,4 +28,43 @@ section Order from website
|
|||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should render a user journey diagram when useMaxWidth is true (default)', () => {
|
||||||
|
renderGraph(
|
||||||
|
`journey
|
||||||
|
title Adding journey diagram functionality to mermaid
|
||||||
|
section Order from website
|
||||||
|
`,
|
||||||
|
{ journey: { useMaxWidth: true } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
expect(svg).to.have.attr('width', '100%');
|
||||||
|
expect(svg).to.have.attr('height');
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
expect(height).to.eq(20);
|
||||||
|
const style = svg.attr('style');
|
||||||
|
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||||
|
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||||
|
expect(maxWidthValue).to.eq(400);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render a user journey diagram when useMaxWidth is false', () => {
|
||||||
|
renderGraph(
|
||||||
|
`journey
|
||||||
|
title Adding journey diagram functionality to mermaid
|
||||||
|
section Order from website
|
||||||
|
`,
|
||||||
|
{ journey: { useMaxWidth: false } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
const width = parseFloat(svg.attr('width'));
|
||||||
|
expect(height).to.eq(20);
|
||||||
|
expect(width).to.eq(400);
|
||||||
|
expect(svg).to.not.have.attr('style');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-env jest */
|
/* eslint-env jest */
|
||||||
import { imgSnapshotTest } from '../../helpers/util.js';
|
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
|
||||||
|
|
||||||
describe('Pie Chart', () => {
|
describe('Pie Chart', () => {
|
||||||
it('should render a simple pie diagram', () => {
|
it('should render a simple pie diagram', () => {
|
||||||
@@ -37,4 +37,45 @@ describe('Pie Chart', () => {
|
|||||||
);
|
);
|
||||||
cy.get('svg');
|
cy.get('svg');
|
||||||
});
|
});
|
||||||
|
it('should render a pie diagram when useMaxWidth is true (default)', () => {
|
||||||
|
renderGraph(
|
||||||
|
`
|
||||||
|
pie title Sports in Sweden
|
||||||
|
"Bandy" : 40
|
||||||
|
"Ice-Hockey" : 80
|
||||||
|
"Football" : 90
|
||||||
|
`,
|
||||||
|
{ pie: { useMaxWidth: true } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
expect(svg).to.have.attr('width', '100%');
|
||||||
|
expect(svg).to.have.attr('height');
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
expect(height).to.eq(450);
|
||||||
|
const style = svg.attr('style');
|
||||||
|
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||||
|
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||||
|
expect(maxWidthValue).to.eq(984);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should render a pie diagram when useMaxWidth is false', () => {
|
||||||
|
renderGraph(
|
||||||
|
`
|
||||||
|
pie title Sports in Sweden
|
||||||
|
"Bandy" : 40
|
||||||
|
"Ice-Hockey" : 80
|
||||||
|
"Football" : 90
|
||||||
|
`,
|
||||||
|
{ pie: { useMaxWidth: false } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
const width = parseFloat(svg.attr('width'));
|
||||||
|
expect(height).to.eq(450);
|
||||||
|
expect(width).to.eq(984);
|
||||||
|
expect(svg).to.not.have.attr('style');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/// <reference types="Cypress" />
|
/// <reference types="Cypress" />
|
||||||
|
|
||||||
import { imgSnapshotTest } from '../../helpers/util';
|
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
|
||||||
|
|
||||||
context('Sequence diagram', () => {
|
context('Sequence diagram', () => {
|
||||||
it('should render a simple sequence diagram', () => {
|
it('should render a simple sequence diagram', () => {
|
||||||
@@ -505,7 +505,7 @@ context('Sequence diagram', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
context('directives', () => {
|
context('directives', () => {
|
||||||
it('should overide config with directive settings', () => {
|
it('should override config with directive settings', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
%%{init: { "config": { "mirrorActors": true }}}%%
|
%%{init: { "config": { "mirrorActors": true }}}%%
|
||||||
@@ -517,7 +517,7 @@ context('Sequence diagram', () => {
|
|||||||
{ logLevel:0, sequence: { mirrorActors: false, noteFontSize: 18, noteFontFamily: 'Arial' } }
|
{ logLevel:0, sequence: { mirrorActors: false, noteFontSize: 18, noteFontFamily: 'Arial' } }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('should overide config with directive settings', () => {
|
it('should override config with directive settings', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
%%{init: { "config": { "mirrorActors": false, "wrap": true }}}%%
|
%%{init: { "config": { "mirrorActors": false, "wrap": true }}}%%
|
||||||
@@ -530,4 +530,85 @@ context('Sequence diagram', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
context('svg size', () => {
|
||||||
|
it('should render a sequence diagram when useMaxWidth is true (default)', () => {
|
||||||
|
renderGraph(
|
||||||
|
`
|
||||||
|
sequenceDiagram
|
||||||
|
participant Alice
|
||||||
|
participant Bob
|
||||||
|
participant John as John<br/>Second Line
|
||||||
|
Alice ->> Bob: Hello Bob, how are you?
|
||||||
|
Bob-->>John: How about you John?
|
||||||
|
Bob--x Alice: I am good thanks!
|
||||||
|
Bob-x John: I am good thanks!
|
||||||
|
Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
|
||||||
|
Bob-->Alice: Checking with John...
|
||||||
|
alt either this
|
||||||
|
Alice->>John: Yes
|
||||||
|
else or this
|
||||||
|
Alice->>John: No
|
||||||
|
else or this will happen
|
||||||
|
Alice->John: Maybe
|
||||||
|
end
|
||||||
|
par this happens in parallel
|
||||||
|
Alice -->> Bob: Parallel message 1
|
||||||
|
and
|
||||||
|
Alice -->> John: Parallel message 2
|
||||||
|
end
|
||||||
|
`,
|
||||||
|
{ sequence: { useMaxWidth: true } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
expect(svg).to.have.attr('width', '100%');
|
||||||
|
expect(svg).to.have.attr('height');
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
expect(height).to.eq(920);
|
||||||
|
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 ±5%
|
||||||
|
expect(maxWidthValue).to.be.within(820 * .95, 820 * 1.05);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should render a sequence diagram when useMaxWidth is false', () => {
|
||||||
|
renderGraph(
|
||||||
|
`
|
||||||
|
sequenceDiagram
|
||||||
|
participant Alice
|
||||||
|
participant Bob
|
||||||
|
participant John as John<br/>Second Line
|
||||||
|
Alice ->> Bob: Hello Bob, how are you?
|
||||||
|
Bob-->>John: How about you John?
|
||||||
|
Bob--x Alice: I am good thanks!
|
||||||
|
Bob-x John: I am good thanks!
|
||||||
|
Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
|
||||||
|
Bob-->Alice: Checking with John...
|
||||||
|
alt either this
|
||||||
|
Alice->>John: Yes
|
||||||
|
else or this
|
||||||
|
Alice->>John: No
|
||||||
|
else or this will happen
|
||||||
|
Alice->John: Maybe
|
||||||
|
end
|
||||||
|
par this happens in parallel
|
||||||
|
Alice -->> Bob: Parallel message 1
|
||||||
|
and
|
||||||
|
Alice -->> John: Parallel message 2
|
||||||
|
end
|
||||||
|
`,
|
||||||
|
{ sequence: { useMaxWidth: false } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
const width = parseFloat(svg.attr('width'));
|
||||||
|
expect(height).to.eq(920);
|
||||||
|
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||||
|
expect(width).to.be.within(820 * .95, 820 * 1.05);
|
||||||
|
expect(svg).to.not.have.attr('style');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-env jest */
|
/* eslint-env jest */
|
||||||
import { imgSnapshotTest } from '../../helpers/util';
|
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
|
||||||
|
|
||||||
describe('State diagram', () => {
|
describe('State diagram', () => {
|
||||||
it('v2 should render a simple info', () => {
|
it('v2 should render a simple info', () => {
|
||||||
@@ -47,7 +47,7 @@ describe('State diagram', () => {
|
|||||||
);
|
);
|
||||||
cy.get('svg');
|
cy.get('svg');
|
||||||
});
|
});
|
||||||
it('v2 should render a single state with short descr', () => {
|
it('v2 should render a single state with short descriptions', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
stateDiagram-v2
|
stateDiagram-v2
|
||||||
@@ -58,7 +58,7 @@ describe('State diagram', () => {
|
|||||||
);
|
);
|
||||||
cy.get('svg');
|
cy.get('svg');
|
||||||
});
|
});
|
||||||
it('v2 should render a transition descrions with new lines', () => {
|
it('v2 should render a transition descriptions with new lines', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
stateDiagram-v2
|
stateDiagram-v2
|
||||||
@@ -201,7 +201,7 @@ describe('State diagram', () => {
|
|||||||
);
|
);
|
||||||
cy.get('svg');
|
cy.get('svg');
|
||||||
});
|
});
|
||||||
it('v2 should render composit states', () => {
|
it('v2 should render composite states', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
stateDiagram-v2
|
stateDiagram-v2
|
||||||
@@ -220,7 +220,7 @@ describe('State diagram', () => {
|
|||||||
);
|
);
|
||||||
cy.get('svg');
|
cy.get('svg');
|
||||||
});
|
});
|
||||||
it('v2 should render multiple composit states', () => {
|
it('v2 should render multiple composite states', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
stateDiagram-v2
|
stateDiagram-v2
|
||||||
@@ -249,7 +249,7 @@ describe('State diagram', () => {
|
|||||||
{ logLevel: 0, fontFamily: 'courier' }
|
{ logLevel: 0, fontFamily: 'courier' }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('v2 should render forks in composit states', () => {
|
it('v2 should render forks in composite states', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
stateDiagram-v2
|
stateDiagram-v2
|
||||||
@@ -329,7 +329,7 @@ describe('State diagram', () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('v2 Simplest composit state', () => {
|
it('v2 Simplest composite state', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
stateDiagram-v2
|
stateDiagram-v2
|
||||||
@@ -354,5 +354,47 @@ describe('State diagram', () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
it('v2 should render a state diagram when useMaxWidth is true (default)', () => {
|
||||||
|
renderGraph(
|
||||||
|
`
|
||||||
|
stateDiagram-v2
|
||||||
|
|
||||||
|
[*] --> State1
|
||||||
|
State1 --> [*]
|
||||||
|
`,
|
||||||
|
{ state: { useMaxWidth: true } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
expect(svg).to.have.attr('width', '100%');
|
||||||
|
expect(svg).to.have.attr('height');
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
expect(height).to.eq(177);
|
||||||
|
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 ±5%
|
||||||
|
expect(maxWidthValue).to.be.within(135 * .95, 135 * 1.05);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('v2 should render a state diagram when useMaxWidth is false', () => {
|
||||||
|
renderGraph(
|
||||||
|
`
|
||||||
|
stateDiagram-v2
|
||||||
|
|
||||||
|
[*] --> State1
|
||||||
|
State1 --> [*]
|
||||||
|
`,
|
||||||
|
{ state: { useMaxWidth: false } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
const width = parseFloat(svg.attr('width'));
|
||||||
|
expect(height).to.eq(177);
|
||||||
|
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||||
|
expect(width).to.be.within(135 * .95, 135 * 1.05);
|
||||||
|
expect(svg).to.not.have.attr('style');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-env jest */
|
/* eslint-env jest */
|
||||||
import { imgSnapshotTest } from '../../helpers/util';
|
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
|
||||||
|
|
||||||
describe('State diagram', () => {
|
describe('State diagram', () => {
|
||||||
it('should render a simple state diagrams', () => {
|
it('should render a simple state diagrams', () => {
|
||||||
@@ -37,7 +37,7 @@ describe('State diagram', () => {
|
|||||||
);
|
);
|
||||||
cy.get('svg');
|
cy.get('svg');
|
||||||
});
|
});
|
||||||
it('should render a single state with short descr', () => {
|
it('should render a single state with short descriptions', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
stateDiagram
|
stateDiagram
|
||||||
@@ -48,7 +48,7 @@ describe('State diagram', () => {
|
|||||||
);
|
);
|
||||||
cy.get('svg');
|
cy.get('svg');
|
||||||
});
|
});
|
||||||
it('should render a transition descrions with new lines', () => {
|
it('should render a transition descriptions with new lines', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
stateDiagram
|
stateDiagram
|
||||||
@@ -191,7 +191,7 @@ describe('State diagram', () => {
|
|||||||
);
|
);
|
||||||
cy.get('svg');
|
cy.get('svg');
|
||||||
});
|
});
|
||||||
it('should render composit states', () => {
|
it('should render composite states', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
stateDiagram
|
stateDiagram
|
||||||
@@ -280,7 +280,7 @@ describe('State diagram', () => {
|
|||||||
);
|
);
|
||||||
cy.get('svg');
|
cy.get('svg');
|
||||||
});
|
});
|
||||||
it('should render conurrency states', () => {
|
it('should render concurrency states', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
stateDiagram
|
stateDiagram
|
||||||
@@ -319,7 +319,7 @@ describe('State diagram', () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('Simplest composit state', () => {
|
it('Simplest composite state', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
stateDiagram
|
stateDiagram
|
||||||
@@ -344,5 +344,45 @@ describe('State diagram', () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
it('should render a state diagram when useMaxWidth is true (default)', () => {
|
||||||
|
renderGraph(
|
||||||
|
`
|
||||||
|
stateDiagram
|
||||||
|
[*] --> State1
|
||||||
|
State1 --> [*]
|
||||||
|
`,
|
||||||
|
{ state: { useMaxWidth: true } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
expect(svg).to.have.attr('width', '100%');
|
||||||
|
expect(svg).to.have.attr('height');
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
expect(height).to.eq(139);
|
||||||
|
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 ±5%
|
||||||
|
expect(maxWidthValue).to.be.within(112 * .95, 112 * 1.05);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should render a state diagram when useMaxWidth is false', () => {
|
||||||
|
renderGraph(
|
||||||
|
`
|
||||||
|
stateDiagram
|
||||||
|
[*] --> State1
|
||||||
|
State1 --> [*]
|
||||||
|
`,
|
||||||
|
{ state: { useMaxWidth: false } }
|
||||||
|
);
|
||||||
|
cy.get('svg')
|
||||||
|
.should((svg) => {
|
||||||
|
const height = parseFloat(svg.attr('height'));
|
||||||
|
const width = parseFloat(svg.attr('width'));
|
||||||
|
expect(height).to.eq(139);
|
||||||
|
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||||
|
expect(width).to.be.within(112 * .95, 112 * 1.05);
|
||||||
|
expect(svg).to.not.have.attr('style');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -884,6 +884,26 @@ const config = {
|
|||||||
*/
|
*/
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
|
||||||
|
/**
|
||||||
|
*| Parameter | Description |Type | Required | Values|
|
||||||
|
*| --- | --- | --- | --- | --- |
|
||||||
|
*| useMaxWidth | See Notes | Boolean | Required | true, false |
|
||||||
|
*
|
||||||
|
***Notes:**
|
||||||
|
*When this flag is set to true, the diagram width is locked to 100% and
|
||||||
|
*scaled based on available space. If set to false, the diagram reserves its
|
||||||
|
*absolute width.
|
||||||
|
***Default value: true**.
|
||||||
|
*/
|
||||||
|
useMaxWidth: true
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object containing configurations specific for pie diagrams
|
||||||
|
*/
|
||||||
|
pie: {
|
||||||
|
useWidth: undefined,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*| Parameter | Description |Type | Required | Values|
|
*| Parameter | Description |Type | Required | Values|
|
||||||
*| --- | --- | --- | --- | --- |
|
*| --- | --- | --- | --- | --- |
|
||||||
|
@@ -98,7 +98,7 @@ export const draw = function(text, id) {
|
|||||||
|
|
||||||
makeGant(taskArray, w, h);
|
makeGant(taskArray, w, h);
|
||||||
|
|
||||||
configureSvgSize(elem, h, w, conf.useMaxWidth);
|
configureSvgSize(svg, h, w, conf.useMaxWidth);
|
||||||
|
|
||||||
svg
|
svg
|
||||||
.append('text')
|
.append('text')
|
||||||
|
@@ -43,7 +43,9 @@ export const draw = (txt, id) => {
|
|||||||
width = conf.useWidth;
|
width = conf.useWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
configureSvgSize(elem, height, width, conf.useMaxWidth);
|
const diagram = select('#' + id);
|
||||||
|
console.log('conf', conf);
|
||||||
|
configureSvgSize(diagram, height, width, conf.useMaxWidth);
|
||||||
|
|
||||||
// Set viewBox
|
// Set viewBox
|
||||||
elem.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
|
elem.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
|
||||||
@@ -55,10 +57,7 @@ export const draw = (txt, id) => {
|
|||||||
|
|
||||||
var radius = Math.min(width, height) / 2 - margin;
|
var radius = Math.min(width, height) / 2 - margin;
|
||||||
|
|
||||||
var svg = select('#' + id)
|
var svg = diagram
|
||||||
.append('svg')
|
|
||||||
.attr('width', width)
|
|
||||||
.attr('height', height)
|
|
||||||
.append('g')
|
.append('g')
|
||||||
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
|
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
|
||||||
|
|
||||||
@@ -67,9 +66,8 @@ export const draw = (txt, id) => {
|
|||||||
Object.keys(data).forEach(function(key) {
|
Object.keys(data).forEach(function(key) {
|
||||||
sum += data[key];
|
sum += data[key];
|
||||||
});
|
});
|
||||||
logger.info(data);
|
|
||||||
|
|
||||||
// set the color scale
|
// Set the color scale
|
||||||
var color = scaleOrdinal()
|
var color = scaleOrdinal()
|
||||||
.domain(data)
|
.domain(data)
|
||||||
.range(schemeSet2);
|
.range(schemeSet2);
|
||||||
@@ -80,12 +78,12 @@ export const draw = (txt, id) => {
|
|||||||
});
|
});
|
||||||
var dataReady = pie(entries(data));
|
var dataReady = pie(entries(data));
|
||||||
|
|
||||||
// shape helper to build arcs:
|
// Shape helper to build arcs:
|
||||||
var arcGenerator = arc()
|
var arcGenerator = arc()
|
||||||
.innerRadius(0)
|
.innerRadius(0)
|
||||||
.outerRadius(radius);
|
.outerRadius(radius);
|
||||||
|
|
||||||
// Build the pie chart: Basically, each part of the pie is a path that we build using the arc function.
|
// Build the pie chart: each part of the pie is a path that we build using the arc function.
|
||||||
svg
|
svg
|
||||||
.selectAll('mySlices')
|
.selectAll('mySlices')
|
||||||
.data(dataReady)
|
.data(dataReady)
|
||||||
@@ -99,7 +97,8 @@ export const draw = (txt, id) => {
|
|||||||
.style('stroke-width', '2px')
|
.style('stroke-width', '2px')
|
||||||
.style('opacity', 0.7);
|
.style('opacity', 0.7);
|
||||||
|
|
||||||
// Now add the Percentage. Use the centroid method to get the best coordinates
|
// Now add the percentage.
|
||||||
|
// Use the centroid method to get the best coordinates.
|
||||||
svg
|
svg
|
||||||
.selectAll('mySlices')
|
.selectAll('mySlices')
|
||||||
.data(dataReady)
|
.data(dataReady)
|
||||||
@@ -122,7 +121,7 @@ export const draw = (txt, id) => {
|
|||||||
.attr('y', -(height - 50) / 2)
|
.attr('y', -(height - 50) / 2)
|
||||||
.attr('class', 'pieTitleText');
|
.attr('class', 'pieTitleText');
|
||||||
|
|
||||||
//Add the slegend/annotations for each section
|
// Add the legends/annotations for each section
|
||||||
var legend = svg
|
var legend = svg
|
||||||
.selectAll('.legend')
|
.selectAll('.legend')
|
||||||
.data(color.domain())
|
.data(color.domain())
|
||||||
|
@@ -385,7 +385,7 @@ const render = function(id, _txt, cb, container) {
|
|||||||
break;
|
break;
|
||||||
case 'pie':
|
case 'pie':
|
||||||
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||||
pieRenderer.setConf(cnf.class);
|
pieRenderer.setConf(cnf.pie);
|
||||||
pieRenderer.draw(txt, id, pkg.version);
|
pieRenderer.draw(txt, id, pkg.version);
|
||||||
break;
|
break;
|
||||||
case 'er':
|
case 'er':
|
||||||
|
@@ -715,6 +715,7 @@ export const calculateSvgSizeAttrs = function(height, width, useMaxWidth) {
|
|||||||
|
|
||||||
export const configureSvgSize = function(svgElem, height, width, useMaxWidth) {
|
export const configureSvgSize = function(svgElem, height, width, useMaxWidth) {
|
||||||
const attrs = calculateSvgSizeAttrs(height, width, useMaxWidth);
|
const attrs = calculateSvgSizeAttrs(height, width, useMaxWidth);
|
||||||
|
console.log('svgElem', svgElem);
|
||||||
d3Attrs(svgElem, attrs);
|
d3Attrs(svgElem, attrs);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user