From 99844b4ca3227cc401989df77b2a5fe64844f6b5 Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Tue, 25 Aug 2020 17:05:01 +0200 Subject: [PATCH] Add e2e tests on all diagrams --- cypress/helpers/util.js | 1 + .../rendering/classDiagram.spec.js | 26 +++-- .../integration/rendering/erDiagram.spec.js | 42 +++++++- .../rendering/flowchart-v2.spec.js | 54 ++++++++++- .../integration/rendering/flowchart.spec.js | 47 ++++++++- cypress/integration/rendering/gantt.spec.js | 97 ++++++++++++++++++- cypress/integration/rendering/journey.spec.js | 41 +++++++- cypress/integration/rendering/pie.spec.js | 43 +++++++- .../rendering/sequencediagram.spec.js | 87 ++++++++++++++++- .../rendering/stateDiagram-v2.spec.js | 56 +++++++++-- .../rendering/stateDiagram.spec.js | 54 +++++++++-- src/defaultConfig.js | 20 ++++ src/diagrams/gantt/ganttRenderer.js | 2 +- src/diagrams/pie/pieRenderer.js | 21 ++-- src/mermaidAPI.js | 2 +- src/utils.js | 1 + src/utils.spec.js | 2 +- 17 files changed, 547 insertions(+), 49 deletions(-) diff --git a/cypress/helpers/util.js b/cypress/helpers/util.js index aa04f7ae6..b075659f0 100644 --- a/cypress/helpers/util.js +++ b/cypress/helpers/util.js @@ -1,4 +1,5 @@ /* eslint-env jest */ +/* global cy */ import { Base64 } from 'js-base64'; export const mermaidUrl = (graphStr, options, api) => { diff --git a/cypress/integration/rendering/classDiagram.spec.js b/cypress/integration/rendering/classDiagram.spec.js index 139ce1cb9..3882b9e99 100644 --- a/cypress/integration/rendering/classDiagram.spec.js +++ b/cypress/integration/rendering/classDiagram.spec.js @@ -354,7 +354,7 @@ describe('Class diagram', () => { 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( ` classDiagram @@ -369,12 +369,18 @@ describe('Class diagram', () => { { class: { useMaxWidth: true } } ); cy.get('svg') - .should('have.attr', 'width', '100%') - .should('have.attr', 'height', '218') - .should('have.attr', 'style', 'max-width: 162.28125px;') + .should((svg) => { + expect(svg).to.have.attr('width', '100%'); + 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( ` classDiagram @@ -389,8 +395,12 @@ describe('Class diagram', () => { { class: { useMaxWidth: false } } ); cy.get('svg') - .should('have.attr', 'width', '162.28125') - .should('have.attr', 'height', '218') - .should('not.have.attr', 'style') + .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(160 * .95, 160 * 1.05); + expect(svg).to.have.attr('height', '218'); + expect(svg).to.not.have.attr('style'); + }); }); }); diff --git a/cypress/integration/rendering/erDiagram.spec.js b/cypress/integration/rendering/erDiagram.spec.js index e965ca57d..a387bf254 100644 --- a/cypress/integration/rendering/erDiagram.spec.js +++ b/cypress/integration/rendering/erDiagram.spec.js @@ -1,5 +1,5 @@ /* eslint-env jest */ -import { imgSnapshotTest } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util'; describe('Entity Relationship Diagram', () => { it('should render a simple ER diagram', () => { @@ -101,4 +101,44 @@ describe('Entity Relationship Diagram', () => { ); 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'); + }); + }); }); diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index 29f2ef5b0..7374dff53 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -1,5 +1,5 @@ /* eslint-env jest */ -import { imgSnapshotTest } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util'; describe('Flowchart v2', () => { it('1: should render a simple flowchart', () => { @@ -47,7 +47,7 @@ describe('Flowchart v2', () => { ); }); - it('Length of edges', () => { + it('4: Length of edges', () => { imgSnapshotTest( `flowchart TD L1 --- L2 @@ -64,7 +64,7 @@ describe('Flowchart v2', () => { { flowchart: { diagramPadding: 0 } } ); }); - it('36: should render escaped without html labels', () => { + it('5: should render escaped without html labels', () => { imgSnapshotTest( `flowchart TD a["Haiya"]---->b @@ -72,13 +72,57 @@ describe('Flowchart v2', () => { {htmlLabels: false, flowchart: {htmlLabels: false}} ); }); - it('37: should render non-escaped with html labels', () => { + it('6: should render non-escaped with html labels', () => { imgSnapshotTest( `flowchart TD a["Haiya"]===>b `, {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'); + }); + }); }); diff --git a/cypress/integration/rendering/flowchart.spec.js b/cypress/integration/rendering/flowchart.spec.js index 804b49b7c..bf03696a2 100644 --- a/cypress/integration/rendering/flowchart.spec.js +++ b/cypress/integration/rendering/flowchart.spec.js @@ -1,5 +1,5 @@ /* eslint-env jest */ -import { imgSnapshotTest } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util'; describe('Flowchart', () => { it('1: should render a simple flowchart no htmlLabels', () => { @@ -731,4 +731,49 @@ describe('Flowchart', () => { {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'); + }); + }); }); diff --git a/cypress/integration/rendering/gantt.spec.js b/cypress/integration/rendering/gantt.spec.js index e655681bb..422af1165 100644 --- a/cypress/integration/rendering/gantt.spec.js +++ b/cypress/integration/rendering/gantt.spec.js @@ -1,5 +1,5 @@ /* eslint-env jest */ -import { imgSnapshotTest } from '../../helpers/util.js'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.js'; describe('Gantt diagram', () => { 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'); + }); + }); }); diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index 8bcf58412..6dd5f6c25 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -1,5 +1,5 @@ /* eslint-env jest */ -import { imgSnapshotTest } from '../../helpers/util.js'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.js'; describe('User journey diagram', () => { 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'); + }); + }); }); diff --git a/cypress/integration/rendering/pie.spec.js b/cypress/integration/rendering/pie.spec.js index b69aad631..bbedb9ebd 100644 --- a/cypress/integration/rendering/pie.spec.js +++ b/cypress/integration/rendering/pie.spec.js @@ -1,5 +1,5 @@ /* eslint-env jest */ -import { imgSnapshotTest } from '../../helpers/util.js'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.js'; describe('Pie Chart', () => { it('should render a simple pie diagram', () => { @@ -37,4 +37,45 @@ describe('Pie Chart', () => { ); 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'); + }); + }); }); diff --git a/cypress/integration/rendering/sequencediagram.spec.js b/cypress/integration/rendering/sequencediagram.spec.js index e20c6104b..bb460418f 100644 --- a/cypress/integration/rendering/sequencediagram.spec.js +++ b/cypress/integration/rendering/sequencediagram.spec.js @@ -1,6 +1,6 @@ /// -import { imgSnapshotTest } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util'; context('Sequence diagram', () => { it('should render a simple sequence diagram', () => { @@ -505,7 +505,7 @@ context('Sequence diagram', () => { }); }); context('directives', () => { - it('should overide config with directive settings', () => { + it('should override config with directive settings', () => { imgSnapshotTest( ` %%{init: { "config": { "mirrorActors": true }}}%% @@ -517,7 +517,7 @@ context('Sequence diagram', () => { { logLevel:0, sequence: { mirrorActors: false, noteFontSize: 18, noteFontFamily: 'Arial' } } ); }); - it('should overide config with directive settings', () => { + it('should override config with directive settings', () => { imgSnapshotTest( ` %%{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
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
long time, so long
that the text does
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
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
long time, so long
that the text does
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'); + }); + }); + }); }); diff --git a/cypress/integration/rendering/stateDiagram-v2.spec.js b/cypress/integration/rendering/stateDiagram-v2.spec.js index bc3cb8816..9013ec64f 100644 --- a/cypress/integration/rendering/stateDiagram-v2.spec.js +++ b/cypress/integration/rendering/stateDiagram-v2.spec.js @@ -1,5 +1,5 @@ /* eslint-env jest */ -import { imgSnapshotTest } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util'; describe('State diagram', () => { it('v2 should render a simple info', () => { @@ -47,7 +47,7 @@ describe('State diagram', () => { ); cy.get('svg'); }); - it('v2 should render a single state with short descr', () => { + it('v2 should render a single state with short descriptions', () => { imgSnapshotTest( ` stateDiagram-v2 @@ -58,7 +58,7 @@ describe('State diagram', () => { ); cy.get('svg'); }); - it('v2 should render a transition descrions with new lines', () => { + it('v2 should render a transition descriptions with new lines', () => { imgSnapshotTest( ` stateDiagram-v2 @@ -201,7 +201,7 @@ describe('State diagram', () => { ); cy.get('svg'); }); - it('v2 should render composit states', () => { + it('v2 should render composite states', () => { imgSnapshotTest( ` stateDiagram-v2 @@ -220,7 +220,7 @@ describe('State diagram', () => { ); cy.get('svg'); }); - it('v2 should render multiple composit states', () => { + it('v2 should render multiple composite states', () => { imgSnapshotTest( ` stateDiagram-v2 @@ -249,7 +249,7 @@ describe('State diagram', () => { { logLevel: 0, fontFamily: 'courier' } ); }); - it('v2 should render forks in composit states', () => { + it('v2 should render forks in composite states', () => { imgSnapshotTest( ` stateDiagram-v2 @@ -329,7 +329,7 @@ describe('State diagram', () => { } ); }); - it('v2 Simplest composit state', () => { + it('v2 Simplest composite state', () => { imgSnapshotTest( ` 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'); + }); + }); }); diff --git a/cypress/integration/rendering/stateDiagram.spec.js b/cypress/integration/rendering/stateDiagram.spec.js index ac1000858..2d10a6a9e 100644 --- a/cypress/integration/rendering/stateDiagram.spec.js +++ b/cypress/integration/rendering/stateDiagram.spec.js @@ -1,5 +1,5 @@ /* eslint-env jest */ -import { imgSnapshotTest } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util'; describe('State diagram', () => { it('should render a simple state diagrams', () => { @@ -37,7 +37,7 @@ describe('State diagram', () => { ); cy.get('svg'); }); - it('should render a single state with short descr', () => { + it('should render a single state with short descriptions', () => { imgSnapshotTest( ` stateDiagram @@ -48,7 +48,7 @@ describe('State diagram', () => { ); cy.get('svg'); }); - it('should render a transition descrions with new lines', () => { + it('should render a transition descriptions with new lines', () => { imgSnapshotTest( ` stateDiagram @@ -191,7 +191,7 @@ describe('State diagram', () => { ); cy.get('svg'); }); - it('should render composit states', () => { + it('should render composite states', () => { imgSnapshotTest( ` stateDiagram @@ -280,7 +280,7 @@ describe('State diagram', () => { ); cy.get('svg'); }); - it('should render conurrency states', () => { + it('should render concurrency states', () => { imgSnapshotTest( ` stateDiagram @@ -319,7 +319,7 @@ describe('State diagram', () => { } ); }); - it('Simplest composit state', () => { + it('Simplest composite state', () => { imgSnapshotTest( ` 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'); + }); + }); }); diff --git a/src/defaultConfig.js b/src/defaultConfig.js index 7c44d5a95..88b441272 100644 --- a/src/defaultConfig.js +++ b/src/defaultConfig.js @@ -884,6 +884,26 @@ const config = { */ 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| *| --- | --- | --- | --- | --- | diff --git a/src/diagrams/gantt/ganttRenderer.js b/src/diagrams/gantt/ganttRenderer.js index 95711f85c..0d3220bc9 100644 --- a/src/diagrams/gantt/ganttRenderer.js +++ b/src/diagrams/gantt/ganttRenderer.js @@ -98,7 +98,7 @@ export const draw = function(text, id) { makeGant(taskArray, w, h); - configureSvgSize(elem, h, w, conf.useMaxWidth); + configureSvgSize(svg, h, w, conf.useMaxWidth); svg .append('text') diff --git a/src/diagrams/pie/pieRenderer.js b/src/diagrams/pie/pieRenderer.js index 3dc4352fe..9cc8ac638 100644 --- a/src/diagrams/pie/pieRenderer.js +++ b/src/diagrams/pie/pieRenderer.js @@ -43,7 +43,9 @@ export const draw = (txt, id) => { 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 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 svg = select('#' + id) - .append('svg') - .attr('width', width) - .attr('height', height) + var svg = diagram .append('g') .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')'); @@ -67,9 +66,8 @@ export const draw = (txt, id) => { Object.keys(data).forEach(function(key) { sum += data[key]; }); - logger.info(data); - // set the color scale + // Set the color scale var color = scaleOrdinal() .domain(data) .range(schemeSet2); @@ -80,12 +78,12 @@ export const draw = (txt, id) => { }); var dataReady = pie(entries(data)); - // shape helper to build arcs: + // Shape helper to build arcs: var arcGenerator = arc() .innerRadius(0) .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 .selectAll('mySlices') .data(dataReady) @@ -99,7 +97,8 @@ export const draw = (txt, id) => { .style('stroke-width', '2px') .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 .selectAll('mySlices') .data(dataReady) @@ -122,7 +121,7 @@ export const draw = (txt, id) => { .attr('y', -(height - 50) / 2) .attr('class', 'pieTitleText'); - //Add the slegend/annotations for each section + // Add the legends/annotations for each section var legend = svg .selectAll('.legend') .data(color.domain()) diff --git a/src/mermaidAPI.js b/src/mermaidAPI.js index 096730791..3e9c76ec0 100644 --- a/src/mermaidAPI.js +++ b/src/mermaidAPI.js @@ -385,7 +385,7 @@ const render = function(id, _txt, cb, container) { break; case 'pie': cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - pieRenderer.setConf(cnf.class); + pieRenderer.setConf(cnf.pie); pieRenderer.draw(txt, id, pkg.version); break; case 'er': diff --git a/src/utils.js b/src/utils.js index 0f54c4212..5344afc04 100644 --- a/src/utils.js +++ b/src/utils.js @@ -715,6 +715,7 @@ export const calculateSvgSizeAttrs = function(height, width, useMaxWidth) { export const configureSvgSize = function(svgElem, height, width, useMaxWidth) { const attrs = calculateSvgSizeAttrs(height, width, useMaxWidth); + console.log('svgElem', svgElem); d3Attrs(svgElem, attrs); }; diff --git a/src/utils.spec.js b/src/utils.spec.js index c3fd94f93..756ad3794 100644 --- a/src/utils.spec.js +++ b/src/utils.spec.js @@ -1,5 +1,5 @@ /* eslint-env jasmine */ -import utils from './utils'; +import utils from './utils'; describe('when assignWithDepth: should merge objects within objects', function() { it('should handle simple, depth:1 types (identity)', function() {