mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-19 20:24:16 +01:00
Merge branch 'develop' into minmaps
This commit is contained in:
@@ -18,6 +18,8 @@ class Diagram {
|
||||
// console.log('this.type', this.type, diagrams[this.type]);
|
||||
// Setup diagram
|
||||
this.db = diagrams[this.type].db;
|
||||
this.db.clear?.();
|
||||
|
||||
this.renderer = diagrams[this.type].renderer;
|
||||
this.parser = diagrams[this.type].parser;
|
||||
this.parser.parser.yy = this.db;
|
||||
|
||||
@@ -471,7 +471,7 @@ describe('sortNodesByHierarchy', function () {
|
||||
return {};
|
||||
});
|
||||
});
|
||||
it('it should sort proper en nodes are in reverse order', function () {
|
||||
it('should sort proper en nodes are in reverse order', function () {
|
||||
/*
|
||||
a -->b
|
||||
subgraph B
|
||||
@@ -488,7 +488,7 @@ describe('sortNodesByHierarchy', function () {
|
||||
g.setEdge('a', 'b', '1');
|
||||
expect(sortNodesByHierarchy(g)).toEqual(['a', 'A', 'B', 'b']);
|
||||
});
|
||||
it('it should sort proper en nodes are in correct order', function () {
|
||||
it('should sort proper en nodes are in correct order', function () {
|
||||
/*
|
||||
a -->b
|
||||
subgraph B
|
||||
|
||||
@@ -64,9 +64,9 @@ const config = {
|
||||
logLevel: 5,
|
||||
|
||||
/**
|
||||
* | Parameter | Description | Type | Required | Values |
|
||||
* | ------------- | --------------------------------- | ------ | -------- | ------------------------------- |
|
||||
* | securitylevel | Level of trust for parsed diagram | string | Required | 'strict', 'loose', 'antiscript' |
|
||||
* | Parameter | Description | Type | Required | Values |
|
||||
* | ------------- | --------------------------------- | ------ | -------- | ------------------------------------------ |
|
||||
* | securityLevel | Level of trust for parsed diagram | string | Required | 'sandbox', 'strict', 'loose', 'antiscript' |
|
||||
*
|
||||
* **Notes**:
|
||||
*
|
||||
@@ -74,6 +74,9 @@ const config = {
|
||||
* - **loose**: tags in text are allowed, click functionality is enabled
|
||||
* - **antiscript**: html tags in text are allowed, (only script element is removed), click
|
||||
* functionality is enabled
|
||||
* - **sandbox**: With this security level all rendering takes place in a sandboxed iframe. This
|
||||
* prevent any JavaScript from running in the context. This may hinder interactive functionality
|
||||
* of the diagram like scripts, popups in sequence diagram or links to other tabs/targets etc.
|
||||
*/
|
||||
securityLevel: 'strict',
|
||||
|
||||
|
||||
84
src/diagrams/c4/parser/flow.spec.js
Normal file
84
src/diagrams/c4/parser/flow.spec.js
Normal file
@@ -0,0 +1,84 @@
|
||||
import flowDb from '../c4Db';
|
||||
import flow from './c4Diagram.jison';
|
||||
import { setConfig } from '../../../config';
|
||||
|
||||
setConfig({
|
||||
securityLevel: 'strict',
|
||||
});
|
||||
|
||||
describe('parsing a flow chart', function () {
|
||||
beforeEach(function () {
|
||||
flow.parser.yy = flowDb;
|
||||
flow.parser.yy.clear();
|
||||
});
|
||||
|
||||
it('should parse a C4 diagram with one Person correctly', function () {
|
||||
flow.parser.parse(`C4Context
|
||||
title System Context diagram for Internet Banking System
|
||||
Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")`);
|
||||
|
||||
const yy = flow.parser.yy;
|
||||
expect(yy.getC4Type()).toBe('C4Context');
|
||||
expect(yy.getTitle()).toBe('System Context diagram for Internet Banking System');
|
||||
|
||||
const shapes = yy.getC4ShapeArray();
|
||||
expect(shapes.length).toBe(1);
|
||||
const onlyShape = shapes[0];
|
||||
|
||||
expect(onlyShape).toEqual({
|
||||
alias: 'customerA',
|
||||
descr: {
|
||||
text: 'A customer of the bank, with personal bank accounts.',
|
||||
},
|
||||
label: {
|
||||
text: 'Banking Customer A',
|
||||
},
|
||||
parentBoundary: 'global',
|
||||
typeC4Shape: {
|
||||
text: 'person',
|
||||
},
|
||||
wrap: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle a trailing whitespaces after statements', function () {
|
||||
const whitespace = ' ';
|
||||
const rendered = flow.parser.parse(`C4Context${whitespace}
|
||||
title System Context diagram for Internet Banking System${whitespace}
|
||||
Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")${whitespace}`);
|
||||
|
||||
expect(rendered).toBe(true);
|
||||
});
|
||||
|
||||
it('should handle parameter names that are keywords', function () {
|
||||
flow.parser.parse(`C4Context
|
||||
title title
|
||||
Person(Person, "Person", "Person")`);
|
||||
|
||||
const yy = flow.parser.yy;
|
||||
expect(yy.getTitle()).toBe('title');
|
||||
|
||||
const shapes = yy.getC4ShapeArray();
|
||||
expect(shapes.length).toBe(1);
|
||||
const onlyShape = shapes[0];
|
||||
|
||||
expect(onlyShape.alias).toBe('Person');
|
||||
expect(onlyShape.descr.text).toBe('Person');
|
||||
expect(onlyShape.label.text).toBe('Person');
|
||||
});
|
||||
|
||||
it('should allow default in the parameters', function () {
|
||||
flow.parser.parse(`C4Context
|
||||
Person(default, "default", "default")`);
|
||||
|
||||
const yy = flow.parser.yy;
|
||||
|
||||
const shapes = yy.getC4ShapeArray();
|
||||
expect(shapes.length).toBe(1);
|
||||
const onlyShape = shapes[0];
|
||||
|
||||
expect(onlyShape.alias).toBe('default');
|
||||
expect(onlyShape.descr.text).toBe('default');
|
||||
expect(onlyShape.label.text).toBe('default');
|
||||
});
|
||||
});
|
||||
@@ -206,7 +206,9 @@ const setTooltip = function (ids, tooltip) {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const getTooltip = function (id) {
|
||||
return classes[id].tooltip;
|
||||
};
|
||||
/**
|
||||
* Called by parser when a link is found. Adds the URL to the vertex data.
|
||||
*
|
||||
@@ -337,6 +339,7 @@ const setupToolTips = function (element) {
|
||||
.text(el.attr('title'))
|
||||
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
|
||||
.style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px');
|
||||
tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '<br/>'));
|
||||
el.classed('hover', true);
|
||||
})
|
||||
.on('mouseout', function () {
|
||||
@@ -378,6 +381,7 @@ export default {
|
||||
setClickEvent,
|
||||
setCssClass,
|
||||
setLink,
|
||||
getTooltip,
|
||||
setTooltip,
|
||||
lookUpDomId,
|
||||
};
|
||||
|
||||
@@ -14,7 +14,16 @@ describe('class diagram, ', function () {
|
||||
|
||||
parser.parse(str);
|
||||
});
|
||||
xit('should handle a leading newline axa', function () {
|
||||
const str = '\nclassDiagram\n' + 'class Car';
|
||||
|
||||
try {
|
||||
parser.parse(str);
|
||||
// Fail test if above expression doesn't throw anything.
|
||||
} catch (e) {
|
||||
expect(true).toBe(false);
|
||||
}
|
||||
});
|
||||
it('should handle relation definitions', function () {
|
||||
const str =
|
||||
'classDiagram\n' +
|
||||
|
||||
@@ -29,8 +29,10 @@ let conf = {
|
||||
* >} classes
|
||||
* Object containing the vertices.
|
||||
* @param {SVGGElement} g The graph that is to be drawn.
|
||||
* @param _id
|
||||
* @param diagObj
|
||||
*/
|
||||
export const addClasses = function (classes, g) {
|
||||
export const addClasses = function (classes, g, _id, diagObj) {
|
||||
// const svg = select(`[id="${svgId}"]`);
|
||||
const keys = Object.keys(classes);
|
||||
log.info('keys:', keys);
|
||||
@@ -108,6 +110,7 @@ export const addClasses = function (classes, g) {
|
||||
style: styles.style,
|
||||
id: vertex.id,
|
||||
domId: vertex.domId,
|
||||
tooltip: diagObj.db.getTooltip(vertex.id) || '',
|
||||
haveCallback: vertex.haveCallback,
|
||||
link: vertex.link,
|
||||
width: vertex.type === 'group' ? 500 : undefined,
|
||||
@@ -319,7 +322,7 @@ export const draw = function (text, id, _version, diagObj) {
|
||||
const relations = diagObj.db.getRelations();
|
||||
|
||||
log.info(relations);
|
||||
addClasses(classes, g, id);
|
||||
addClasses(classes, g, id, diagObj);
|
||||
addRelations(relations, g);
|
||||
|
||||
// Add custom shapes
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { line, curveBasis } from 'd3';
|
||||
import utils from '../../utils';
|
||||
import { log } from '../../logger';
|
||||
import { parseGenericTypes } from '../common/common';
|
||||
|
||||
let edgeCount = 0;
|
||||
export const drawEdge = function (elem, path, relation, conf, diagObj) {
|
||||
@@ -412,29 +413,6 @@ const addTspan = function (textEl, txt, isFirst, conf) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes generics in typescript syntax
|
||||
*
|
||||
* @example <caption>Array of array of strings in typescript syntax</caption>
|
||||
* // returns "Array<Array<string>>"
|
||||
* parseGenericTypes('Array~Array~string~~');
|
||||
*
|
||||
* @param {string} text The text to convert
|
||||
* @returns {string} The converted string
|
||||
*/
|
||||
const parseGenericTypes = function (text) {
|
||||
let cleanedText = text;
|
||||
|
||||
if (text.indexOf('~') != -1) {
|
||||
cleanedText = cleanedText.replace('~', '<');
|
||||
cleanedText = cleanedText.replace('~', '>');
|
||||
|
||||
return parseGenericTypes(cleanedText);
|
||||
} else {
|
||||
return cleanedText;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gives the styles for a classifier
|
||||
*
|
||||
|
||||
@@ -182,6 +182,29 @@ const getUrl = (useAbsolute) => {
|
||||
*/
|
||||
export const evaluate = (val) => (val === 'false' || val === false ? false : true);
|
||||
|
||||
/**
|
||||
* Makes generics in typescript syntax
|
||||
*
|
||||
* @example <caption>Array of array of strings in typescript syntax</caption>
|
||||
* // returns "Array<Array<string>>"
|
||||
* parseGenericTypes('Array~Array~string~~');
|
||||
*
|
||||
* @param {string} text The text to convert
|
||||
* @returns {string} The converted string
|
||||
*/
|
||||
export const parseGenericTypes = function (text) {
|
||||
let cleanedText = text;
|
||||
|
||||
if (text.indexOf('~') != -1) {
|
||||
cleanedText = cleanedText.replace('~', '<');
|
||||
cleanedText = cleanedText.replace('~', '>');
|
||||
|
||||
return parseGenericTypes(cleanedText);
|
||||
} else {
|
||||
return cleanedText;
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
getRows,
|
||||
sanitizeText,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { sanitizeText, removeScript, removeEscapes } from './common';
|
||||
import { sanitizeText, removeScript, removeEscapes, parseGenericTypes } from './common';
|
||||
|
||||
describe('when securityLevel is antiscript, all script must be removed', function () {
|
||||
/**
|
||||
@@ -103,3 +103,10 @@ describe('Sanitize text', function () {
|
||||
expect(result).not.toContain('javascript:alert(1)');
|
||||
});
|
||||
});
|
||||
|
||||
describe('generic parser', function () {
|
||||
it('should parse generic types', function () {
|
||||
const result = parseGenericTypes('test~T~');
|
||||
expect(result).toEqual('test<T>');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ import { log } from '../../logger';
|
||||
import erMarkers from './erMarkers';
|
||||
import { configureSvgSize } from '../../utils';
|
||||
import addSVGAccessibilityFields from '../../accessibility';
|
||||
import { parseGenericTypes } from '../common/common';
|
||||
|
||||
let conf = {};
|
||||
|
||||
@@ -63,6 +64,8 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => {
|
||||
const attrPrefix = `${entityTextNode.node().id}-attr-${attrNum}`;
|
||||
let nodeHeight = 0;
|
||||
|
||||
const attributeType = parseGenericTypes(item.attributeType);
|
||||
|
||||
// Add a text node for the attribute type
|
||||
const typeNode = groupNode
|
||||
.append('text')
|
||||
@@ -76,7 +79,7 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => {
|
||||
'style',
|
||||
'font-family: ' + getConfig().fontFamily + '; font-size: ' + attrFontSize + 'px'
|
||||
)
|
||||
.text(item.attributeType);
|
||||
.text(attributeType);
|
||||
|
||||
// Add a text node for the attribute name
|
||||
const nameNode = groupNode
|
||||
|
||||
@@ -29,7 +29,8 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
||||
"{" { this.begin("block"); return 'BLOCK_START'; }
|
||||
<block>\s+ /* skip whitespace in block */
|
||||
<block>\b((?:PK)|(?:FK))\b return 'ATTRIBUTE_KEY'
|
||||
<block>[A-Za-z][A-Za-z0-9\-_]* return 'ATTRIBUTE_WORD'
|
||||
<block>(.*?)[~](.*?)*[~] return 'ATTRIBUTE_WORD';
|
||||
<block>[A-Za-z][A-Za-z0-9\-_\[\]]* return 'ATTRIBUTE_WORD'
|
||||
<block>\"[^"]*\" return 'COMMENT';
|
||||
<block>[\n]+ /* nothing */
|
||||
<block>"}" { this.popState(); return 'BLOCK_STOP'; }
|
||||
|
||||
@@ -85,6 +85,31 @@ describe('when parsing ER diagram it...', function () {
|
||||
expect(entities[entity].attributes.length).toBe(3);
|
||||
});
|
||||
|
||||
it('should allow an entity with attribute that has a generic type', function () {
|
||||
const entity = 'BOOK';
|
||||
const attribute1 = 'type~T~ type';
|
||||
const attribute2 = 'option~T~ readable "comment"';
|
||||
const attribute3 = 'string id PK';
|
||||
|
||||
erDiagram.parser.parse(
|
||||
`erDiagram\n${entity} {\n${attribute1}\n${attribute2}\n${attribute3}\n}`
|
||||
);
|
||||
const entities = erDb.getEntities();
|
||||
expect(Object.keys(entities).length).toBe(1);
|
||||
expect(entities[entity].attributes.length).toBe(3);
|
||||
});
|
||||
|
||||
it('should allow an entity with attribute that is an array', function () {
|
||||
const entity = 'BOOK';
|
||||
const attribute1 = 'string[] readers FK "comment"';
|
||||
const attribute2 = 'string[] authors FK';
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity} {\n${attribute1}\n${attribute2}\n}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(Object.keys(entities).length).toBe(1);
|
||||
expect(entities[entity].attributes.length).toBe(2);
|
||||
});
|
||||
|
||||
it('should allow an entity with multiple attributes to be defined', function () {
|
||||
const entity = 'BOOK';
|
||||
const attribute1 = 'string title';
|
||||
|
||||
@@ -409,6 +409,7 @@ const setupToolTips = function (element) {
|
||||
.text(el.attr('title'))
|
||||
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
|
||||
.style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px');
|
||||
tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '<br/>'));
|
||||
el.classed('hover', true);
|
||||
})
|
||||
.on('mouseout', function () {
|
||||
|
||||
@@ -14,7 +14,7 @@ describe('[Interactions] when parsing', () => {
|
||||
flow.parser.yy.clear();
|
||||
});
|
||||
|
||||
it('it should be possible to use click to a callback', function () {
|
||||
it('should be possible to use click to a callback', function () {
|
||||
spyOn(flowDb, 'setClickEvent');
|
||||
const res = flow.parser.parse('graph TD\nA-->B\nclick A callback');
|
||||
|
||||
@@ -24,7 +24,7 @@ describe('[Interactions] when parsing', () => {
|
||||
expect(flowDb.setClickEvent).toHaveBeenCalledWith('A', 'callback');
|
||||
});
|
||||
|
||||
it('it should be possible to use click to a click and call callback', function () {
|
||||
it('should be possible to use click to a click and call callback', function () {
|
||||
spyOn(flowDb, 'setClickEvent');
|
||||
const res = flow.parser.parse('graph TD\nA-->B\nclick A call callback()');
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('[Interactions] when parsing', () => {
|
||||
expect(flowDb.setClickEvent).toHaveBeenCalledWith('A', 'callback');
|
||||
});
|
||||
|
||||
it('it should be possible to use click to a callback with toolip', function () {
|
||||
it('should be possible to use click to a callback with toolip', function () {
|
||||
spyOn(flowDb, 'setClickEvent');
|
||||
spyOn(flowDb, 'setTooltip');
|
||||
const res = flow.parser.parse('graph TD\nA-->B\nclick A callback "tooltip"');
|
||||
@@ -46,7 +46,7 @@ describe('[Interactions] when parsing', () => {
|
||||
expect(flowDb.setTooltip).toHaveBeenCalledWith('A', 'tooltip');
|
||||
});
|
||||
|
||||
it('it should be possible to use click to a click and call callback with toolip', function () {
|
||||
it('should be possible to use click to a click and call callback with toolip', function () {
|
||||
spyOn(flowDb, 'setClickEvent');
|
||||
spyOn(flowDb, 'setTooltip');
|
||||
const res = flow.parser.parse('graph TD\nA-->B\nclick A call callback() "tooltip"');
|
||||
@@ -58,7 +58,7 @@ describe('[Interactions] when parsing', () => {
|
||||
expect(flowDb.setTooltip).toHaveBeenCalledWith('A', 'tooltip');
|
||||
});
|
||||
|
||||
it('it should be possible to use click to a callback with an arbitrary number of args', function () {
|
||||
it('should be possible to use click to a callback with an arbitrary number of args', function () {
|
||||
spyOn(flowDb, 'setClickEvent');
|
||||
const res = flow.parser.parse('graph TD\nA-->B\nclick A call callback("test0", test1, test2)');
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ describe('[Lines] when parsing', () => {
|
||||
});
|
||||
|
||||
describe('it should handle new line type notation', function () {
|
||||
it('it should handle regular lines', function () {
|
||||
it('should handle regular lines', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -98,7 +98,7 @@ describe('[Lines] when parsing', () => {
|
||||
expect(edges[0].stroke).toBe('normal');
|
||||
});
|
||||
|
||||
it('it should handle dotted lines', function () {
|
||||
it('should handle dotted lines', function () {
|
||||
const res = flow.parser.parse('graph TD;A-.->B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -107,7 +107,7 @@ describe('[Lines] when parsing', () => {
|
||||
expect(edges[0].stroke).toBe('dotted');
|
||||
});
|
||||
|
||||
it('it should handle dotted lines', function () {
|
||||
it('should handle dotted lines', function () {
|
||||
const res = flow.parser.parse('graph TD;A==>B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
@@ -13,7 +13,7 @@ describe('[Text] when parsing', () => {
|
||||
});
|
||||
|
||||
describe('it should handle text on edges', function () {
|
||||
it('it should handle text without space', function () {
|
||||
it('should handle text without space', function () {
|
||||
const res = flow.parser.parse('graph TD;A--x|textNoSpace|B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -22,7 +22,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
});
|
||||
|
||||
it('should handle with space', function () {
|
||||
it('should handle with space', function () {
|
||||
const res = flow.parser.parse('graph TD;A--x|text including space|B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -31,7 +31,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
});
|
||||
|
||||
it('it should handle text with /', function () {
|
||||
it('should handle text with /', function () {
|
||||
const res = flow.parser.parse('graph TD;A--x|text with / should work|B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -40,7 +40,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].text).toBe('text with / should work');
|
||||
});
|
||||
|
||||
it('it should handle space and space between vertices and link', function () {
|
||||
it('should handle space and space between vertices and link', function () {
|
||||
const res = flow.parser.parse('graph TD;A --x|textNoSpace| B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -159,12 +159,6 @@ describe('[Text] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
expect(vert['a'].text).toBe('v');
|
||||
});
|
||||
it('should handle keywords', function () {
|
||||
const res = flow.parser.parse('graph TD;V-->a[v]');
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
expect(vert['a'].text).toBe('v');
|
||||
});
|
||||
it('should handle quoted text', function () {
|
||||
const res = flow.parser.parse('graph TD;V-- "test string()" -->a[v]');
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -174,7 +168,7 @@ describe('[Text] when parsing', () => {
|
||||
});
|
||||
|
||||
describe('it should handle text on lines', () => {
|
||||
it('it should handle normal text on lines', function () {
|
||||
it('should handle normal text on lines', function () {
|
||||
const res = flow.parser.parse('graph TD;A-- test text with == -->B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -182,7 +176,7 @@ describe('[Text] when parsing', () => {
|
||||
|
||||
expect(edges[0].stroke).toBe('normal');
|
||||
});
|
||||
it('it should handle dotted text on lines (TD3)', function () {
|
||||
it('should handle dotted text on lines (TD3)', function () {
|
||||
const res = flow.parser.parse('graph TD;A-. test text with == .->B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -190,7 +184,7 @@ describe('[Text] when parsing', () => {
|
||||
|
||||
expect(edges[0].stroke).toBe('dotted');
|
||||
});
|
||||
it('it should handle thick text on lines', function () {
|
||||
it('should handle thick text on lines', function () {
|
||||
const res = flow.parser.parse('graph TD;A== test text with - ==>B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -201,7 +195,7 @@ describe('[Text] when parsing', () => {
|
||||
});
|
||||
|
||||
describe('it should handle text on edges using the new notation', function () {
|
||||
it('it should handle text without space', function () {
|
||||
it('should handle text without space', function () {
|
||||
const res = flow.parser.parse('graph TD;A-- textNoSpace --xB;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -210,7 +204,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
});
|
||||
|
||||
it('it should handle text with multiple leading space', function () {
|
||||
it('should handle text with multiple leading space', function () {
|
||||
const res = flow.parser.parse('graph TD;A-- textNoSpace --xB;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -219,7 +213,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
});
|
||||
|
||||
it('should handle with space', function () {
|
||||
it('should handle with space', function () {
|
||||
const res = flow.parser.parse('graph TD;A-- text including space --xB;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -228,7 +222,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
});
|
||||
|
||||
it('it should handle text with /', function () {
|
||||
it('should handle text with /', function () {
|
||||
const res = flow.parser.parse('graph TD;A -- text with / should work --x B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -237,7 +231,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(edges[0].text).toBe('text with / should work');
|
||||
});
|
||||
|
||||
it('it should handle space and space between vertices and link', function () {
|
||||
it('should handle space and space between vertices and link', function () {
|
||||
const res = flow.parser.parse('graph TD;A -- textNoSpace --x B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -302,7 +296,7 @@ describe('[Text] when parsing', () => {
|
||||
});
|
||||
|
||||
describe('it should handle text in vertices, ', function () {
|
||||
it('it should handle space', function () {
|
||||
it('should handle space', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(Chimpansen hoppar);');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -311,7 +305,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(vert['C'].type).toBe('round');
|
||||
expect(vert['C'].text).toBe('Chimpansen hoppar');
|
||||
});
|
||||
it('it should handle åäö and minus', function () {
|
||||
it('should handle åäö and minus', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C{Chimpansen hoppar åäö-ÅÄÖ};');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -321,7 +315,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(vert['C'].text).toBe('Chimpansen hoppar åäö-ÅÄÖ');
|
||||
});
|
||||
|
||||
it('it should handle with åäö, minus and space and br', function () {
|
||||
it('should handle with åäö, minus and space and br', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(Chimpansen hoppar åäö <br> - ÅÄÖ);');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -330,7 +324,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(vert['C'].type).toBe('round');
|
||||
expect(vert['C'].text).toBe('Chimpansen hoppar åäö <br> - ÅÄÖ');
|
||||
});
|
||||
// xit('it should handle åäö, minus and space and br',function(){
|
||||
// xit('should handle åäö, minus and space and br',function(){
|
||||
// const res = flow.parser.parse('graph TD; A[Object(foo,bar)]-->B(Thing);');
|
||||
//
|
||||
// const vert = flow.parser.yy.getVertices();
|
||||
@@ -339,21 +333,21 @@ describe('[Text] when parsing', () => {
|
||||
// expect(vert['C'].type).toBe('round');
|
||||
// expect(vert['C'].text).toBe(' A[Object(foo,bar)]-->B(Thing);');
|
||||
// });
|
||||
it('it should handle unicode chars', function () {
|
||||
it('should handle unicode chars', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(Начало);');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
expect(vert['C'].text).toBe('Начало');
|
||||
});
|
||||
it('it should handle backslask', function () {
|
||||
it('should handle backslask', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(c:\\windows);');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
expect(vert['C'].text).toBe('c:\\windows');
|
||||
});
|
||||
it('it should handle CAPS', function () {
|
||||
it('should handle CAPS', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(some CAPS);');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
@@ -362,7 +356,7 @@ describe('[Text] when parsing', () => {
|
||||
expect(vert['C'].type).toBe('round');
|
||||
expect(vert['C'].text).toBe('some CAPS');
|
||||
});
|
||||
it('it should handle directions', function () {
|
||||
it('should handle directions', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(some URL);');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
@@ -233,6 +233,9 @@ const getStartDate = function (prevTime, dateFormat, str) {
|
||||
const durationToDate = function (durationStatement, relativeTime) {
|
||||
if (durationStatement !== null) {
|
||||
switch (durationStatement[2]) {
|
||||
case 'ms':
|
||||
relativeTime.add(durationStatement[1], 'milliseconds');
|
||||
break;
|
||||
case 's':
|
||||
relativeTime.add(durationStatement[1], 'seconds');
|
||||
break;
|
||||
@@ -267,7 +270,7 @@ const getEndDate = function (prevTime, dateFormat, str, inclusive) {
|
||||
return mDate.toDate();
|
||||
}
|
||||
|
||||
return durationToDate(/^([\d]+)([wdhms])/.exec(str.trim()), moment(prevTime));
|
||||
return durationToDate(/^([\d]+)([wdhms]|ms)$/.exec(str.trim()), moment(prevTime));
|
||||
};
|
||||
|
||||
let taskCnt = 0;
|
||||
|
||||
@@ -99,6 +99,27 @@ describe('when using the ganttDb', function () {
|
||||
}
|
||||
);
|
||||
|
||||
it('should handle milliseconds', function () {
|
||||
ganttDb.setDateFormat('x');
|
||||
ganttDb.addSection('testa1');
|
||||
ganttDb.addTask('test1', 'id1,0,20ms');
|
||||
ganttDb.addTask('test2', 'id2,after id1,5ms');
|
||||
ganttDb.addSection('testa2');
|
||||
ganttDb.addTask('test3', 'id3,20,10ms');
|
||||
ganttDb.addTask('test4', 'id4,after id3,5ms');
|
||||
|
||||
const tasks = ganttDb.getTasks();
|
||||
|
||||
expect(tasks[0].startTime.toISOString()).toEqual('1970-01-01T00:00:00.000Z');
|
||||
expect(tasks[0].endTime.toISOString()).toEqual('1970-01-01T00:00:00.020Z');
|
||||
expect(tasks[1].startTime.toISOString()).toEqual('1970-01-01T00:00:00.020Z');
|
||||
expect(tasks[1].endTime.toISOString()).toEqual('1970-01-01T00:00:00.025Z');
|
||||
expect(tasks[2].startTime.toISOString()).toEqual('1970-01-01T00:00:00.020Z');
|
||||
expect(tasks[2].endTime.toISOString()).toEqual('1970-01-01T00:00:00.030Z');
|
||||
expect(tasks[3].startTime.toISOString()).toEqual('1970-01-01T00:00:00.030Z');
|
||||
expect(tasks[3].endTime.toISOString()).toEqual('1970-01-01T00:00:00.035Z');
|
||||
});
|
||||
|
||||
it('should handle relative start date based on id regardless of sections', function () {
|
||||
ganttDb.setDateFormat('YYYY-MM-DD');
|
||||
ganttDb.addSection('testa1');
|
||||
|
||||
@@ -115,7 +115,7 @@ describe('when parsing a gitGraph', function() {
|
||||
expect(parser.yy.getCurrentBranch()).toBe('master');
|
||||
});
|
||||
|
||||
it('it should reset a branch', function() {
|
||||
it('should reset a branch', function() {
|
||||
const str =
|
||||
'gitGraph:\n' +
|
||||
'commit\n' +
|
||||
@@ -153,7 +153,7 @@ describe('when parsing a gitGraph', function() {
|
||||
expect(parser.yy.getHead().id).toEqual(master.parent);
|
||||
});
|
||||
|
||||
it('it should handle fast forwardable merges', function() {
|
||||
it('should handle fast forwardable merges', function() {
|
||||
const str =
|
||||
'gitGraph:\n' +
|
||||
'commit\n' +
|
||||
@@ -173,7 +173,7 @@ describe('when parsing a gitGraph', function() {
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch']);
|
||||
});
|
||||
|
||||
it('it should handle cases when merge is a noop', function() {
|
||||
it('should handle cases when merge is a noop', function() {
|
||||
const str =
|
||||
'gitGraph:\n' +
|
||||
'commit\n' +
|
||||
@@ -192,7 +192,7 @@ describe('when parsing a gitGraph', function() {
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['newbranch']);
|
||||
});
|
||||
|
||||
it('it should handle merge with 2 parents', function() {
|
||||
it('should handle merge with 2 parents', function() {
|
||||
const str =
|
||||
'gitGraph:\n' +
|
||||
'commit\n' +
|
||||
@@ -213,7 +213,7 @@ describe('when parsing a gitGraph', function() {
|
||||
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches()['master']);
|
||||
});
|
||||
|
||||
it('it should handle ff merge when history walk has two parents (merge commit)', function() {
|
||||
it('should handle ff merge when history walk has two parents (merge commit)', function() {
|
||||
const str =
|
||||
'gitGraph:\n' +
|
||||
'commit\n' +
|
||||
@@ -239,7 +239,7 @@ describe('when parsing a gitGraph', function() {
|
||||
parser.yy.prettyPrint();
|
||||
});
|
||||
|
||||
it('it should generate a secure random ID for commits', function() {
|
||||
it('should generate a secure random ID for commits', function() {
|
||||
const str = 'gitGraph:\n' + 'commit\n' + 'commit\n';
|
||||
const EXPECTED_LENGTH = 7;
|
||||
const EXPECTED_CHARACTERS = '0123456789abcdef';
|
||||
@@ -267,7 +267,7 @@ describe('when parsing a gitGraph', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('it should generate an array of known branches', function() {
|
||||
it('should generate an array of known branches', function() {
|
||||
const str =
|
||||
'gitGraph:\n' +
|
||||
'commit\n' +
|
||||
|
||||
@@ -22,6 +22,81 @@ function addConf(conf, key, value) {
|
||||
// const parser = sequence.parser;
|
||||
let diagram;
|
||||
|
||||
describe('more than one sequence diagram', () => {
|
||||
it('should not have duplicated messages', () => {
|
||||
const diagram1 = new Diagram(`
|
||||
sequenceDiagram
|
||||
Alice->Bob:Hello Bob, how are you?
|
||||
Bob-->Alice: I am good thanks!`);
|
||||
expect(diagram1.db.getMessages()).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"from": "Alice",
|
||||
"message": "Hello Bob, how are you?",
|
||||
"to": "Bob",
|
||||
"type": 5,
|
||||
"wrap": false,
|
||||
},
|
||||
Object {
|
||||
"from": "Bob",
|
||||
"message": "I am good thanks!",
|
||||
"to": "Alice",
|
||||
"type": 6,
|
||||
"wrap": false,
|
||||
},
|
||||
]
|
||||
`);
|
||||
const diagram2 = new Diagram(`
|
||||
sequenceDiagram
|
||||
Alice->Bob:Hello Bob, how are you?
|
||||
Bob-->Alice: I am good thanks!`);
|
||||
|
||||
expect(diagram2.db.getMessages()).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"from": "Alice",
|
||||
"message": "Hello Bob, how are you?",
|
||||
"to": "Bob",
|
||||
"type": 5,
|
||||
"wrap": false,
|
||||
},
|
||||
Object {
|
||||
"from": "Bob",
|
||||
"message": "I am good thanks!",
|
||||
"to": "Alice",
|
||||
"type": 6,
|
||||
"wrap": false,
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
||||
// Add John actor
|
||||
const diagram3 = new Diagram(`
|
||||
sequenceDiagram
|
||||
Alice->John:Hello John, how are you?
|
||||
John-->Alice: I am good thanks!`);
|
||||
|
||||
expect(diagram3.db.getMessages()).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"from": "Alice",
|
||||
"message": "Hello John, how are you?",
|
||||
"to": "John",
|
||||
"type": 5,
|
||||
"wrap": false,
|
||||
},
|
||||
Object {
|
||||
"from": "John",
|
||||
"message": "I am good thanks!",
|
||||
"to": "Alice",
|
||||
"type": 6,
|
||||
"wrap": false,
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when parsing a sequenceDiagram', function () {
|
||||
beforeEach(function () {
|
||||
// diagram.db = sequenceDb;
|
||||
@@ -51,7 +126,7 @@ Bob-->Alice: I am good thanks!`;
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[2].from).toBe('Bob');
|
||||
});
|
||||
it('it should not show sequence numbers per default', function () {
|
||||
it('should not show sequence numbers per default', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob:Hello Bob, how are you?
|
||||
@@ -62,7 +137,7 @@ Bob-->Alice: I am good thanks!`;
|
||||
diagram.renderer.draw(str, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility autonumbers
|
||||
expect(diagram.db.showSequenceNumbers()).toBe(false);
|
||||
});
|
||||
it('it should show sequence numbers when autonumber is enabled', function () {
|
||||
it('should show sequence numbers when autonumber is enabled', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
@@ -74,7 +149,7 @@ Bob-->Alice: I am good thanks!`;
|
||||
diagram.renderer.draw(str, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility autonumbers
|
||||
expect(diagram.db.showSequenceNumbers()).toBe(true);
|
||||
});
|
||||
it('it should handle a sequenceDiagram definition with a title:', function () {
|
||||
it('should handle a sequenceDiagram definition with a title:', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
title: Diagram Title
|
||||
@@ -97,7 +172,7 @@ Bob-->Alice: I am good thanks!`;
|
||||
expect(title).toBe('Diagram Title');
|
||||
});
|
||||
|
||||
it('it should handle a sequenceDiagram definition with a title without a :', function () {
|
||||
it('should handle a sequenceDiagram definition with a title without a :', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
title Diagram Title
|
||||
@@ -120,7 +195,7 @@ Bob-->Alice: I am good thanks!`;
|
||||
expect(title).toBe('Diagram Title');
|
||||
});
|
||||
|
||||
it('it should handle a sequenceDiagram definition with a accessibility title and description (accDescr)', function () {
|
||||
it('should handle a sequenceDiagram definition with a accessibility title and description (accDescr)', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
title: Diagram Title
|
||||
@@ -135,7 +210,7 @@ Alice->Bob:Hello Bob, how are you?
|
||||
expect(diagram.db.getAccDescription()).toBe('Accessibility Description');
|
||||
const messages = diagram.db.getMessages();
|
||||
});
|
||||
it('it should handle a sequenceDiagram definition with a accessibility title and multiline description (accDescr)', function () {
|
||||
it('should handle a sequenceDiagram definition with a accessibility title and multiline description (accDescr)', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
accTitle: This is the title
|
||||
@@ -152,7 +227,7 @@ Alice->Bob:Hello Bob, how are you?
|
||||
const messages = diagram.db.getMessages();
|
||||
});
|
||||
|
||||
it('it should space in actor names', function () {
|
||||
it('should space in actor names', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob:Hello Bob, how are - you?
|
||||
@@ -169,7 +244,7 @@ Bob-->Alice: I am good thanks!`;
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[1].from).toBe('Bob');
|
||||
});
|
||||
it('it should handle dashes in actor names', function () {
|
||||
it('should handle dashes in actor names', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice-in-Wonderland->Bob:Hello Bob, how are - you?
|
||||
@@ -186,7 +261,7 @@ Bob-->Alice-in-Wonderland:I am good thanks!`;
|
||||
expect(messages[0].from).toBe('Alice-in-Wonderland');
|
||||
expect(messages[1].from).toBe('Bob');
|
||||
});
|
||||
it('it should alias participants', function () {
|
||||
it('should alias participants', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
participant A as Alice
|
||||
@@ -207,7 +282,7 @@ B-->A: I am good thanks!`;
|
||||
expect(messages[0].from).toBe('A');
|
||||
expect(messages[1].from).toBe('B');
|
||||
});
|
||||
it('it should alias a mix of actors and participants apa12', function () {
|
||||
it('should alias a mix of actors and participants apa12', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
actor Alice as Alice2
|
||||
@@ -235,7 +310,7 @@ sequenceDiagram
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[4].to).toBe('Joan');
|
||||
});
|
||||
it('it should alias actors apa13', function () {
|
||||
it('should alias actors apa13', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
actor A as Alice
|
||||
@@ -255,7 +330,7 @@ B-->A: I am good thanks!`;
|
||||
expect(messages[0].from).toBe('A');
|
||||
expect(messages[1].from).toBe('B');
|
||||
});
|
||||
it('it should handle in async messages', function () {
|
||||
it('should handle in async messages', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice-xBob:Hello Bob, how are you?`;
|
||||
@@ -270,7 +345,7 @@ Alice-xBob:Hello Bob, how are you?`;
|
||||
expect(messages.length).toBe(1);
|
||||
expect(messages[0].type).toBe(diagram.db.LINETYPE.SOLID_CROSS);
|
||||
});
|
||||
it('it should handle in async dotted messages', function () {
|
||||
it('should handle in async dotted messages', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice--xBob:Hello Bob, how are you?`;
|
||||
@@ -285,7 +360,7 @@ Alice--xBob:Hello Bob, how are you?`;
|
||||
expect(messages.length).toBe(1);
|
||||
expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED_CROSS);
|
||||
});
|
||||
it('it should handle in sync messages', function () {
|
||||
it('should handle in sync messages', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice-)Bob:Hello Bob, how are you?`;
|
||||
@@ -300,7 +375,7 @@ Alice-)Bob:Hello Bob, how are you?`;
|
||||
expect(messages.length).toBe(1);
|
||||
expect(messages[0].type).toBe(diagram.db.LINETYPE.SOLID_POINT);
|
||||
});
|
||||
it('it should handle in sync dotted messages', function () {
|
||||
it('should handle in sync dotted messages', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice--)Bob:Hello Bob, how are you?`;
|
||||
@@ -315,7 +390,7 @@ Alice--)Bob:Hello Bob, how are you?`;
|
||||
expect(messages.length).toBe(1);
|
||||
expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED_POINT);
|
||||
});
|
||||
it('it should handle in arrow messages', function () {
|
||||
it('should handle in arrow messages', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->>Bob:Hello Bob, how are you?`;
|
||||
@@ -330,7 +405,7 @@ Alice->>Bob:Hello Bob, how are you?`;
|
||||
expect(messages.length).toBe(1);
|
||||
expect(messages[0].type).toBe(diagram.db.LINETYPE.SOLID);
|
||||
});
|
||||
it('it should handle in arrow messages', function () {
|
||||
it('should handle in arrow messages', function () {
|
||||
const str = 'sequenceDiagram\n' + 'Alice-->>Bob:Hello Bob, how are you?';
|
||||
|
||||
mermaidAPI.parse(str);
|
||||
@@ -343,7 +418,7 @@ Alice->>Bob:Hello Bob, how are you?`;
|
||||
expect(messages.length).toBe(1);
|
||||
expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED);
|
||||
});
|
||||
it('it should handle actor activation', function () {
|
||||
it('should handle actor activation', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice-->>Bob:Hello Bob, how are you?
|
||||
@@ -366,7 +441,7 @@ deactivate Bob`;
|
||||
expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_END);
|
||||
expect(messages[3].from.actor).toBe('Bob');
|
||||
});
|
||||
it('it should handle actor one line notation activation', function () {
|
||||
it('should handle actor one line notation activation', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice-->>+Bob:Hello Bob, how are you?
|
||||
@@ -387,7 +462,7 @@ deactivate Bob`;
|
||||
expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_END);
|
||||
expect(messages[3].from.actor).toBe('Bob');
|
||||
});
|
||||
it('it should handle stacked activations', function () {
|
||||
it('should handle stacked activations', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice-->>+Bob:Hello Bob, how are you?
|
||||
@@ -414,7 +489,7 @@ deactivate Bob`;
|
||||
expect(messages[7].type).toBe(diagram.db.LINETYPE.ACTIVE_END);
|
||||
expect(messages[7].from.actor).toBe('Carol');
|
||||
});
|
||||
it('it should handle fail parsing when activating an inactive participant', function () {
|
||||
it('should handle fail parsing when activating an inactive participant', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
participant user as End User
|
||||
@@ -440,7 +515,7 @@ deactivate Bob`;
|
||||
expect(error).toBe(true);
|
||||
});
|
||||
|
||||
it('it should handle comments in a sequenceDiagram', function () {
|
||||
it('should handle comments in a sequenceDiagram', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -459,7 +534,7 @@ deactivate Bob`;
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[2].from).toBe('Bob');
|
||||
});
|
||||
it('it should handle new lines in a sequenceDiagram', function () {
|
||||
it('should handle new lines in a sequenceDiagram', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -480,7 +555,7 @@ deactivate Bob`;
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[2].from).toBe('Bob');
|
||||
});
|
||||
it('it should handle semicolons', function () {
|
||||
it('should handle semicolons', function () {
|
||||
const str = `
|
||||
sequenceDiagram;Alice->Bob: Hello Bob, how are you?;Note right of Bob: Bob thinks;Bob-->Alice: I am good thanks!;`;
|
||||
|
||||
@@ -495,7 +570,7 @@ sequenceDiagram;Alice->Bob: Hello Bob, how are you?;Note right of Bob: Bob think
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[2].from).toBe('Bob');
|
||||
});
|
||||
it('it should handle one leading space in lines in a sequenceDiagram', function () {
|
||||
it('should handle one leading space in lines in a sequenceDiagram', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -515,7 +590,7 @@ Bob-->Alice: I am good thanks!`;
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[2].from).toBe('Bob');
|
||||
});
|
||||
it('it should handle several leading spaces in lines in a sequenceDiagram', function () {
|
||||
it('should handle several leading spaces in lines in a sequenceDiagram', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -535,7 +610,7 @@ Bob-->Alice: I am good thanks!`;
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[2].from).toBe('Bob');
|
||||
});
|
||||
it('it should handle several leading spaces in lines in a sequenceDiagram', function () {
|
||||
it('should handle several leading spaces in lines in a sequenceDiagram', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
@@ -560,7 +635,7 @@ Bob-->John: Jolly good!`;
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[2].from).toBe('John');
|
||||
});
|
||||
it('it should handle different line breaks', function () {
|
||||
it('should handle different line breaks', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
participant 1 as multiline<br>text
|
||||
@@ -595,7 +670,7 @@ note right of 1: multiline<br \t/>text
|
||||
expect(messages[6].message).toBe('multiline<br \t/>text');
|
||||
expect(messages[7].message).toBe('multiline<br \t/>text');
|
||||
});
|
||||
it('it should handle notes and messages without wrap specified', function () {
|
||||
it('should handle notes and messages without wrap specified', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
participant 1
|
||||
@@ -634,7 +709,7 @@ note right of 1:nowrap: multiline<br/>text
|
||||
expect(messages[6].wrap).toBe(false);
|
||||
expect(messages[7].wrap).toBe(false);
|
||||
});
|
||||
it('it should handle notes and messages with wrap specified', function () {
|
||||
it('should handle notes and messages with wrap specified', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
participant 1
|
||||
@@ -659,7 +734,7 @@ note right of 3:wrap: multiline<br/>text
|
||||
expect(messages[2].wrap).toBe(true);
|
||||
expect(messages[3].wrap).toBe(true);
|
||||
});
|
||||
it('it should handle notes and messages with nowrap or line breaks', function () {
|
||||
it('should handle notes and messages with nowrap or line breaks', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
participant 1
|
||||
@@ -676,7 +751,7 @@ note right of 2: single-line text
|
||||
expect(messages[0].wrap).toBe(false);
|
||||
expect(messages[1].wrap).toBe(false);
|
||||
});
|
||||
it('it should handle notes over a single actor', function () {
|
||||
it('should handle notes over a single actor', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -689,7 +764,7 @@ Note over Bob: Bob thinks
|
||||
expect(messages[1].from).toBe('Bob');
|
||||
expect(messages[1].to).toBe('Bob');
|
||||
});
|
||||
it('it should handle notes over multiple actors', function () {
|
||||
it('should handle notes over multiple actors', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -705,7 +780,7 @@ Note over Bob,Alice: resolution
|
||||
expect(messages[2].from).toBe('Bob');
|
||||
expect(messages[2].to).toBe('Alice');
|
||||
});
|
||||
it('it should handle loop statements', function () {
|
||||
it('should handle loop statements', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -728,7 +803,7 @@ end`;
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[1].from).toBe('Bob');
|
||||
});
|
||||
it('it should add a rect around sequence', function () {
|
||||
it('should add a rect around sequence', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -752,7 +827,7 @@ end`;
|
||||
expect(messages[4].type).toEqual(diagram.db.LINETYPE.RECT_END);
|
||||
});
|
||||
|
||||
it('it should allow for nested rects', function () {
|
||||
it('should allow for nested rects', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -779,7 +854,7 @@ end`;
|
||||
expect(messages[5].type).toEqual(diagram.db.LINETYPE.DOTTED_OPEN);
|
||||
expect(messages[6].type).toEqual(diagram.db.LINETYPE.RECT_END);
|
||||
});
|
||||
it('it should handle opt statements', function () {
|
||||
it('should handle opt statements', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -802,7 +877,7 @@ end`;
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[1].from).toBe('Bob');
|
||||
});
|
||||
it('it should handle alt statements', function () {
|
||||
it('should handle alt statements', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -828,7 +903,7 @@ end`;
|
||||
expect(messages[0].from).toBe('Alice');
|
||||
expect(messages[1].from).toBe('Bob');
|
||||
});
|
||||
it('it should handle alt statements with multiple elses', function () {
|
||||
it('should handle alt statements with multiple elses', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -855,7 +930,7 @@ end`;
|
||||
expect(messages[7].from).toBe('Bob');
|
||||
expect(messages[8].type).toBe(diagram.db.LINETYPE.ALT_END);
|
||||
});
|
||||
it('it should handle critical statements without options', function () {
|
||||
it('should handle critical statements without options', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
critical Establish a connection to the DB
|
||||
@@ -875,7 +950,7 @@ sequenceDiagram
|
||||
expect(messages[1].from).toBe('Service');
|
||||
expect(messages[2].type).toBe(diagram.db.LINETYPE.CRITICAL_END);
|
||||
});
|
||||
it('it should handle critical statements with options', function () {
|
||||
it('should handle critical statements with options', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
critical Establish a connection to the DB
|
||||
@@ -903,7 +978,7 @@ sequenceDiagram
|
||||
expect(messages[5].from).toBe('Service');
|
||||
expect(messages[6].type).toBe(diagram.db.LINETYPE.CRITICAL_END);
|
||||
});
|
||||
it('it should handle break statements', function () {
|
||||
it('should handle break statements', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Consumer-->API: Book something
|
||||
@@ -929,7 +1004,7 @@ sequenceDiagram
|
||||
expect(messages[4].type).toBe(diagram.db.LINETYPE.BREAK_END);
|
||||
expect(messages[5].from).toBe('API');
|
||||
});
|
||||
it('it should handle par statements a sequenceDiagram', function () {
|
||||
it('should handle par statements a sequenceDiagram', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
par Parallel one
|
||||
@@ -956,7 +1031,7 @@ end`;
|
||||
expect(messages[1].from).toBe('Alice');
|
||||
expect(messages[2].from).toBe('Bob');
|
||||
});
|
||||
it('it should handle special characters in signals', function () {
|
||||
it('should handle special characters in signals', function () {
|
||||
const str = 'sequenceDiagram\n' + 'Alice->Bob: -:<>,;# comment';
|
||||
|
||||
mermaidAPI.parse(str);
|
||||
@@ -964,7 +1039,7 @@ end`;
|
||||
const messages = diagram.db.getMessages();
|
||||
expect(messages[0].message).toBe('-:<>,');
|
||||
});
|
||||
it('it should handle special characters in notes', function () {
|
||||
it('should handle special characters in notes', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -975,7 +1050,7 @@ Note right of Bob: -:<>,;# comment`;
|
||||
const messages = diagram.db.getMessages();
|
||||
expect(messages[1].message).toBe('-:<>,');
|
||||
});
|
||||
it('it should handle special characters in loop', function () {
|
||||
it('should handle special characters in loop', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -988,7 +1063,7 @@ end`;
|
||||
const messages = diagram.db.getMessages();
|
||||
expect(messages[1].message).toBe('-:<>,');
|
||||
});
|
||||
it('it should handle special characters in opt', function () {
|
||||
it('should handle special characters in opt', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -1001,7 +1076,7 @@ end`;
|
||||
const messages = diagram.db.getMessages();
|
||||
expect(messages[1].message).toBe('-:<>,');
|
||||
});
|
||||
it('it should handle special characters in alt', function () {
|
||||
it('should handle special characters in alt', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -1017,7 +1092,7 @@ end`;
|
||||
expect(messages[1].message).toBe('-:<>,');
|
||||
expect(messages[3].message).toBe(',<>:-');
|
||||
});
|
||||
it('it should handle special characters in par', function () {
|
||||
it('should handle special characters in par', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -1033,7 +1108,7 @@ end`;
|
||||
expect(messages[1].message).toBe('-:<>,');
|
||||
expect(messages[3].message).toBe(',<>:-');
|
||||
});
|
||||
it('it should handle no-label loop', function () {
|
||||
it('should handle no-label loop', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -1047,7 +1122,7 @@ end`;
|
||||
expect(messages[1].message).toBe('');
|
||||
expect(messages[2].message).toBe('I am good thanks!');
|
||||
});
|
||||
it('it should handle no-label opt', function () {
|
||||
it('should handle no-label opt', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -1061,7 +1136,7 @@ end`;
|
||||
expect(messages[1].message).toBe('');
|
||||
expect(messages[2].message).toBe('I am good thanks!');
|
||||
});
|
||||
it('it should handle no-label alt', function () {
|
||||
it('should handle no-label alt', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -1078,7 +1153,7 @@ end`;
|
||||
expect(messages[3].message).toBe('');
|
||||
expect(messages[4].message).toBe('I am good thanks!');
|
||||
});
|
||||
it('it should handle no-label par', function () {
|
||||
it('should handle no-label par', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -1096,7 +1171,7 @@ end`;
|
||||
expect(messages[4].message).toBe('I am good thanks!');
|
||||
});
|
||||
|
||||
it('it should handle links', function () {
|
||||
it('should handle links', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
participant a as Alice
|
||||
@@ -1123,7 +1198,7 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com
|
||||
expect(actors.a.links['Tests']).toBe('https://tests.contoso.com/?svc=alice@contoso.com');
|
||||
});
|
||||
|
||||
it('it should handle properties EXPERIMENTAL: USE WITH CAUTION', function () {
|
||||
it('should handle properties EXPERIMENTAL: USE WITH CAUTION', function () {
|
||||
//Be aware that the syntax for "properties" is likely to be changed.
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
@@ -1170,7 +1245,7 @@ describe('when checking the bounds in a sequenceDiagram', function () {
|
||||
diagram.renderer.bounds.init();
|
||||
conf = diagram.db.getConfig();
|
||||
});
|
||||
it('it should handle a simple bound call', function () {
|
||||
it('should handle a simple bound call', function () {
|
||||
diagram.renderer.bounds.insert(100, 100, 200, 200);
|
||||
|
||||
const { bounds } = diagram.renderer.bounds.getBounds();
|
||||
@@ -1179,7 +1254,7 @@ describe('when checking the bounds in a sequenceDiagram', function () {
|
||||
expect(bounds.stopx).toBe(200);
|
||||
expect(bounds.stopy).toBe(200);
|
||||
});
|
||||
it('it should handle an expanding bound', function () {
|
||||
it('should handle an expanding bound', function () {
|
||||
diagram.renderer.bounds.insert(100, 100, 200, 200);
|
||||
diagram.renderer.bounds.insert(25, 50, 300, 400);
|
||||
|
||||
@@ -1189,7 +1264,7 @@ describe('when checking the bounds in a sequenceDiagram', function () {
|
||||
expect(bounds.stopx).toBe(300);
|
||||
expect(bounds.stopy).toBe(400);
|
||||
});
|
||||
it('it should handle inserts within the bound without changing the outer bounds', function () {
|
||||
it('should handle inserts within the bound without changing the outer bounds', function () {
|
||||
diagram.renderer.bounds.insert(100, 100, 200, 200);
|
||||
diagram.renderer.bounds.insert(25, 50, 300, 400);
|
||||
diagram.renderer.bounds.insert(125, 150, 150, 200);
|
||||
@@ -1200,7 +1275,7 @@ describe('when checking the bounds in a sequenceDiagram', function () {
|
||||
expect(bounds.stopx).toBe(300);
|
||||
expect(bounds.stopy).toBe(400);
|
||||
});
|
||||
it('it should handle a loop without expanding the area', function () {
|
||||
it('should handle a loop without expanding the area', function () {
|
||||
diagram.renderer.bounds.insert(25, 50, 300, 400);
|
||||
diagram.renderer.bounds.verticalPos = 150;
|
||||
diagram.renderer.bounds.newLoop();
|
||||
@@ -1221,7 +1296,7 @@ describe('when checking the bounds in a sequenceDiagram', function () {
|
||||
expect(bounds.stopx).toBe(300);
|
||||
expect(bounds.stopy).toBe(400);
|
||||
});
|
||||
it('it should handle multiple loops withtout expanding the bounds', function () {
|
||||
it('should handle multiple loops withtout expanding the bounds', function () {
|
||||
diagram.renderer.bounds.insert(100, 100, 1000, 1000);
|
||||
diagram.renderer.bounds.verticalPos = 200;
|
||||
diagram.renderer.bounds.newLoop();
|
||||
@@ -1252,7 +1327,7 @@ describe('when checking the bounds in a sequenceDiagram', function () {
|
||||
expect(bounds.stopx).toBe(1000);
|
||||
expect(bounds.stopy).toBe(1000);
|
||||
});
|
||||
it('it should handle a loop that expands the area', function () {
|
||||
it('should handle a loop that expands the area', function () {
|
||||
diagram.renderer.bounds.insert(100, 100, 200, 200);
|
||||
diagram.renderer.bounds.verticalPos = 200;
|
||||
diagram.renderer.bounds.newLoop();
|
||||
@@ -1339,7 +1414,7 @@ participant Alice`;
|
||||
expect(bounds.stopy).toBe(conf.height);
|
||||
});
|
||||
});
|
||||
it('it should handle same actor with different whitespace properly', function () {
|
||||
it('should handle same actor with different whitespace properly', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
@@ -1352,7 +1427,7 @@ participant Alice
|
||||
const actors = diagram.db.getActors();
|
||||
expect(Object.keys(actors)).toEqual(['Alice']);
|
||||
});
|
||||
it('it should handle one actor and a centered note', function () {
|
||||
it('should handle one actor and a centered note', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
@@ -1370,7 +1445,7 @@ Note over Alice: Alice thinks
|
||||
// 10 comes from mock of text height
|
||||
expect(bounds.stopy).toBe(models.lastNote().stopy);
|
||||
});
|
||||
it('it should handle one actor and a note to the left', function () {
|
||||
it('should handle one actor and a note to the left', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
@@ -1386,7 +1461,7 @@ Note left of Alice: Alice thinks`;
|
||||
// 10 comes from mock of text height
|
||||
expect(bounds.stopy).toBe(models.lastNote().stopy);
|
||||
});
|
||||
it('it should handle one actor and a note to the right', function () {
|
||||
it('should handle one actor and a note to the right', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
@@ -1402,7 +1477,7 @@ Note right of Alice: Alice thinks`;
|
||||
// 10 comes from mock of text height
|
||||
expect(bounds.stopy).toBe(models.lastNote().stopy);
|
||||
});
|
||||
it('it should handle two actors', function () {
|
||||
it('should handle two actors', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?`;
|
||||
@@ -1416,7 +1491,7 @@ Alice->Bob: Hello Bob, how are you?`;
|
||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||
expect(bounds.stopy).toBe(models.lastMessage().stopy + 10);
|
||||
});
|
||||
it('it should handle two actors with init directive', function () {
|
||||
it('should handle two actors with init directive', function () {
|
||||
const str = `
|
||||
%%{init: {'logLevel': 0}}%%
|
||||
sequenceDiagram
|
||||
@@ -1433,7 +1508,7 @@ Alice->Bob: Hello Bob, how are you?`;
|
||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||
expect(bounds.stopy).toBe(models.lastMessage().stopy + 10);
|
||||
});
|
||||
it('it should handle two actors with init directive with multiline directive', function () {
|
||||
it('should handle two actors with init directive with multiline directive', function () {
|
||||
const str = `
|
||||
%%{init: { 'logLevel': 0}}%%
|
||||
sequenceDiagram
|
||||
@@ -1455,7 +1530,7 @@ Alice->Bob: Hello Bob, how are you?`;
|
||||
expect(bounds.stopy).toBe(models.lastMessage().stopy + 10);
|
||||
expect(msgs.every((v) => v.wrap)).toBe(true);
|
||||
});
|
||||
it('it should handle two actors and two centered shared notes', function () {
|
||||
it('should handle two actors and two centered shared notes', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -1472,7 +1547,7 @@ Note over Bob,Alice: Looks back
|
||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||
expect(bounds.stopy).toBe(models.lastNote().stopy);
|
||||
});
|
||||
it('it should draw two actors and two messages', function () {
|
||||
it('should draw two actors and two messages', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -1487,7 +1562,7 @@ Bob->Alice: Fine!`;
|
||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||
expect(bounds.stopy).toBe(models.lastMessage().stopy + 10);
|
||||
});
|
||||
it('it should draw two actors notes to the right', function () {
|
||||
it('should draw two actors notes to the right', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -1506,7 +1581,7 @@ Bob->Alice: Fine!`;
|
||||
expect(bounds.stopx).toBe(expStopX);
|
||||
expect(bounds.stopy).toBe(models.lastMessage().stopy + 10);
|
||||
});
|
||||
it('it should draw two actors notes to the left', function () {
|
||||
it('should draw two actors notes to the left', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -1523,7 +1598,7 @@ Bob->Alice: Fine!`;
|
||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||
expect(bounds.stopy).toBe(models.lastMessage().stopy + 10);
|
||||
});
|
||||
it('it should draw two actors notes to the left with text wrapped (inline)', function () {
|
||||
it('should draw two actors notes to the left with text wrapped (inline)', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->>Bob:wrap: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can!
|
||||
@@ -1542,7 +1617,7 @@ Bob->>Alice: Fine!`;
|
||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||
expect(bounds.stopy).toBe(models.lastMessage().stopy + 10);
|
||||
});
|
||||
it('it should draw two actors notes to the left with text wrapped (directive)', function () {
|
||||
it('should draw two actors notes to the left with text wrapped (directive)', function () {
|
||||
const str = `
|
||||
%%{init: { 'theme': 'dark' } }%%
|
||||
sequenceDiagram
|
||||
@@ -1565,7 +1640,7 @@ Bob->>Alice: Fine!`;
|
||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||
expect(bounds.stopy).toBe(models.lastMessage().stopy + 10);
|
||||
});
|
||||
it('it should draw two actors notes to the left with text wrapped and the init directive sets the theme to dark', function () {
|
||||
it('should draw two actors notes to the left with text wrapped and the init directive sets the theme to dark', function () {
|
||||
const str = `
|
||||
%%{init:{'theme':'dark'}}%%
|
||||
sequenceDiagram
|
||||
@@ -1588,7 +1663,7 @@ Bob->>Alice: Fine!`;
|
||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||
expect(bounds.stopy).toBe(models.lastMessage().stopy + 10);
|
||||
});
|
||||
it('it should draw two actors, notes to the left with text wrapped and the init directive sets the theme to dark and fontFamily to Menlo, fontSize to 18, and fontWeight to 800', function () {
|
||||
it('should draw two actors, notes to the left with text wrapped and the init directive sets the theme to dark and fontFamily to Menlo, fontSize to 18, and fontWeight to 800', function () {
|
||||
const str = `
|
||||
%%{init: { "theme": "dark", 'config': { "fontFamily": "Menlo", "fontSize": 18, "messageFontWeight": 400, "wrap": true }}}%%
|
||||
sequenceDiagram
|
||||
@@ -1613,7 +1688,7 @@ Bob->>Alice: Fine!`;
|
||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||
expect(bounds.stopy).toBe(models.lastMessage().stopy + 10);
|
||||
});
|
||||
it('it should draw two loops', function () {
|
||||
it('should draw two loops', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, how are you?
|
||||
@@ -1630,7 +1705,7 @@ end`;
|
||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||
expect(bounds.stopy).toBe(models.lastLoop().stopy);
|
||||
});
|
||||
it('it should draw background rect', function () {
|
||||
it('should draw background rect', function () {
|
||||
const str = `
|
||||
sequenceDiagram
|
||||
Alice->Bob: Hello Bob, are you alright?
|
||||
@@ -1680,7 +1755,7 @@ describe('when rendering a sequenceDiagram with actor mirror activated', functio
|
||||
diagram.renderer.bounds.init();
|
||||
});
|
||||
['tspan', 'fo', 'old', undefined].forEach(function (textPlacement) {
|
||||
it('it should handle one actor, when textPlacement is' + textPlacement, function () {
|
||||
it('should handle one actor, when textPlacement is' + textPlacement, function () {
|
||||
mermaidAPI.initialize(addConf(conf, 'textPlacement', textPlacement));
|
||||
diagram.renderer.bounds.init();
|
||||
const str = `
|
||||
@@ -1724,7 +1799,7 @@ describe('when rendering a sequenceDiagram with directives', function () {
|
||||
diagram.renderer.bounds.init();
|
||||
});
|
||||
|
||||
it('it should handle one actor, when theme is dark and logLevel is 1 DX1', function () {
|
||||
it('should handle one actor, when theme is dark and logLevel is 1 DX1', function () {
|
||||
const str = `
|
||||
%%{init: { "theme": "dark", "logLevel": 1 } }%%
|
||||
sequenceDiagram
|
||||
@@ -1748,7 +1823,7 @@ participant Alice
|
||||
models.lastActor().y + models.lastActor().height + mermaid.sequence.boxMargin
|
||||
);
|
||||
});
|
||||
it('it should handle one actor, when logLevel is 3', function () {
|
||||
it('should handle one actor, when logLevel is 3', function () {
|
||||
const str = `
|
||||
%%{initialize: { "logLevel": 3 }}%%
|
||||
sequenceDiagram
|
||||
@@ -1768,7 +1843,7 @@ participant Alice
|
||||
models.lastActor().y + models.lastActor().height + mermaid.sequence.boxMargin
|
||||
);
|
||||
});
|
||||
it('it should hide sequence numbers when autonumber is removed when autonumber is enabled', function () {
|
||||
it('should hide sequence numbers when autonumber is removed when autonumber is enabled', function () {
|
||||
const str1 = `
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
|
||||
@@ -45,7 +45,7 @@ const getStyles = (options) =>
|
||||
|
||||
.messageText {
|
||||
fill: ${options.signalTextColor};
|
||||
stroke: ${options.signalTextColor};
|
||||
stroke: none;
|
||||
}
|
||||
|
||||
.labelBox {
|
||||
|
||||
@@ -3,7 +3,7 @@ const { MockD3 } = require('d3');
|
||||
|
||||
describe('svgDraw', function () {
|
||||
describe('drawRect', function () {
|
||||
it('it should append a rectangle', function () {
|
||||
it('should append a rectangle', function () {
|
||||
const svg = MockD3('svg');
|
||||
svgDraw.drawRect(svg, {
|
||||
x: 10,
|
||||
@@ -29,7 +29,7 @@ describe('svgDraw', function () {
|
||||
expect(rect.attr).toHaveBeenCalledWith('ry', '10');
|
||||
expect(rect.attr).toHaveBeenCalledWith('class', 'unitTestRectangleClass');
|
||||
});
|
||||
it('it should not add the class attribute if a class isn`t provided', () => {
|
||||
it('should not add the class attribute if a class isn`t provided', () => {
|
||||
const svg = MockD3('svg');
|
||||
svgDraw.drawRect(svg, {
|
||||
x: 10,
|
||||
@@ -49,7 +49,7 @@ describe('svgDraw', function () {
|
||||
});
|
||||
});
|
||||
describe('drawText', function () {
|
||||
it('it should append a single element', function () {
|
||||
it('should append a single element', function () {
|
||||
const svg = MockD3('svg');
|
||||
svgDraw.drawText(svg, {
|
||||
x: 10,
|
||||
@@ -73,7 +73,7 @@ describe('svgDraw', function () {
|
||||
expect(text.style).toHaveBeenCalledWith('font-size', '10px');
|
||||
expect(text.style).toHaveBeenCalledWith('font-weight', '500');
|
||||
});
|
||||
it('it should append a multiple elements', function () {
|
||||
it('should append a multiple elements', function () {
|
||||
const svg = MockD3('svg');
|
||||
svgDraw.drawText(svg, {
|
||||
x: 10,
|
||||
@@ -101,7 +101,7 @@ describe('svgDraw', function () {
|
||||
});
|
||||
});
|
||||
describe('drawBackgroundRect', function () {
|
||||
it('it should append a rect before the previous element within a given bound', function () {
|
||||
it('should append a rect before the previous element within a given bound', function () {
|
||||
const svg = MockD3('svg');
|
||||
const boundingRect = {
|
||||
startx: 50,
|
||||
@@ -125,12 +125,12 @@ describe('svgDraw', function () {
|
||||
});
|
||||
});
|
||||
describe('sanitizeUrl', function () {
|
||||
it('it should sanitize malicious urls', function () {
|
||||
it('should sanitize malicious urls', function () {
|
||||
const maliciousStr = 'javascript:script:alert(1)';
|
||||
const result = svgDraw.sanitizeUrl(maliciousStr);
|
||||
expect(result).not.toContain('javascript:alert(1)');
|
||||
});
|
||||
it('it should not sanitize non dangerous urls', function () {
|
||||
it('should not sanitize non dangerous urls', function () {
|
||||
const maliciousStr = 'javajavascript:script:alert(1)';
|
||||
const result = svgDraw.sanitizeUrl(maliciousStr);
|
||||
expect(result).not.toContain('javascript:alert(1)');
|
||||
|
||||
@@ -19,7 +19,7 @@ describe('when parsing a journey diagram it', function () {
|
||||
expect(parserFnConstructor(str)).not.toThrow();
|
||||
});
|
||||
|
||||
it('it should handle an accessibility description (accDescr)', function () {
|
||||
it('should handle an accessibility description (accDescr)', function () {
|
||||
const str =
|
||||
'journey\n' +
|
||||
'accDescr: A user journey for family shopping\n' +
|
||||
@@ -28,7 +28,7 @@ describe('when parsing a journey diagram it', function () {
|
||||
|
||||
expect(parserFnConstructor(str)).not.toThrow();
|
||||
});
|
||||
it('it should handle an accessibility multiline description (accDescr)', function () {
|
||||
it('should handle an accessibility multiline description (accDescr)', function () {
|
||||
const str =
|
||||
'journey\n' +
|
||||
`accDescr {
|
||||
@@ -44,7 +44,7 @@ describe('when parsing a journey diagram it', function () {
|
||||
expect(journeyDb.getDiagramTitle()).toBe('Adding journey diagram functionality to mermaid');
|
||||
expect(journeyDb.getAccTitle()).toBe('Adding acc journey diagram functionality to mermaid');
|
||||
});
|
||||
it('it should handle an accessibility title (accDescr)', function () {
|
||||
it('should handle an accessibility title (accDescr)', function () {
|
||||
const str = `journey
|
||||
accTitle: The title
|
||||
section Order from website`;
|
||||
|
||||
@@ -34,7 +34,7 @@ const init = function () {
|
||||
initThrowsErrors(...arguments);
|
||||
} catch (e) {
|
||||
log.warn('Syntax Error rendering');
|
||||
log.warn(e);
|
||||
log.warn(e.str);
|
||||
if (this.parseError) {
|
||||
this.parseError(e);
|
||||
}
|
||||
@@ -120,19 +120,23 @@ const initThrowsErrors = function () {
|
||||
if (init) {
|
||||
log.debug('Detected early reinit: ', init);
|
||||
}
|
||||
|
||||
mermaidAPI.render(
|
||||
id,
|
||||
txt,
|
||||
(svgCode, bindFunctions) => {
|
||||
element.innerHTML = svgCode;
|
||||
if (typeof callback !== 'undefined') {
|
||||
callback(id);
|
||||
}
|
||||
if (bindFunctions) bindFunctions(element);
|
||||
},
|
||||
element
|
||||
);
|
||||
try {
|
||||
mermaidAPI.render(
|
||||
id,
|
||||
txt,
|
||||
(svgCode, bindFunctions) => {
|
||||
element.innerHTML = svgCode;
|
||||
if (typeof callback !== 'undefined') {
|
||||
callback(id);
|
||||
}
|
||||
if (bindFunctions) bindFunctions(element);
|
||||
},
|
||||
element
|
||||
);
|
||||
} catch (error) {
|
||||
log.warn('Catching Error (bootstrap)');
|
||||
throw { error, message: error.str };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ describe('when using mermaid and ', function () {
|
||||
flowDb.clear();
|
||||
flowDb.setGen('gen-2');
|
||||
});
|
||||
it('it should handle edges with text', function () {
|
||||
it('should handle edges with text', function () {
|
||||
const diag = new Diagram('graph TD;A-->|text ex|B;');
|
||||
diag.db.getVertices();
|
||||
const edges = diag.db.getEdges();
|
||||
@@ -189,18 +189,18 @@ describe('when using mermaid and ', function () {
|
||||
flowDb.clear();
|
||||
flowDb.setGen('gen-2');
|
||||
});
|
||||
it('it should throw for an invalid definition', function () {
|
||||
it('should throw for an invalid definition', function () {
|
||||
expect(() => mermaid.parse('this is not a mermaid diagram definition')).toThrow();
|
||||
});
|
||||
|
||||
it('it should not throw for a valid flow definition', function () {
|
||||
it('should not throw for a valid flow definition', function () {
|
||||
expect(() => mermaid.parse('graph TD;A--x|text including URL space|B;')).not.toThrow();
|
||||
});
|
||||
it('it should throw for an invalid flow definition', function () {
|
||||
it('should throw for an invalid flow definition', function () {
|
||||
expect(() => mermaid.parse('graph TQ;A--x|text including URL space|B;')).toThrow();
|
||||
});
|
||||
|
||||
it('it should not throw for a valid sequenceDiagram definition', function () {
|
||||
it('should not throw for a valid sequenceDiagram definition', function () {
|
||||
const text =
|
||||
'sequenceDiagram\n' +
|
||||
'Alice->Bob: Hello Bob, how are you?\n\n' +
|
||||
@@ -214,7 +214,7 @@ describe('when using mermaid and ', function () {
|
||||
expect(() => mermaid.parse(text)).not.toThrow();
|
||||
});
|
||||
|
||||
it('it should throw for an invalid sequenceDiagram definition', function () {
|
||||
it('should throw for an invalid sequenceDiagram definition', function () {
|
||||
const text =
|
||||
'sequenceDiagram\n' +
|
||||
'Alice:->Bob: Hello Bob, how are you?\n\n' +
|
||||
|
||||
@@ -40,13 +40,21 @@ import utils, { directiveSanitizer } from './utils';
|
||||
import assignWithDepth from './assignWithDepth';
|
||||
import DOMPurify from 'dompurify';
|
||||
import mermaid from './mermaid';
|
||||
|
||||
let hasLoadedDiagrams = false;
|
||||
|
||||
/**
|
||||
* @param text
|
||||
* @param dia
|
||||
* @returns {any}
|
||||
*/
|
||||
function parse(text, dia) {
|
||||
if (!hasLoadedDiagrams) {
|
||||
addDiagrams();
|
||||
hasLoadedDiagrams = true;
|
||||
}
|
||||
var parseEncounteredException = false;
|
||||
|
||||
try {
|
||||
const diag = dia ? dia : new Diagram(text);
|
||||
diag.db.clear();
|
||||
@@ -133,7 +141,7 @@ export const decodeEntities = function (text) {
|
||||
* @param {any} _txt The graph definition
|
||||
* @param {any} cb Callback which is called after rendering is finished with the svg code as inparam.
|
||||
* @param {any} container Selector to element in which a div with the graph temporarily will be
|
||||
* inserted. In one is provided a hidden div will be inserted in the body of the page instead. The
|
||||
* inserted. If one is provided a hidden div will be inserted in the body of the page instead. The
|
||||
* element will be removed when rendering is completed.
|
||||
* @returns {any}
|
||||
*/
|
||||
@@ -250,7 +258,7 @@ const render = function (id, _txt, cb, container) {
|
||||
|
||||
txt = encodeEntities(txt);
|
||||
|
||||
// Imortant that we do not create the diagram until after the directives have been included
|
||||
// Important that we do not create the diagram until after the directives have been included
|
||||
const diag = new Diagram(txt);
|
||||
// Get the tmp element containing the the svg
|
||||
const element = root.select('#d' + id).node();
|
||||
@@ -491,23 +499,20 @@ function updateRendererConfigs(conf) {
|
||||
/** @param {any} options */
|
||||
function initialize(options) {
|
||||
// Handle legacy location of font-family configuration
|
||||
if (options && options.fontFamily) {
|
||||
if (!options.themeVariables) {
|
||||
if (options?.fontFamily) {
|
||||
if (!options.themeVariables?.fontFamily) {
|
||||
options.themeVariables = { fontFamily: options.fontFamily };
|
||||
} else {
|
||||
if (!options.themeVariables.fontFamily) {
|
||||
options.themeVariables = { fontFamily: options.fontFamily };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set default options
|
||||
configApi.saveConfigFromInitialize(options);
|
||||
|
||||
if (options && options.theme && theme[options.theme]) {
|
||||
if (options?.theme && theme[options.theme]) {
|
||||
// Todo merge with user options
|
||||
options.themeVariables = theme[options.theme].getThemeVariables(options.themeVariables);
|
||||
} else {
|
||||
if (options) options.themeVariables = theme.default.getThemeVariables(options.themeVariables);
|
||||
} else if (options) {
|
||||
options.themeVariables = theme.default.getThemeVariables(options.themeVariables);
|
||||
}
|
||||
|
||||
const config =
|
||||
@@ -515,7 +520,10 @@ function initialize(options) {
|
||||
|
||||
updateRendererConfigs(config);
|
||||
setLogLevel(config.logLevel);
|
||||
addDiagrams();
|
||||
if (!hasLoadedDiagrams) {
|
||||
addDiagrams();
|
||||
hasLoadedDiagrams = true;
|
||||
}
|
||||
}
|
||||
|
||||
const mermaidAPI = Object.freeze({
|
||||
|
||||
@@ -122,14 +122,14 @@ describe('when using mermaidAPI and ', function () {
|
||||
});
|
||||
describe('test mermaidApi.parse() for checking validity of input ', function () {
|
||||
mermaid.parseError = undefined; // ensure it parseError undefined
|
||||
it('it should throw for an invalid definition (with no mermaid.parseError() defined)', function () {
|
||||
it('should throw for an invalid definition (with no mermaid.parseError() defined)', function () {
|
||||
expect(mermaid.parseError).toEqual(undefined);
|
||||
expect(() => mermaidAPI.parse('this is not a mermaid diagram definition')).toThrow();
|
||||
});
|
||||
it('it should not throw for a valid definition', function () {
|
||||
it('should not throw for a valid definition', function () {
|
||||
expect(() => mermaidAPI.parse('graph TD;A--x|text including URL space|B;')).not.toThrow();
|
||||
});
|
||||
it('it should return false for invalid definition WITH a parseError() callback defined', function () {
|
||||
it('should return false for invalid definition WITH a parseError() callback defined', function () {
|
||||
var parseErrorWasCalled = false;
|
||||
// also test setParseErrorHandler() call working to set mermaid.parseError
|
||||
mermaid.setParseErrorHandler(function (error, hash) {
|
||||
@@ -140,7 +140,7 @@ describe('when using mermaidAPI and ', function () {
|
||||
expect(mermaidAPI.parse('this is not a mermaid diagram definition')).toEqual(false);
|
||||
expect(parseErrorWasCalled).toEqual(true);
|
||||
});
|
||||
it('it should return true for valid definition', function () {
|
||||
it('should return true for valid definition', function () {
|
||||
expect(mermaidAPI.parse('graph TD;A--x|text including URL space|B;')).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user