mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-18 06:49:47 +02:00

* develop: chore(deps-dev): bump @commitlint/cli from 17.0.3 to 17.1.1 (#3376) chore(deps-dev): bump eslint from 8.22.0 to 8.23.0 (#3378) chore(deps): bump dompurify from 2.3.10 to 2.4.0 (#3375) chore(deps-dev): bump @commitlint/config-conventional (#3370) chore(deps-dev): bump @babel/core from 7.18.10 to 7.18.13 (#3373) chore(deps-dev): bump eslint-plugin-jest from 26.8.7 to 27.0.1 (#3372) chore(deps-dev): bump jest-environment-jsdom from 28.1.3 to 29.0.1 (#3369) chore(deps-dev): bump babel-jest from 28.1.3 to 29.0.1 (#3368) Updating docs to latest mermaid version build: add eslint --cache file Adjusting size and test Updated viewBox settings Border feat(git): allow custom merge commit ids Document line curve options Added 'ms' duration Fix font weight for messages in sequence diagrams Added lollipop feature for updated codebase
337 lines
11 KiB
JavaScript
337 lines
11 KiB
JavaScript
import utils from './utils';
|
|
import assignWithDepth from './assignWithDepth';
|
|
import { detectType } from './diagram-api/detectType';
|
|
import { addDiagrams } from './diagram-api/diagram-orchestration';
|
|
|
|
addDiagrams();
|
|
|
|
describe('when assignWithDepth: should merge objects within objects', function () {
|
|
it('should handle simple, depth:1 types (identity)', function () {
|
|
let config_0 = { foo: 'bar', bar: 0 };
|
|
let config_1 = { foo: 'bar', bar: 0 };
|
|
let result = assignWithDepth(config_0, config_1);
|
|
expect(result).toEqual(config_1);
|
|
});
|
|
it('should handle simple, depth:1 types (dst: undefined)', function () {
|
|
let config_0 = undefined;
|
|
let config_1 = { foo: 'bar', bar: 0 };
|
|
let result = assignWithDepth(config_0, config_1);
|
|
expect(result).toEqual(config_1);
|
|
});
|
|
it('should handle simple, depth:1 types (src: undefined)', function () {
|
|
let config_0 = { foo: 'bar', bar: 0 };
|
|
let config_1 = undefined;
|
|
let result = assignWithDepth(config_0, config_1);
|
|
expect(result).toEqual(config_0);
|
|
});
|
|
it('should handle simple, depth:1 types (merge)', function () {
|
|
let config_0 = { foo: 'bar', bar: 0 };
|
|
let config_1 = { foo: 'foo' };
|
|
let result = assignWithDepth(config_0, config_1);
|
|
expect(result).toEqual({ foo: 'foo', bar: 0 });
|
|
});
|
|
it('should handle depth:2 types (dst: orphan)', function () {
|
|
let config_0 = { foo: 'bar', bar: { foo: 'bar' } };
|
|
let config_1 = { foo: 'bar' };
|
|
let result = assignWithDepth(config_0, config_1);
|
|
expect(result).toEqual(config_0);
|
|
});
|
|
it('should handle depth:2 types (dst: object, src: simple type)', function () {
|
|
let config_0 = { foo: 'bar', bar: { foo: 'bar' } };
|
|
let config_1 = { foo: 'foo', bar: 'should NOT clobber' };
|
|
let result = assignWithDepth(config_0, config_1);
|
|
expect(result).toEqual({ foo: 'foo', bar: { foo: 'bar' } });
|
|
});
|
|
it('should handle depth:2 types (src: orphan)', function () {
|
|
let config_0 = { foo: 'bar' };
|
|
let config_1 = { foo: 'bar', bar: { foo: 'bar' } };
|
|
let result = assignWithDepth(config_0, config_1);
|
|
expect(result).toEqual(config_1);
|
|
});
|
|
it('should handle depth:2 types (merge)', function () {
|
|
let config_0 = { foo: 'bar', bar: { foo: 'bar' }, boofar: 1 };
|
|
let config_1 = { foo: 'foo', bar: { bar: 0 }, foobar: 'foobar' };
|
|
let result = assignWithDepth(config_0, config_1);
|
|
expect(result).toEqual({
|
|
foo: 'foo',
|
|
bar: { foo: 'bar', bar: 0 },
|
|
foobar: 'foobar',
|
|
boofar: 1,
|
|
});
|
|
});
|
|
it('should handle depth:3 types (merge with clobber because assignWithDepth::depth == 2)', function () {
|
|
let config_0 = {
|
|
foo: 'bar',
|
|
bar: { foo: 'bar', bar: { foo: { message: 'this', willbe: 'clobbered' } } },
|
|
boofar: 1,
|
|
};
|
|
let config_1 = {
|
|
foo: 'foo',
|
|
bar: { foo: 'foo', bar: { foo: { message: 'clobbered other foo' } } },
|
|
foobar: 'foobar',
|
|
};
|
|
let result = assignWithDepth(config_0, config_1);
|
|
expect(result).toEqual({
|
|
foo: 'foo',
|
|
bar: { foo: 'foo', bar: { foo: { message: 'clobbered other foo' } } },
|
|
foobar: 'foobar',
|
|
boofar: 1,
|
|
});
|
|
});
|
|
it('should handle depth:3 types (merge with clobber because assignWithDepth::depth == 1)', function () {
|
|
let config_0 = {
|
|
foo: 'bar',
|
|
bar: {
|
|
foo: 'bar',
|
|
bar: { foo: { message: '', willNotbe: 'present' }, bar: 'shouldNotBePresent' },
|
|
},
|
|
boofar: 1,
|
|
};
|
|
let config_1 = {
|
|
foo: 'foo',
|
|
bar: { foo: 'foo', bar: { foo: { message: 'this' } } },
|
|
foobar: 'foobar',
|
|
};
|
|
let result = assignWithDepth(config_0, config_1, { depth: 1 });
|
|
expect(result).toEqual({
|
|
foo: 'foo',
|
|
bar: { foo: 'foo', bar: { foo: { message: 'this' } } },
|
|
foobar: 'foobar',
|
|
boofar: 1,
|
|
});
|
|
});
|
|
it('should handle depth:3 types (merge with no clobber because assignWithDepth::depth == 3)', function () {
|
|
let config_0 = {
|
|
foo: 'bar',
|
|
bar: { foo: 'bar', bar: { foo: { message: '', willbe: 'present' } } },
|
|
boofar: 1,
|
|
};
|
|
let config_1 = {
|
|
foo: 'foo',
|
|
bar: { foo: 'foo', bar: { foo: { message: 'this' } } },
|
|
foobar: 'foobar',
|
|
};
|
|
let result = assignWithDepth(config_0, config_1, { depth: 3 });
|
|
expect(result).toEqual({
|
|
foo: 'foo',
|
|
bar: { foo: 'foo', bar: { foo: { message: 'this', willbe: 'present' } } },
|
|
foobar: 'foobar',
|
|
boofar: 1,
|
|
});
|
|
});
|
|
});
|
|
describe('when memoizing', function () {
|
|
it('should return the same value', function () {
|
|
const fib = utils.memoize(function (n, canary) {
|
|
canary.flag = true;
|
|
if (n < 2) {
|
|
return 1;
|
|
} else {
|
|
//We'll console.log a loader every time we have to recurse
|
|
return fib(n - 2, canary) + fib(n - 1, canary);
|
|
}
|
|
});
|
|
let canary = { flag: false };
|
|
fib(10, canary);
|
|
expect(canary.flag).toBe(true);
|
|
canary = { flag: false };
|
|
fib(10, canary);
|
|
expect(canary.flag).toBe(false);
|
|
});
|
|
});
|
|
describe('when detecting chart type ', function () {
|
|
it('should handle a graph definition', function () {
|
|
const str = 'graph TB\nbfs1:queue';
|
|
const type = detectType(str);
|
|
expect(type).toBe('flowchart');
|
|
});
|
|
it('should handle an initialize definition', function () {
|
|
const str = `
|
|
%%{initialize: { 'logLevel': 0, 'theme': 'dark' }}%%
|
|
sequenceDiagram
|
|
Alice->Bob: hi`;
|
|
const type = detectType(str);
|
|
const init = utils.detectInit(str);
|
|
expect(type).toBe('sequence');
|
|
expect(init).toEqual({ logLevel: 0, theme: 'dark' });
|
|
});
|
|
it('should handle an init definition', function () {
|
|
const str = `
|
|
%%{init: { 'logLevel': 0, 'theme': 'dark' }}%%
|
|
sequenceDiagram
|
|
Alice->Bob: hi`;
|
|
const type = detectType(str);
|
|
const init = utils.detectInit(str);
|
|
expect(type).toBe('sequence');
|
|
expect(init).toEqual({ logLevel: 0, theme: 'dark' });
|
|
});
|
|
it('should handle an init definition with config converted to the proper diagram configuration', function () {
|
|
const str = `
|
|
%%{init: { 'logLevel': 0, 'theme': 'dark', 'config': {'wrap': true} } }%%
|
|
sequenceDiagram
|
|
Alice->Bob: hi`;
|
|
const type = detectType(str);
|
|
const init = utils.detectInit(str);
|
|
expect(type).toBe('sequence');
|
|
expect(init).toEqual({ logLevel: 0, theme: 'dark', sequence: { wrap: true } });
|
|
});
|
|
it('should handle a multiline init definition', function () {
|
|
const str = `
|
|
%%{
|
|
init: {
|
|
'logLevel': 0,
|
|
'theme': 'dark'
|
|
}
|
|
}%%
|
|
sequenceDiagram
|
|
Alice->Bob: hi`;
|
|
const type = detectType(str);
|
|
const init = utils.detectInit(str);
|
|
expect(type).toBe('sequence');
|
|
expect(init).toEqual({ logLevel: 0, theme: 'dark' });
|
|
});
|
|
it('should handle multiple init directives', function () {
|
|
const str = `
|
|
%%{ init: { 'logLevel': 0, 'theme': 'forest' } }%%
|
|
%%{
|
|
init: {
|
|
'theme': 'dark'
|
|
}
|
|
}%%
|
|
sequenceDiagram
|
|
Alice->Bob: hi`;
|
|
const type = detectType(str);
|
|
const init = utils.detectInit(str);
|
|
expect(type).toBe('sequence');
|
|
expect(init).toEqual({ logLevel: 0, theme: 'dark' });
|
|
});
|
|
it('should handle a graph definition with leading spaces', function () {
|
|
const str = ' graph TB\nbfs1:queue';
|
|
const type = detectType(str);
|
|
expect(type).toBe('flowchart');
|
|
});
|
|
|
|
it('should handle a graph definition with leading spaces and newline', function () {
|
|
const str = ' \n graph TB\nbfs1:queue';
|
|
const type = detectType(str);
|
|
expect(type).toBe('flowchart');
|
|
});
|
|
it('should handle a graph definition for gitGraph', function () {
|
|
const str = ' \n gitGraph TB:\nbfs1:queue';
|
|
const type = detectType(str);
|
|
expect(type).toBe('gitGraph');
|
|
});
|
|
});
|
|
describe('when finding substring in array ', function () {
|
|
it('should return the array index that contains the substring', function () {
|
|
const arr = ['stroke:val1', 'fill:val2'];
|
|
const result = utils.isSubstringInArray('fill', arr);
|
|
expect(result).toEqual(1);
|
|
});
|
|
it('should return -1 if the substring is not found in the array', function () {
|
|
const arr = ['stroke:val1', 'stroke-width:val2'];
|
|
const result = utils.isSubstringInArray('fill', arr);
|
|
expect(result).toEqual(-1);
|
|
});
|
|
});
|
|
describe('when formatting urls', function () {
|
|
it('should handle links', function () {
|
|
const url = 'https://mermaid-js.github.io/mermaid/#/';
|
|
|
|
let config = { securityLevel: 'loose' };
|
|
let result = utils.formatUrl(url, config);
|
|
expect(result).toEqual(url);
|
|
|
|
config.securityLevel = 'strict';
|
|
result = utils.formatUrl(url, config);
|
|
expect(result).toEqual(url);
|
|
});
|
|
it('should handle anchors', function () {
|
|
const url = '#interaction';
|
|
|
|
let config = { securityLevel: 'loose' };
|
|
let result = utils.formatUrl(url, config);
|
|
expect(result).toEqual(url);
|
|
|
|
config.securityLevel = 'strict';
|
|
result = utils.formatUrl(url, config);
|
|
expect(result).toEqual(url);
|
|
});
|
|
it('should handle mailto', function () {
|
|
const url = 'mailto:user@user.user';
|
|
|
|
let config = { securityLevel: 'loose' };
|
|
let result = utils.formatUrl(url, config);
|
|
expect(result).toEqual(url);
|
|
|
|
config.securityLevel = 'strict';
|
|
result = utils.formatUrl(url, config);
|
|
expect(result).toEqual(url);
|
|
});
|
|
it('should handle other protocols', function () {
|
|
const url = 'notes://do-your-thing/id';
|
|
|
|
let config = { securityLevel: 'loose' };
|
|
let result = utils.formatUrl(url, config);
|
|
expect(result).toEqual(url);
|
|
|
|
config.securityLevel = 'strict';
|
|
result = utils.formatUrl(url, config);
|
|
expect(result).toEqual(url);
|
|
});
|
|
it('should handle scripts', function () {
|
|
const url = 'javascript:alert("test")';
|
|
|
|
let config = { securityLevel: 'loose' };
|
|
let result = utils.formatUrl(url, config);
|
|
expect(result).toEqual(url);
|
|
|
|
config.securityLevel = 'strict';
|
|
result = utils.formatUrl(url, config);
|
|
expect(result).toEqual('about:blank');
|
|
});
|
|
});
|
|
describe('when calculating SVG size', function () {
|
|
it('should return width 100% when useMaxWidth is true', function () {
|
|
const attrs = utils.calculateSvgSizeAttrs(100, 200, true);
|
|
// expect(attrs.get('height')).toEqual(100);
|
|
expect(attrs.get('style')).toEqual('max-width: 200px;');
|
|
expect(attrs.get('width')).toEqual('100%');
|
|
});
|
|
it('should return absolute width when useMaxWidth is false', function () {
|
|
const attrs = utils.calculateSvgSizeAttrs(100, 200, false);
|
|
// expect(attrs.get('height')).toEqual(100);
|
|
expect(attrs.get('width')).toEqual(200);
|
|
});
|
|
});
|
|
|
|
describe('when initializing the id generator', function () {
|
|
it('should return a random number generator based on Date', function (done) {
|
|
const idGenerator = new utils.initIdGenerator(false);
|
|
expect(typeof idGenerator.next).toEqual('function');
|
|
const lastId = idGenerator.next();
|
|
setTimeout(() => {
|
|
expect(idGenerator.next() > lastId).toBe(true);
|
|
done();
|
|
}, 5);
|
|
});
|
|
|
|
it('should return a non random number generator', function () {
|
|
const idGenerator = new utils.initIdGenerator(true);
|
|
expect(typeof idGenerator.next).toEqual('function');
|
|
const start = 0;
|
|
const lastId = idGenerator.next();
|
|
expect(start).toEqual(lastId);
|
|
expect(idGenerator.next()).toEqual(lastId + 1);
|
|
});
|
|
|
|
it('should return a non random number generator based on seed', function () {
|
|
const idGenerator = new utils.initIdGenerator(true, 'thisIsASeed');
|
|
expect(typeof idGenerator.next).toEqual('function');
|
|
const start = 11;
|
|
const lastId = idGenerator.next();
|
|
expect(start).toEqual(lastId);
|
|
expect(idGenerator.next()).toEqual(lastId + 1);
|
|
});
|
|
});
|