Compare commits
7 Commits
cafcc73366
...
master
Author | SHA1 | Date | |
---|---|---|---|
cef87ba4a5
|
|||
78556c6c98
|
|||
019647b04a | |||
fa8e0d25c6 | |||
af7bd4e00e | |||
9a2c2ce14c | |||
59542eb7b1 |
@ -1,5 +1,9 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 1.4.0
|
||||||
|
|
||||||
|
Allow specifying shapes for nodes
|
||||||
|
|
||||||
## 1.3.0
|
## 1.3.0
|
||||||
|
|
||||||
Stream:
|
Stream:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# @sapphirecode/graphviz-builder
|
# @sapphirecode/graphviz-builder
|
||||||
|
|
||||||
version: 1.3.x
|
version: 1.4.x
|
||||||
|
|
||||||
constructing graphviz files using an easy typescript interface
|
constructing graphviz files using an easy typescript interface
|
||||||
|
|
||||||
|
14
jasmine.json
Normal file
14
jasmine.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
{
|
||||||
|
"spec_dir": "test",
|
||||||
|
"spec_files": [
|
||||||
|
"spec/*.js",
|
||||||
|
"spec/*.ts"
|
||||||
|
],
|
||||||
|
"helpers": [
|
||||||
|
"helpers/*.js",
|
||||||
|
"helpers/*.ts"
|
||||||
|
],
|
||||||
|
"stopSpecOnExpectationFailure": false,
|
||||||
|
"random": false
|
||||||
|
}
|
@ -5,20 +5,13 @@
|
|||||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { GraphStyles, NodeStyles } from '../enums/Styles';
|
import { GraphStyles } from '../enums/Styles';
|
||||||
import { GraphLayouts } from '../enums/GraphLayouts';
|
import { GraphLayouts } from '../enums/GraphLayouts';
|
||||||
import { Element } from './Element';
|
import { Element } from './Element';
|
||||||
import { Edge } from './Edge';
|
import { Edge } from './Edge';
|
||||||
import { Node } from './Node';
|
import { Node } from './Node';
|
||||||
import { Color } from './Color';
|
import { Color } from './Color';
|
||||||
|
|
||||||
interface NodeOptions {
|
|
||||||
name: string;
|
|
||||||
label: string;
|
|
||||||
style: NodeStyles;
|
|
||||||
color: Color;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Graph extends Element {
|
export class Graph extends Element {
|
||||||
public children: Array<Graph> = [];
|
public children: Array<Graph> = [];
|
||||||
public nodes: Array<Node> = [];
|
public nodes: Array<Node> = [];
|
||||||
@ -83,7 +76,7 @@ export class Graph extends Element {
|
|||||||
.replace (/^\s+$/gmu, '');
|
.replace (/^\s+$/gmu, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
public add_node (constructor: ((n: Node) => void) | string): string {
|
public add_node (constructor: string | ((n: Node) => void)): string {
|
||||||
const node = new Node ('unnamed', this.full_name);
|
const node = new Node ('unnamed', this.full_name);
|
||||||
|
|
||||||
if (typeof constructor === 'string') {
|
if (typeof constructor === 'string') {
|
||||||
@ -96,7 +89,7 @@ export class Graph extends Element {
|
|||||||
return node.full_name;
|
return node.full_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public add_graph (constructor: ((g: Graph) => void) | string): string {
|
public add_graph (constructor: string | ((g: Graph) => void)): string {
|
||||||
const graph = new Graph ('unnamed', this.full_name);
|
const graph = new Graph ('unnamed', this.full_name);
|
||||||
|
|
||||||
graph.directional = this.directional;
|
graph.directional = this.directional;
|
||||||
|
@ -42,7 +42,7 @@ export class GraphStream extends Transform {
|
|||||||
return ' '.repeat (this._path.length);
|
return ' '.repeat (this._path.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private finish_node ():void {
|
private finish_node (): void {
|
||||||
if (
|
if (
|
||||||
[
|
[
|
||||||
'ce',
|
'ce',
|
||||||
@ -168,7 +168,7 @@ export class GraphStream extends Transform {
|
|||||||
// this.write ({ type: 'en', args: [] });
|
// this.write ({ type: 'en', args: [] });
|
||||||
}
|
}
|
||||||
|
|
||||||
public create_graph (name: string, type: 'u'|'d'|'s' = 's'): void {
|
public create_graph (name: string, type: 'd' | 's' | 'u' = 's'): void {
|
||||||
const instr_type = `c${type}g` as GraphStreamCommand;
|
const instr_type = `c${type}g` as GraphStreamCommand;
|
||||||
this.write ({ type: instr_type, args: [ validate_name (name) ] });
|
this.write ({ type: instr_type, args: [ validate_name (name) ] });
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { NodeStyles } from '../enums/Styles';
|
import { NodeStyles } from '../enums/Styles';
|
||||||
|
import { NodeShapes } from '../enums/Shapes';
|
||||||
import { Element } from './Element';
|
import { Element } from './Element';
|
||||||
import { Color } from './Color';
|
import { Color } from './Color';
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ export class Node extends Element {
|
|||||||
public table_contents?: Array<Array<string>>;
|
public table_contents?: Array<Array<string>>;
|
||||||
public style?: NodeStyles;
|
public style?: NodeStyles;
|
||||||
public color?: Color;
|
public color?: Color;
|
||||||
|
public shape?: NodeShapes;
|
||||||
|
|
||||||
public constructor (name: string, parent: string, label?: string) {
|
public constructor (name: string, parent: string, label?: string) {
|
||||||
super (name, parent);
|
super (name, parent);
|
||||||
@ -47,6 +49,8 @@ export class Node extends Element {
|
|||||||
}
|
}
|
||||||
if (this.style)
|
if (this.style)
|
||||||
attributes.push ({ name: 'style', value: this.style.toString () });
|
attributes.push ({ name: 'style', value: this.style.toString () });
|
||||||
|
if (this.shape)
|
||||||
|
attributes.push ({ name: 'shape', value: this.shape.toString () });
|
||||||
if (this.color)
|
if (this.color)
|
||||||
attributes.push ({ name: 'color', value: this.color.toString () });
|
attributes.push ({ name: 'color', value: this.color.toString () });
|
||||||
|
|
||||||
|
@ -6,11 +6,4 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export type GraphLayouts =
|
export type GraphLayouts =
|
||||||
'neato'
|
'circo' | 'dot' | 'fdp' | 'neato' | 'osage' | 'patchwork' | 'sfdp' | 'twopi'
|
||||||
| 'dot'
|
|
||||||
| 'circo'
|
|
||||||
| 'fdp'
|
|
||||||
| 'sfdp'
|
|
||||||
| 'osage'
|
|
||||||
| 'twopi'
|
|
||||||
| 'patchwork'
|
|
||||||
|
@ -8,19 +8,11 @@
|
|||||||
/* eslint-disable line-comment-position */
|
/* eslint-disable line-comment-position */
|
||||||
/* eslint-disable no-inline-comments */
|
/* eslint-disable no-inline-comments */
|
||||||
type GraphStreamCommand =
|
type GraphStreamCommand =
|
||||||
'cn'|
|
'at' | 'cdg' | 'ce' | 'cn' | 'csg' | 'cug' | 'eg'
|
||||||
'en'|
|
|
||||||
'cug'|
|
|
||||||
'cdg'|
|
|
||||||
'csg'|
|
|
||||||
'eg'|
|
|
||||||
'at'|
|
|
||||||
'ce'
|
|
||||||
|
|
||||||
function translate_command (cmd: GraphStreamCommand|''): string {
|
function translate_command (cmd: GraphStreamCommand|''): string {
|
||||||
const translations = {
|
const translations = {
|
||||||
cn: 'create node',
|
cn: 'create node',
|
||||||
en: 'end node',
|
|
||||||
cug: 'create unordered graph',
|
cug: 'create unordered graph',
|
||||||
cdg: 'create directional graph',
|
cdg: 'create directional graph',
|
||||||
csg: 'create subgraph',
|
csg: 'create subgraph',
|
||||||
|
14
lib/enums/Shapes.ts
Normal file
14
lib/enums/Shapes.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
type NodeShapes =
|
||||||
|
'' | 'assembly' | 'box' | 'box3d' | 'cds' | 'circle' | 'component'
|
||||||
|
| 'cylinder' | 'diamond' | 'doublecircle' | 'doubleoctagon' | 'egg'
|
||||||
|
| 'ellipse' | 'fivepoverhang' | 'folder' | 'hexagon' | 'house'
|
||||||
|
| 'insulator' | 'invhouse' | 'invtrapezium' | 'invtriangle' | 'larrow'
|
||||||
|
| 'lpromoter' | 'Mcircle' | 'Mdiamond' | 'Msquare' | 'none' | 'note'
|
||||||
|
| 'noverhang' | 'octagon' | 'oval' | 'parallelogram' | 'pentagon'
|
||||||
|
| 'plain' | 'plaintext' | 'point' | 'polygon' | 'primersite' | 'promoter'
|
||||||
|
| 'proteasesite' | 'proteinstab' | 'rarrow' | 'rect' | 'rectangle'
|
||||||
|
| 'restrictionsite' | 'ribosite' | 'rnastab' | 'rpromoter' | 'septagon'
|
||||||
|
| 'signature' | 'square' | 'star' | 'tab' | 'terminator' | 'threepoverhang'
|
||||||
|
| 'trapezium' | 'triangle' | 'tripleoctagon' | 'underline' | 'utr'
|
||||||
|
|
||||||
|
export { NodeShapes };
|
@ -6,34 +6,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
type EdgeStyles =
|
type EdgeStyles =
|
||||||
''
|
'' | 'bold' | 'dashed' | 'dotted' | 'solid'
|
||||||
|'solid'
|
|
||||||
|'dashed'
|
|
||||||
|'dotted'
|
|
||||||
|'bold'
|
|
||||||
|
|
||||||
|
|
||||||
type NodeStyles =
|
type NodeStyles =
|
||||||
''
|
'' | 'bold' | 'dashed' | 'diagonals' | 'dotted'
|
||||||
|'solid'
|
| 'filled' | 'invis' | 'rounded' | 'solid' | 'striped' | 'wedged'
|
||||||
|'dashed'
|
|
||||||
|'dotted'
|
|
||||||
|'bold'
|
|
||||||
|'rounded'
|
|
||||||
|'diagonals'
|
|
||||||
|'filled'
|
|
||||||
|'striped'
|
|
||||||
|'wedged'
|
|
||||||
|'invis'
|
|
||||||
|
|
||||||
|
|
||||||
type GraphStyles =
|
type GraphStyles =
|
||||||
'solid'
|
'bold' | 'dashed' | 'dotted' | 'filled' | 'rounded' | 'solid' | 'striped'
|
||||||
| 'dashed'
|
|
||||||
| 'dotted'
|
|
||||||
| 'bold'
|
|
||||||
| 'rounded'
|
|
||||||
| 'filled'
|
|
||||||
| 'striped'
|
|
||||||
|
|
||||||
export { EdgeStyles, NodeStyles, GraphStyles };
|
export { EdgeStyles, NodeStyles, GraphStyles };
|
||||||
|
11
package.json
11
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@sapphirecode/graphviz-builder",
|
"name": "@sapphirecode/graphviz-builder",
|
||||||
"main": "dist/lib/index.js",
|
"main": "dist/lib/index.js",
|
||||||
"version": "1.3.3",
|
"version": "1.4.0",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Timo Hocker",
|
"name": "Timo Hocker",
|
||||||
"email": "timo@scode.ovh"
|
"email": "timo@scode.ovh"
|
||||||
@ -14,16 +14,19 @@
|
|||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ava/typescript": "^1.1.1",
|
|
||||||
"@sapphirecode/eslint-config-ts": "^1.1.4",
|
"@sapphirecode/eslint-config-ts": "^1.1.4",
|
||||||
"ava": "^3.8.2",
|
"@types/jasmine": "^3.5.14",
|
||||||
|
"@types/node": "^14.11.2",
|
||||||
"eslint": "^7.0.0",
|
"eslint": "^7.0.0",
|
||||||
|
"jasmine": "^3.6.1",
|
||||||
|
"jasmine-ts": "^0.3.0",
|
||||||
"nyc": "^15.0.1",
|
"nyc": "^15.0.1",
|
||||||
|
"ts-node": "^9.0.0",
|
||||||
"typescript": "^4.0.2"
|
"typescript": "^4.0.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "eslint . --ext .js,.jsx,.ts,.tsx,.vue,.mjs",
|
"lint": "eslint . --ext .js,.jsx,.ts,.tsx,.vue,.mjs",
|
||||||
"test": "tsc && nyc ava",
|
"test": "nyc jasmine-ts --config=\"jasmine.json\"",
|
||||||
"compile": "tsc"
|
"compile": "tsc"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
|
||||||
* This file is part of graphviz-builder which is released under MIT.
|
|
||||||
* See file 'LICENSE' for full license details.
|
|
||||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
import test from 'ava';
|
|
||||||
import { Color } from '../lib';
|
|
||||||
|
|
||||||
test ('serialize', (t) => {
|
|
||||||
const wh = Color.white;
|
|
||||||
const tr = Color.transparent;
|
|
||||||
|
|
||||||
t.is (wh.toString (), '#ffffff');
|
|
||||||
t.is (tr.toString (), '#00000000');
|
|
||||||
});
|
|
29
test/Edge.ts
29
test/Edge.ts
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
|
||||||
* This file is part of graphviz-builder which is released under MIT.
|
|
||||||
* See file 'LICENSE' for full license details.
|
|
||||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
import test from 'ava';
|
|
||||||
import { Edge, Color } from '../lib';
|
|
||||||
|
|
||||||
test ('serialize', (t) => {
|
|
||||||
const e = new Edge ('foo', 'bar', false);
|
|
||||||
|
|
||||||
e.color = Color.white;
|
|
||||||
e.style = 'dashed';
|
|
||||||
const serialized = e.toString ();
|
|
||||||
|
|
||||||
t.is (serialized, 'foo -- bar [style="dashed",color="#ffffff"]');
|
|
||||||
});
|
|
||||||
|
|
||||||
test ('serialize directional', (t) => {
|
|
||||||
const e = new Edge ('foo', 'bar', true);
|
|
||||||
|
|
||||||
e.color = Color.white;
|
|
||||||
e.style = 'dashed';
|
|
||||||
const serialized = e.toString ();
|
|
||||||
|
|
||||||
t.is (serialized, 'foo -> bar [style="dashed",color="#ffffff"]');
|
|
||||||
});
|
|
128
test/Graph.ts
128
test/Graph.ts
@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
|
||||||
* This file is part of graphviz-builder which is released under MIT.
|
|
||||||
* See file 'LICENSE' for full license details.
|
|
||||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
import test from 'ava';
|
|
||||||
import { Graph, Color } from '../lib';
|
|
||||||
|
|
||||||
const result = `digraph foo {
|
|
||||||
subgraph cluster_foo_baz {
|
|
||||||
color = #ff0000
|
|
||||||
style = bold
|
|
||||||
|
|
||||||
subgraph cluster_foo_baz_nested {
|
|
||||||
color = #808080
|
|
||||||
style = dotted
|
|
||||||
|
|
||||||
subgraph cluster_foo_baz_nested_unnamed {
|
|
||||||
color = #808080
|
|
||||||
style = dotted
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foo_baz_asd [label="asd"]
|
|
||||||
foo_baz_test [style="bold", color="#808080"]
|
|
||||||
}
|
|
||||||
|
|
||||||
foo_baz [label="baz"]
|
|
||||||
foo_foo [label="foo"]
|
|
||||||
|
|
||||||
foo_foo -> foo_baz
|
|
||||||
}`;
|
|
||||||
|
|
||||||
const non_directional = `graph foo {
|
|
||||||
subgraph cluster_foo_bar {
|
|
||||||
foo_bar_baz [label="baz"]
|
|
||||||
foo_bar_asd [label="asd"]
|
|
||||||
|
|
||||||
foo_bar_baz -- foo_bar_asd
|
|
||||||
}
|
|
||||||
|
|
||||||
foo_foo [label="foo"]
|
|
||||||
|
|
||||||
foo_bar_baz -- foo_foo
|
|
||||||
}`;
|
|
||||||
|
|
||||||
const attributes = `digraph attr {
|
|
||||||
color = #000000
|
|
||||||
style = bold
|
|
||||||
overlap = false
|
|
||||||
splines = true
|
|
||||||
layout = neato
|
|
||||||
}`;
|
|
||||||
|
|
||||||
test ('serialize', (t) => {
|
|
||||||
const g = new Graph ('foo');
|
|
||||||
|
|
||||||
t.is (g.full_name, 'foo');
|
|
||||||
g.add_graph ((graph) => {
|
|
||||||
graph.name = 'baz';
|
|
||||||
graph.add_node ('asd');
|
|
||||||
graph.add_node ((n) => {
|
|
||||||
n.name = 'test';
|
|
||||||
n.style = 'bold';
|
|
||||||
n.color = Color.gray;
|
|
||||||
});
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-shadow
|
|
||||||
graph.add_graph ((g) => {
|
|
||||||
g.style = 'dotted';
|
|
||||||
g.color = Color.gray;
|
|
||||||
g.name = 'nested';
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-shadow, max-nested-callbacks
|
|
||||||
g.add_graph ((g) => {
|
|
||||||
g.style = 'dotted';
|
|
||||||
g.color = Color.gray;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
graph.style = 'bold';
|
|
||||||
graph.color = Color.red;
|
|
||||||
});
|
|
||||||
|
|
||||||
const baz = g.add_node ('baz');
|
|
||||||
const foo = g.add_node ('foo');
|
|
||||||
|
|
||||||
g.add_edge (foo, baz);
|
|
||||||
|
|
||||||
const serialized = g.toString ();
|
|
||||||
|
|
||||||
t.is (serialized, result);
|
|
||||||
});
|
|
||||||
|
|
||||||
test ('non directional', (t) => {
|
|
||||||
const g = new Graph ('foo');
|
|
||||||
|
|
||||||
g.directional = false;
|
|
||||||
|
|
||||||
let n = '';
|
|
||||||
|
|
||||||
g.add_graph ((sub) => {
|
|
||||||
sub.name = 'bar';
|
|
||||||
n = sub.add_node ('baz');
|
|
||||||
const n2 = sub.add_node ('asd');
|
|
||||||
|
|
||||||
sub.add_edge (n, n2);
|
|
||||||
});
|
|
||||||
|
|
||||||
const f = g.add_node ('foo');
|
|
||||||
|
|
||||||
g.add_edge (n, f);
|
|
||||||
|
|
||||||
t.is (g.toString (), non_directional);
|
|
||||||
});
|
|
||||||
|
|
||||||
test ('attributes', (t) => {
|
|
||||||
const g = new Graph ('attr');
|
|
||||||
|
|
||||||
g.layout = 'neato';
|
|
||||||
g.overlap = false;
|
|
||||||
g.splines = true;
|
|
||||||
g.color = Color.black;
|
|
||||||
g.style = 'bold';
|
|
||||||
|
|
||||||
t.is (g.toString (), attributes);
|
|
||||||
});
|
|
77
test/Node.ts
77
test/Node.ts
@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
|
||||||
* This file is part of graphviz-builder which is released under MIT.
|
|
||||||
* See file 'LICENSE' for full license details.
|
|
||||||
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
import test from 'ava';
|
|
||||||
import { Node, Color } from '../lib';
|
|
||||||
|
|
||||||
const serialized_simple
|
|
||||||
= 'bar_foo [label="baz", style="dashed", color="#00ff00"]';
|
|
||||||
const serialized_table = `bar_foo [label=<<table>
|
|
||||||
<tr><td>foo</td><td>bar</td><td>baz</td></tr>
|
|
||||||
<tr><td>bar</td><td>baz</td><td>foo</td></tr>
|
|
||||||
<tr><td>baz</td><td>foo</td><td>bar</td></tr>
|
|
||||||
</table>>, style="invis", color="#00ff00"]`;
|
|
||||||
|
|
||||||
test ('serialize simple', (t) => {
|
|
||||||
const g = new Node ('foo', 'bar', 'baz');
|
|
||||||
|
|
||||||
g.color = Color.green;
|
|
||||||
g.style = 'dashed';
|
|
||||||
|
|
||||||
const serialized = g.toString ();
|
|
||||||
|
|
||||||
t.is (g.full_name, 'bar_foo');
|
|
||||||
t.is (serialized, serialized_simple);
|
|
||||||
});
|
|
||||||
|
|
||||||
test ('serialize table', (t) => {
|
|
||||||
const g = new Node ('foo', 'bar', 'baz');
|
|
||||||
|
|
||||||
g.color = Color.green;
|
|
||||||
g.style = 'invis';
|
|
||||||
|
|
||||||
g.table_contents = [
|
|
||||||
[
|
|
||||||
'foo',
|
|
||||||
'bar',
|
|
||||||
'baz'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'bar',
|
|
||||||
'baz',
|
|
||||||
'foo'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'baz',
|
|
||||||
'foo',
|
|
||||||
'bar'
|
|
||||||
]
|
|
||||||
];
|
|
||||||
g.is_table = true;
|
|
||||||
|
|
||||||
const serialized = g.toString ();
|
|
||||||
|
|
||||||
t.is (g.full_name, 'bar_foo');
|
|
||||||
t.is (serialized, serialized_table);
|
|
||||||
});
|
|
||||||
|
|
||||||
test ('adhere to naming convention', (t) => {
|
|
||||||
const n = new Node ('invalid.name', 'parent');
|
|
||||||
t.is (n.name, 'invalidname');
|
|
||||||
});
|
|
||||||
|
|
||||||
test ('throw on invalid name', (t) => {
|
|
||||||
t.throws (() => {
|
|
||||||
const n = new Node ('564#+-.,/@', 'parent');
|
|
||||||
return n.toString ();
|
|
||||||
}, { message: 'invalid node name 564#+-.,/@' });
|
|
||||||
});
|
|
||||||
|
|
||||||
test ('leave numbers after the first letter', (t) => {
|
|
||||||
const n = new Node ('i123nvalid.name', 'parent');
|
|
||||||
t.is (n.name, 'i123nvalidname');
|
|
||||||
});
|
|
@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Sapphirecode - All Rights Reserved
|
|
||||||
* This file is part of graphviz-builder which is released under MIT.
|
|
||||||
* See file 'LICENSE' for full license details.
|
|
||||||
* Created by Timo Hocker <timo@scode.ovh>, June 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
import test from 'ava';
|
|
||||||
import { GraphStream, Color } from '../lib/index';
|
|
||||||
|
|
||||||
const simple = `graph foo {
|
|
||||||
}
|
|
||||||
|
|
||||||
`;
|
|
||||||
|
|
||||||
const complex = `digraph foo {
|
|
||||||
subgraph cluster_foo_baz {
|
|
||||||
color = #ff0000
|
|
||||||
style = bold
|
|
||||||
|
|
||||||
subgraph cluster_foo_baz_nested {
|
|
||||||
color = #808080
|
|
||||||
style = dotted
|
|
||||||
|
|
||||||
subgraph cluster_foo_baz_nested_unnamed {
|
|
||||||
color = #808080
|
|
||||||
style = dotted
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
foo_baz_asd [label = "asd"]
|
|
||||||
foo_baz_test [style = "bold", color = "#808080"]
|
|
||||||
}
|
|
||||||
|
|
||||||
foo_baz [label = "baz"]
|
|
||||||
foo_foo [label = "foo"]
|
|
||||||
foo_foo -> foo_baz
|
|
||||||
foo_foo -> foo_baz_asd [label = "edge attr"]
|
|
||||||
}
|
|
||||||
|
|
||||||
`;
|
|
||||||
|
|
||||||
test ('stream graph', (t) => new Promise ((resolve) => {
|
|
||||||
let output = '';
|
|
||||||
const stream = (new GraphStream);
|
|
||||||
stream.on ('data', (data) => {
|
|
||||||
output += data;
|
|
||||||
});
|
|
||||||
stream.on ('end', () => {
|
|
||||||
t.is (output, simple);
|
|
||||||
resolve ();
|
|
||||||
});
|
|
||||||
stream.create_graph ('foo', 'u');
|
|
||||||
stream.end_graph ();
|
|
||||||
stream.end ();
|
|
||||||
}));
|
|
||||||
|
|
||||||
// eslint-disable-next-line max-statements
|
|
||||||
test ('complex stream graph', (t) => new Promise ((resolve) => {
|
|
||||||
let output = '';
|
|
||||||
const stream = (new GraphStream);
|
|
||||||
stream.on ('data', (data) => {
|
|
||||||
output += data;
|
|
||||||
});
|
|
||||||
stream.on ('end', () => {
|
|
||||||
t.is (output, complex);
|
|
||||||
resolve ();
|
|
||||||
});
|
|
||||||
stream.create_graph ('foo', 'd');
|
|
||||||
stream.create_graph ('baz');
|
|
||||||
stream.attributes ({ color: Color.red, style: 'bold' });
|
|
||||||
stream.create_graph ('nested');
|
|
||||||
stream.attributes ({ color: Color.gray, style: 'dotted' });
|
|
||||||
stream.create_graph ('unnamed');
|
|
||||||
stream.attributes ({ color: Color.gray, style: 'dotted' });
|
|
||||||
stream.end_graph ();
|
|
||||||
stream.end_graph ();
|
|
||||||
const asd = stream.create_node ('asd');
|
|
||||||
stream.attributes ({ label: 'asd' });
|
|
||||||
stream.end_node ();
|
|
||||||
stream.create_node ('test');
|
|
||||||
stream.attributes ({ style: 'bold', color: Color.gray });
|
|
||||||
stream.end_graph ();
|
|
||||||
const baz = stream.create_node ('baz');
|
|
||||||
stream.attributes ({ label: 'baz' });
|
|
||||||
const foo = stream.create_node ('foo');
|
|
||||||
stream.attributes ({ label: 'foo' });
|
|
||||||
stream.create_edge (foo, baz);
|
|
||||||
stream.create_edge (foo, asd);
|
|
||||||
stream.attributes ({ label: 'edge attr' });
|
|
||||||
stream.end_graph ();
|
|
||||||
stream.end ();
|
|
||||||
}));
|
|
20
test/spec/Color.ts
Normal file
20
test/spec/Color.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Sapphirecode - All Rights Reserved
|
||||||
|
* This file is part of graphviz-builder which is released under MIT.
|
||||||
|
* See file 'LICENSE' for full license details.
|
||||||
|
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Color } from '../../lib';
|
||||||
|
|
||||||
|
describe ('color', () => {
|
||||||
|
it ('should serialize', () => {
|
||||||
|
const wh = Color.white;
|
||||||
|
const tr = Color.transparent;
|
||||||
|
|
||||||
|
expect (wh.toString ())
|
||||||
|
.toEqual ('#ffffff');
|
||||||
|
expect (tr.toString ())
|
||||||
|
.toEqual ('#00000000');
|
||||||
|
});
|
||||||
|
});
|
32
test/spec/Edge.ts
Normal file
32
test/spec/Edge.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Sapphirecode - All Rights Reserved
|
||||||
|
* This file is part of graphviz-builder which is released under MIT.
|
||||||
|
* See file 'LICENSE' for full license details.
|
||||||
|
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Edge, Color } from '../../lib';
|
||||||
|
|
||||||
|
describe ('edge', () => {
|
||||||
|
it ('should serialize', () => {
|
||||||
|
const e = new Edge ('foo', 'bar', false);
|
||||||
|
|
||||||
|
e.color = Color.white;
|
||||||
|
e.style = 'dashed';
|
||||||
|
const serialized = e.toString ();
|
||||||
|
|
||||||
|
expect (serialized)
|
||||||
|
.toEqual ('foo -- bar [style="dashed",color="#ffffff"]');
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('should serialize directional', () => {
|
||||||
|
const e = new Edge ('foo', 'bar', true);
|
||||||
|
|
||||||
|
e.color = Color.white;
|
||||||
|
e.style = 'dashed';
|
||||||
|
const serialized = e.toString ();
|
||||||
|
|
||||||
|
expect (serialized)
|
||||||
|
.toEqual ('foo -> bar [style="dashed",color="#ffffff"]');
|
||||||
|
});
|
||||||
|
});
|
135
test/spec/Graph.ts
Normal file
135
test/spec/Graph.ts
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Sapphirecode - All Rights Reserved
|
||||||
|
* This file is part of graphviz-builder which is released under MIT.
|
||||||
|
* See file 'LICENSE' for full license details.
|
||||||
|
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable max-nested-callbacks */
|
||||||
|
import { Graph, Color } from '../../lib';
|
||||||
|
|
||||||
|
// eslint-disable-next-line max-lines-per-function
|
||||||
|
describe ('graph', () => {
|
||||||
|
const result = `digraph foo {
|
||||||
|
subgraph cluster_foo_baz {
|
||||||
|
color = #ff0000
|
||||||
|
style = bold
|
||||||
|
|
||||||
|
subgraph cluster_foo_baz_nested {
|
||||||
|
color = #808080
|
||||||
|
style = dotted
|
||||||
|
|
||||||
|
subgraph cluster_foo_baz_nested_unnamed {
|
||||||
|
color = #808080
|
||||||
|
style = dotted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foo_baz_asd [label="asd"]
|
||||||
|
foo_baz_test [style="bold", color="#808080"]
|
||||||
|
}
|
||||||
|
|
||||||
|
foo_baz [label="baz"]
|
||||||
|
foo_foo [label="foo"]
|
||||||
|
|
||||||
|
foo_foo -> foo_baz
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const non_directional = `graph foo {
|
||||||
|
subgraph cluster_foo_bar {
|
||||||
|
foo_bar_baz [label="baz"]
|
||||||
|
foo_bar_asd [label="asd"]
|
||||||
|
|
||||||
|
foo_bar_baz -- foo_bar_asd
|
||||||
|
}
|
||||||
|
|
||||||
|
foo_foo [label="foo"]
|
||||||
|
|
||||||
|
foo_bar_baz -- foo_foo
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const attributes = `digraph attr {
|
||||||
|
color = #000000
|
||||||
|
style = bold
|
||||||
|
overlap = false
|
||||||
|
splines = true
|
||||||
|
layout = neato
|
||||||
|
}`;
|
||||||
|
|
||||||
|
it ('should serialize', () => {
|
||||||
|
const g = new Graph ('foo');
|
||||||
|
|
||||||
|
expect (g.full_name)
|
||||||
|
.toEqual ('foo');
|
||||||
|
g.add_graph ((graph) => {
|
||||||
|
graph.name = 'baz';
|
||||||
|
graph.add_node ('asd');
|
||||||
|
graph.add_node ((n) => {
|
||||||
|
n.name = 'test';
|
||||||
|
n.style = 'bold';
|
||||||
|
n.color = Color.gray;
|
||||||
|
});
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-shadow
|
||||||
|
graph.add_graph ((g) => {
|
||||||
|
g.style = 'dotted';
|
||||||
|
g.color = Color.gray;
|
||||||
|
g.name = 'nested';
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-shadow
|
||||||
|
g.add_graph ((g) => {
|
||||||
|
g.style = 'dotted';
|
||||||
|
g.color = Color.gray;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
graph.style = 'bold';
|
||||||
|
graph.color = Color.red;
|
||||||
|
});
|
||||||
|
|
||||||
|
const baz = g.add_node ('baz');
|
||||||
|
const foo = g.add_node ('foo');
|
||||||
|
|
||||||
|
g.add_edge (foo, baz);
|
||||||
|
|
||||||
|
const serialized = g.toString ();
|
||||||
|
|
||||||
|
expect (serialized)
|
||||||
|
.toEqual (result);
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('non directional', () => {
|
||||||
|
const g = new Graph ('foo');
|
||||||
|
|
||||||
|
g.directional = false;
|
||||||
|
|
||||||
|
let n = '';
|
||||||
|
|
||||||
|
g.add_graph ((sub) => {
|
||||||
|
sub.name = 'bar';
|
||||||
|
n = sub.add_node ('baz');
|
||||||
|
const n2 = sub.add_node ('asd');
|
||||||
|
|
||||||
|
sub.add_edge (n, n2);
|
||||||
|
});
|
||||||
|
|
||||||
|
const f = g.add_node ('foo');
|
||||||
|
|
||||||
|
g.add_edge (n, f);
|
||||||
|
|
||||||
|
expect (g.toString ())
|
||||||
|
.toEqual (non_directional);
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('attributes', () => {
|
||||||
|
const g = new Graph ('attr');
|
||||||
|
|
||||||
|
g.layout = 'neato';
|
||||||
|
g.overlap = false;
|
||||||
|
g.splines = true;
|
||||||
|
g.color = Color.black;
|
||||||
|
g.style = 'bold';
|
||||||
|
|
||||||
|
expect (g.toString ())
|
||||||
|
.toEqual (attributes);
|
||||||
|
});
|
||||||
|
});
|
87
test/spec/Node.ts
Normal file
87
test/spec/Node.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Sapphirecode - All Rights Reserved
|
||||||
|
* This file is part of graphviz-builder which is released under MIT.
|
||||||
|
* See file 'LICENSE' for full license details.
|
||||||
|
* Created by Timo Hocker <timo@scode.ovh>, May 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Node, Color } from '../../lib';
|
||||||
|
|
||||||
|
const serialized_simple
|
||||||
|
= 'bar_foo [label="baz", style="dashed",'
|
||||||
|
+ ' shape="tripleoctagon", color="#00ff00"]';
|
||||||
|
const serialized_table = `bar_foo [label=<<table>
|
||||||
|
<tr><td>foo</td><td>bar</td><td>baz</td></tr>
|
||||||
|
<tr><td>bar</td><td>baz</td><td>foo</td></tr>
|
||||||
|
<tr><td>baz</td><td>foo</td><td>bar</td></tr>
|
||||||
|
</table>>, style="invis", color="#00ff00"]`;
|
||||||
|
// eslint-disable-next-line max-lines-per-function
|
||||||
|
describe ('node', () => {
|
||||||
|
it ('should serialize simple', () => {
|
||||||
|
const g = new Node ('foo', 'bar', 'baz');
|
||||||
|
|
||||||
|
g.color = Color.green;
|
||||||
|
g.style = 'dashed';
|
||||||
|
g.shape = 'tripleoctagon';
|
||||||
|
|
||||||
|
const serialized = g.toString ();
|
||||||
|
|
||||||
|
expect (g.full_name)
|
||||||
|
.toEqual ('bar_foo');
|
||||||
|
expect (serialized)
|
||||||
|
.toEqual (serialized_simple);
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('should serialize table', () => {
|
||||||
|
const g = new Node ('foo', 'bar', 'baz');
|
||||||
|
|
||||||
|
g.color = Color.green;
|
||||||
|
g.style = 'invis';
|
||||||
|
|
||||||
|
g.table_contents = [
|
||||||
|
[
|
||||||
|
'foo',
|
||||||
|
'bar',
|
||||||
|
'baz'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'bar',
|
||||||
|
'baz',
|
||||||
|
'foo'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'baz',
|
||||||
|
'foo',
|
||||||
|
'bar'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
g.is_table = true;
|
||||||
|
|
||||||
|
const serialized = g.toString ();
|
||||||
|
|
||||||
|
expect (g.full_name)
|
||||||
|
.toEqual ('bar_foo');
|
||||||
|
expect (serialized)
|
||||||
|
.toEqual (serialized_table);
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('should adhere to naming convention', () => {
|
||||||
|
const n = new Node ('invalid.name', 'parent');
|
||||||
|
expect (n.name)
|
||||||
|
.toEqual ('invalidname');
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('should throw on invalid name', () => {
|
||||||
|
expect (() => {
|
||||||
|
const n = new Node ('564#+-.,/@', 'parent');
|
||||||
|
return n.toString ();
|
||||||
|
})
|
||||||
|
.toThrowError ('invalid node name 564#+-.,/@');
|
||||||
|
});
|
||||||
|
|
||||||
|
it ('should leave numbers after the first letter', () => {
|
||||||
|
const n = new Node ('i123nvalid.name', 'parent');
|
||||||
|
expect (n.name)
|
||||||
|
.toEqual ('i123nvalidname');
|
||||||
|
});
|
||||||
|
});
|
217
test/spec/Stream.ts
Normal file
217
test/spec/Stream.ts
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Sapphirecode - All Rights Reserved
|
||||||
|
* This file is part of graphviz-builder which is released under MIT.
|
||||||
|
* See file 'LICENSE' for full license details.
|
||||||
|
* Created by Timo Hocker <timo@scode.ovh>, June 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { GraphStream, Color } from '../../lib/index';
|
||||||
|
|
||||||
|
const simple = `graph foo {
|
||||||
|
}
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
const complex = `digraph foo {
|
||||||
|
subgraph cluster_foo_baz {
|
||||||
|
color = #ff0000
|
||||||
|
style = bold
|
||||||
|
|
||||||
|
subgraph cluster_foo_baz_nested {
|
||||||
|
color = #808080
|
||||||
|
style = dotted
|
||||||
|
|
||||||
|
subgraph cluster_foo_baz_nested_unnamed {
|
||||||
|
color = #808080
|
||||||
|
style = dotted
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
foo_baz_asd [label = "asd"]
|
||||||
|
foo_baz_test [style = "bold", color = "#808080"]
|
||||||
|
}
|
||||||
|
|
||||||
|
foo_baz [label = "baz"]
|
||||||
|
foo_foo [label = "foo"]
|
||||||
|
foo_foo -> foo_baz
|
||||||
|
foo_foo -> foo_baz_asd [label = "edge attr"]
|
||||||
|
}
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
// eslint-disable-next-line max-lines-per-function
|
||||||
|
describe ('stream', () => {
|
||||||
|
it ('stream graph', () => new Promise<void> ((resolve) => {
|
||||||
|
let output = '';
|
||||||
|
const stream = (new GraphStream);
|
||||||
|
stream.on ('data', (data) => {
|
||||||
|
output += data;
|
||||||
|
});
|
||||||
|
stream.on ('end', () => {
|
||||||
|
expect (output)
|
||||||
|
.toEqual (simple);
|
||||||
|
resolve ();
|
||||||
|
});
|
||||||
|
stream.create_graph ('foo', 'u');
|
||||||
|
stream.end_graph ();
|
||||||
|
stream.end ();
|
||||||
|
}));
|
||||||
|
|
||||||
|
// eslint-disable-next-line max-statements
|
||||||
|
it ('complex stream graph', () => new Promise<void> ((resolve) => {
|
||||||
|
let output = '';
|
||||||
|
const stream = (new GraphStream);
|
||||||
|
stream.on ('data', (data) => {
|
||||||
|
output += data;
|
||||||
|
});
|
||||||
|
stream.on ('end', () => {
|
||||||
|
expect (output)
|
||||||
|
.toEqual (complex);
|
||||||
|
resolve ();
|
||||||
|
});
|
||||||
|
stream.create_graph ('foo', 'd');
|
||||||
|
stream.create_graph ('baz');
|
||||||
|
stream.attributes ({ color: Color.red, style: 'bold' });
|
||||||
|
stream.create_graph ('nested');
|
||||||
|
stream.attributes ({ color: Color.gray, style: 'dotted' });
|
||||||
|
stream.create_graph ('unnamed');
|
||||||
|
stream.attributes ({ color: Color.gray, style: 'dotted' });
|
||||||
|
stream.end_graph ();
|
||||||
|
stream.end_graph ();
|
||||||
|
const asd = stream.create_node ('asd');
|
||||||
|
stream.attributes ({ label: 'asd' });
|
||||||
|
stream.end_node ();
|
||||||
|
stream.create_node ('test');
|
||||||
|
stream.attributes ({ style: 'bold', color: Color.gray });
|
||||||
|
stream.end_graph ();
|
||||||
|
const baz = stream.create_node ('baz');
|
||||||
|
stream.attributes ({ label: 'baz' });
|
||||||
|
const foo = stream.create_node ('foo');
|
||||||
|
stream.attributes ({ label: 'foo' });
|
||||||
|
stream.create_edge (foo, baz);
|
||||||
|
stream.create_edge (foo, asd);
|
||||||
|
stream.attributes ({ label: 'edge attr' });
|
||||||
|
stream.end_graph ();
|
||||||
|
stream.end ();
|
||||||
|
}));
|
||||||
|
|
||||||
|
// eslint-disable-next-line max-lines-per-function
|
||||||
|
it ('should reject invalid command sequences', () => {
|
||||||
|
/**
|
||||||
|
* command valid invalid
|
||||||
|
* [s] cug, cdg eg, cn, csg, ce, at
|
||||||
|
* cn eg, cn, csg, ce, at cug, cdg
|
||||||
|
* cug eg, cn, csg, ce, at cug, cdg
|
||||||
|
* cdg eg, cn, csg, ce, at cug, cdg
|
||||||
|
* csg eg, cn, csg, ce, at cug, cdg
|
||||||
|
* eg eg, cn, csg, ce cug, cdg, at
|
||||||
|
* at eg, cn, csg, ce cug, cdg, at
|
||||||
|
* ce eg, cn, csg, ce, at cug, cdg
|
||||||
|
*/
|
||||||
|
|
||||||
|
const cn = (g: GraphStream) => {
|
||||||
|
g.create_node ('foo');
|
||||||
|
};
|
||||||
|
const cug = (g: GraphStream) => {
|
||||||
|
g.create_graph ('foo', 'u');
|
||||||
|
};
|
||||||
|
const cdg = (g: GraphStream) => {
|
||||||
|
g.create_graph ('foo', 'd');
|
||||||
|
};
|
||||||
|
const csg = (g: GraphStream) => {
|
||||||
|
g.create_graph ('foo', 's');
|
||||||
|
};
|
||||||
|
const eg = (g: GraphStream) => {
|
||||||
|
g.end_graph ();
|
||||||
|
};
|
||||||
|
const at = (g: GraphStream) => {
|
||||||
|
g.attributes ({ color: 'red' });
|
||||||
|
};
|
||||||
|
const ce = (g: GraphStream) => {
|
||||||
|
g.create_edge ('foo', 'bar');
|
||||||
|
};
|
||||||
|
|
||||||
|
const combinations = [
|
||||||
|
{
|
||||||
|
primary: (g: GraphStream) => {
|
||||||
|
cug (g);
|
||||||
|
cn (g);
|
||||||
|
},
|
||||||
|
secondary: [
|
||||||
|
cug,
|
||||||
|
cdg
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
primary: cug,
|
||||||
|
secondary: [
|
||||||
|
cug,
|
||||||
|
cdg
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
primary: cdg,
|
||||||
|
secondary: [
|
||||||
|
cug,
|
||||||
|
cdg
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
primary: (g: GraphStream) => {
|
||||||
|
cug (g);
|
||||||
|
csg (g);
|
||||||
|
},
|
||||||
|
secondary: [
|
||||||
|
cug,
|
||||||
|
cdg
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
primary: (g: GraphStream) => {
|
||||||
|
cug (g);
|
||||||
|
csg (g);
|
||||||
|
eg (g);
|
||||||
|
},
|
||||||
|
secondary: [
|
||||||
|
cug,
|
||||||
|
cdg,
|
||||||
|
at
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
primary: (g: GraphStream) => {
|
||||||
|
cug (g);
|
||||||
|
at (g);
|
||||||
|
},
|
||||||
|
secondary: [
|
||||||
|
cug,
|
||||||
|
cdg,
|
||||||
|
at
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
primary: (g: GraphStream) => {
|
||||||
|
cug (g);
|
||||||
|
ce (g);
|
||||||
|
},
|
||||||
|
secondary: [
|
||||||
|
cug,
|
||||||
|
cdg
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const comb of combinations) {
|
||||||
|
for (const secondary of comb.secondary) {
|
||||||
|
const g = (new GraphStream);
|
||||||
|
comb.primary (g);
|
||||||
|
expect (() => secondary (g))
|
||||||
|
.toThrowError (
|
||||||
|
/invalid state to execute command.*?expected:.*?actual:/uis
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
Reference in New Issue
Block a user