2020-08-25 17:05:01 +02:00
|
|
|
import utils from './utils';
|
2015-10-17 10:39:20 +02:00
|
|
|
|
2021-11-18 19:17:00 +01:00
|
|
|
describe('when assignWithDepth: should merge objects within objects', function () {
|
|
|
|
it('should handle simple, depth:1 types (identity)', function () {
|
2020-07-01 12:18:48 +02:00
|
|
|
let config_0 = { foo: 'bar', bar: 0 };
|
|
|
|
let config_1 = { foo: 'bar', bar: 0 };
|
|
|
|
let result = utils.assignWithDepth(config_0, config_1);
|
|
|
|
expect(result).toEqual(config_1);
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle simple, depth:1 types (dst: undefined)', function () {
|
2020-07-01 12:18:48 +02:00
|
|
|
let config_0 = undefined;
|
|
|
|
let config_1 = { foo: 'bar', bar: 0 };
|
|
|
|
let result = utils.assignWithDepth(config_0, config_1);
|
|
|
|
expect(result).toEqual(config_1);
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle simple, depth:1 types (src: undefined)', function () {
|
2020-07-01 12:18:48 +02:00
|
|
|
let config_0 = { foo: 'bar', bar: 0 };
|
|
|
|
let config_1 = undefined;
|
|
|
|
let result = utils.assignWithDepth(config_0, config_1);
|
|
|
|
expect(result).toEqual(config_0);
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle simple, depth:1 types (merge)', function () {
|
2020-07-01 12:18:48 +02:00
|
|
|
let config_0 = { foo: 'bar', bar: 0 };
|
|
|
|
let config_1 = { foo: 'foo' };
|
|
|
|
let result = utils.assignWithDepth(config_0, config_1);
|
2021-11-18 19:17:00 +01:00
|
|
|
expect(result).toEqual({ foo: 'foo', bar: 0 });
|
2020-07-01 12:18:48 +02:00
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle depth:2 types (dst: orphan)', function () {
|
2020-07-01 12:18:48 +02:00
|
|
|
let config_0 = { foo: 'bar', bar: { foo: 'bar' } };
|
|
|
|
let config_1 = { foo: 'bar' };
|
|
|
|
let result = utils.assignWithDepth(config_0, config_1);
|
|
|
|
expect(result).toEqual(config_0);
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle depth:2 types (dst: object, src: simple type)', function () {
|
2020-07-01 12:18:48 +02:00
|
|
|
let config_0 = { foo: 'bar', bar: { foo: 'bar' } };
|
2021-11-18 19:17:00 +01:00
|
|
|
let config_1 = { foo: 'foo', bar: 'should NOT clobber' };
|
2020-07-01 12:18:48 +02:00
|
|
|
let result = utils.assignWithDepth(config_0, config_1);
|
2021-11-18 19:17:00 +01:00
|
|
|
expect(result).toEqual({ foo: 'foo', bar: { foo: 'bar' } });
|
2020-07-01 12:18:48 +02:00
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle depth:2 types (src: orphan)', function () {
|
2020-07-01 12:18:48 +02:00
|
|
|
let config_0 = { foo: 'bar' };
|
|
|
|
let config_1 = { foo: 'bar', bar: { foo: 'bar' } };
|
|
|
|
let result = utils.assignWithDepth(config_0, config_1);
|
|
|
|
expect(result).toEqual(config_1);
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle depth:2 types (merge)', function () {
|
2020-07-01 12:18:48 +02:00
|
|
|
let config_0 = { foo: 'bar', bar: { foo: 'bar' }, boofar: 1 };
|
|
|
|
let config_1 = { foo: 'foo', bar: { bar: 0 }, foobar: 'foobar' };
|
|
|
|
let result = utils.assignWithDepth(config_0, config_1);
|
2021-11-18 19:17:00 +01:00
|
|
|
expect(result).toEqual({
|
|
|
|
foo: 'foo',
|
|
|
|
bar: { foo: 'bar', bar: 0 },
|
|
|
|
foobar: 'foobar',
|
|
|
|
boofar: 1,
|
|
|
|
});
|
2020-07-01 12:18:48 +02:00
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
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',
|
|
|
|
};
|
2020-07-01 12:18:48 +02:00
|
|
|
let result = utils.assignWithDepth(config_0, config_1);
|
2021-11-18 19:17:00 +01:00
|
|
|
expect(result).toEqual({
|
|
|
|
foo: 'foo',
|
|
|
|
bar: { foo: 'foo', bar: { foo: { message: 'clobbered other foo' } } },
|
|
|
|
foobar: 'foobar',
|
|
|
|
boofar: 1,
|
|
|
|
});
|
2020-07-01 12:18:48 +02:00
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
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',
|
|
|
|
};
|
2020-07-01 12:18:48 +02:00
|
|
|
let result = utils.assignWithDepth(config_0, config_1, { depth: 1 });
|
2021-11-18 19:17:00 +01:00
|
|
|
expect(result).toEqual({
|
|
|
|
foo: 'foo',
|
|
|
|
bar: { foo: 'foo', bar: { foo: { message: 'this' } } },
|
|
|
|
foobar: 'foobar',
|
|
|
|
boofar: 1,
|
|
|
|
});
|
2020-07-01 12:18:48 +02:00
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
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',
|
|
|
|
};
|
2020-07-01 12:18:48 +02:00
|
|
|
let result = utils.assignWithDepth(config_0, config_1, { depth: 3 });
|
2021-11-18 19:17:00 +01:00
|
|
|
expect(result).toEqual({
|
|
|
|
foo: 'foo',
|
|
|
|
bar: { foo: 'foo', bar: { foo: { message: 'this', willbe: 'present' } } },
|
|
|
|
foobar: 'foobar',
|
|
|
|
boofar: 1,
|
|
|
|
});
|
2020-07-01 12:18:48 +02:00
|
|
|
});
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
describe('when memoizing', function () {
|
|
|
|
it('should return the same value', function () {
|
|
|
|
const fib = utils.memoize(function (n, canary) {
|
2020-07-01 12:18:48 +02:00
|
|
|
canary.flag = true;
|
2021-11-18 19:17:00 +01:00
|
|
|
if (n < 2) {
|
2020-07-01 12:18:48 +02:00
|
|
|
return 1;
|
2021-11-18 19:17:00 +01:00
|
|
|
} else {
|
2020-07-01 12:18:48 +02:00
|
|
|
//We'll console.log a loader every time we have to recurse
|
2021-11-18 19:17:00 +01:00
|
|
|
return fib(n - 2, canary) + fib(n - 1, canary);
|
2020-07-01 12:18:48 +02:00
|
|
|
}
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
let canary = { flag: false };
|
2020-07-01 12:18:48 +02:00
|
|
|
fib(10, canary);
|
|
|
|
expect(canary.flag).toBe(true);
|
2021-11-18 19:17:00 +01:00
|
|
|
canary = { flag: false };
|
2020-07-01 12:18:48 +02:00
|
|
|
fib(10, canary);
|
|
|
|
expect(canary.flag).toBe(false);
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
});
|
|
|
|
describe('when detecting chart type ', function () {
|
|
|
|
it('should handle a graph definition', function () {
|
2019-09-12 21:58:57 +02:00
|
|
|
const str = 'graph TB\nbfs1:queue';
|
|
|
|
const type = utils.detectType(str);
|
|
|
|
expect(type).toBe('flowchart');
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle an initialize definition', function () {
|
2020-06-11 21:31:59 +02:00
|
|
|
const str = `
|
|
|
|
%%{initialize: { 'logLevel': 0, 'theme': 'dark' }}%%
|
2020-06-14 17:34:39 +02:00
|
|
|
sequenceDiagram
|
|
|
|
Alice->Bob: hi`;
|
|
|
|
const type = utils.detectType(str);
|
|
|
|
const init = utils.detectInit(str);
|
|
|
|
expect(type).toBe('sequence');
|
2021-11-18 19:17:00 +01:00
|
|
|
expect(init).toEqual({ logLevel: 0, theme: 'dark' });
|
2020-06-08 20:48:03 +02:00
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle an init definition', function () {
|
2020-06-11 21:31:59 +02:00
|
|
|
const str = `
|
|
|
|
%%{init: { 'logLevel': 0, 'theme': 'dark' }}%%
|
2020-06-14 17:34:39 +02:00
|
|
|
sequenceDiagram
|
|
|
|
Alice->Bob: hi`;
|
|
|
|
const type = utils.detectType(str);
|
|
|
|
const init = utils.detectInit(str);
|
|
|
|
expect(type).toBe('sequence');
|
2021-11-18 19:17:00 +01:00
|
|
|
expect(init).toEqual({ logLevel: 0, theme: 'dark' });
|
2020-06-14 17:34:39 +02:00
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle an init definition with config converted to the proper diagram configuration', function () {
|
2020-07-01 12:18:48 +02:00
|
|
|
const str = `
|
2020-07-27 12:50:54 +02:00
|
|
|
%%{init: { 'logLevel': 0, 'theme': 'dark', 'config': {'wrap': true} } }%%
|
2020-07-01 12:18:48 +02:00
|
|
|
sequenceDiagram
|
|
|
|
Alice->Bob: hi`;
|
|
|
|
const type = utils.detectType(str);
|
|
|
|
const init = utils.detectInit(str);
|
|
|
|
expect(type).toBe('sequence');
|
2021-11-18 19:17:00 +01:00
|
|
|
expect(init).toEqual({ logLevel: 0, theme: 'dark', sequence: { wrap: true } });
|
2020-07-01 12:18:48 +02:00
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle a multiline init definition', function () {
|
2020-06-14 17:34:39 +02:00
|
|
|
const str = `
|
|
|
|
%%{
|
|
|
|
init: {
|
|
|
|
'logLevel': 0,
|
|
|
|
'theme': 'dark'
|
|
|
|
}
|
|
|
|
}%%
|
|
|
|
sequenceDiagram
|
|
|
|
Alice->Bob: hi`;
|
|
|
|
const type = utils.detectType(str);
|
|
|
|
const init = utils.detectInit(str);
|
|
|
|
expect(type).toBe('sequence');
|
2021-11-18 19:17:00 +01:00
|
|
|
expect(init).toEqual({ logLevel: 0, theme: 'dark' });
|
2020-06-14 17:34:39 +02:00
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle multiple init directives', function () {
|
2020-06-14 17:34:39 +02:00
|
|
|
const str = `
|
|
|
|
%%{ init: { 'logLevel': 0, 'theme': 'forest' } }%%
|
|
|
|
%%{
|
|
|
|
init: {
|
|
|
|
'theme': 'dark'
|
|
|
|
}
|
|
|
|
}%%
|
|
|
|
sequenceDiagram
|
|
|
|
Alice->Bob: hi`;
|
|
|
|
const type = utils.detectType(str);
|
|
|
|
const init = utils.detectInit(str);
|
|
|
|
expect(type).toBe('sequence');
|
2021-11-18 19:17:00 +01:00
|
|
|
expect(init).toEqual({ logLevel: 0, theme: 'dark' });
|
2020-06-08 20:48:03 +02:00
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle a graph definition with leading spaces', function () {
|
2019-09-12 21:58:57 +02:00
|
|
|
const str = ' graph TB\nbfs1:queue';
|
|
|
|
const type = utils.detectType(str);
|
|
|
|
expect(type).toBe('flowchart');
|
|
|
|
});
|
2015-10-17 10:39:20 +02:00
|
|
|
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle a graph definition with leading spaces and newline', function () {
|
2019-09-12 21:58:57 +02:00
|
|
|
const str = ' \n graph TB\nbfs1:queue';
|
|
|
|
const type = utils.detectType(str);
|
|
|
|
expect(type).toBe('flowchart');
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle a graph definition for gitGraph', function () {
|
2019-09-12 21:58:57 +02:00
|
|
|
const str = ' \n gitGraph TB:\nbfs1:queue';
|
|
|
|
const type = utils.detectType(str);
|
|
|
|
expect(type).toBe('git');
|
|
|
|
});
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
describe('when finding substring in array ', function () {
|
|
|
|
it('should return the array index that contains the substring', function () {
|
2019-09-12 21:58:57 +02:00
|
|
|
const arr = ['stroke:val1', 'fill:val2'];
|
|
|
|
const result = utils.isSubstringInArray('fill', arr);
|
|
|
|
expect(result).toEqual(1);
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should return -1 if the substring is not found in the array', function () {
|
2019-09-12 21:58:57 +02:00
|
|
|
const arr = ['stroke:val1', 'stroke-width:val2'];
|
|
|
|
const result = utils.isSubstringInArray('fill', arr);
|
|
|
|
expect(result).toEqual(-1);
|
|
|
|
});
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
describe('when formatting urls', function () {
|
|
|
|
it('should handle links', function () {
|
2020-01-26 16:56:42 +01:00
|
|
|
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);
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle anchors', function () {
|
2020-01-26 16:56:42 +01:00
|
|
|
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('about:blank');
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle mailto', function () {
|
2020-01-26 16:56:42 +01:00
|
|
|
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);
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle other protocols', function () {
|
2020-01-26 16:56:42 +01:00
|
|
|
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);
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
it('should handle scripts', function () {
|
2020-01-26 16:56:42 +01:00
|
|
|
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');
|
|
|
|
});
|
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
describe('when calculating SVG size', function () {
|
2020-08-23 15:45:23 +02:00
|
|
|
it('should return width 100% when useMaxWidth is true', function () {
|
|
|
|
const attrs = utils.calculateSvgSizeAttrs(100, 200, true);
|
2021-09-29 18:22:35 +02:00
|
|
|
expect(attrs.get('height')).toEqual(100);
|
2020-08-23 15:45:23 +02:00
|
|
|
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);
|
|
|
|
});
|
|
|
|
});
|
2020-11-23 23:34:47 +01:00
|
|
|
|
|
|
|
describe('when initializing the id generator', function () {
|
|
|
|
it('should return a random number generator based on Date', function (done) {
|
2021-11-18 19:17:00 +01:00
|
|
|
const idGenerator = new utils.initIdGeneratior(false);
|
|
|
|
expect(typeof idGenerator.next).toEqual('function');
|
|
|
|
const lastId = idGenerator.next();
|
2020-11-23 23:34:47 +01:00
|
|
|
setTimeout(() => {
|
2021-11-18 19:17:00 +01:00
|
|
|
expect(idGenerator.next() > lastId).toBe(true);
|
|
|
|
done();
|
|
|
|
}, 5);
|
2020-11-23 23:34:47 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should return a non random number generator', function () {
|
2021-11-18 19:17:00 +01:00
|
|
|
const idGenerator = new utils.initIdGeneratior(true);
|
|
|
|
expect(typeof idGenerator.next).toEqual('function');
|
|
|
|
const start = 0;
|
|
|
|
const lastId = idGenerator.next();
|
|
|
|
expect(start).toEqual(lastId);
|
|
|
|
expect(idGenerator.next()).toEqual(lastId + 1);
|
2020-11-23 23:34:47 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should return a non random number generator based on seed', function () {
|
2021-11-18 19:17:00 +01:00
|
|
|
const idGenerator = new utils.initIdGeneratior(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);
|
2020-11-23 23:34:47 +01:00
|
|
|
});
|
2021-11-18 19:17:00 +01:00
|
|
|
});
|