Compare commits
	
		
			3 Commits
		
	
	
		
			cafcc73366
			...
			af7bd4e00e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| af7bd4e00e | |||
| 9a2c2ce14c | |||
| 59542eb7b1 | 
							
								
								
									
										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
 | 
			
		||||
}
 | 
			
		||||
@@ -9,7 +9,6 @@
 | 
			
		||||
/* eslint-disable no-inline-comments */
 | 
			
		||||
type GraphStreamCommand =
 | 
			
		||||
  'cn'|
 | 
			
		||||
  'en'|
 | 
			
		||||
  'cug'|
 | 
			
		||||
  'cdg'|
 | 
			
		||||
  'csg'|
 | 
			
		||||
@@ -20,7 +19,6 @@ type GraphStreamCommand =
 | 
			
		||||
function translate_command (cmd: GraphStreamCommand|''): string {
 | 
			
		||||
  const translations = {
 | 
			
		||||
    cn:  'create node',
 | 
			
		||||
    en:  'end node',
 | 
			
		||||
    cug: 'create unordered graph',
 | 
			
		||||
    cdg: 'create directional graph',
 | 
			
		||||
    csg: 'create subgraph',
 | 
			
		||||
 
 | 
			
		||||
@@ -14,16 +14,19 @@
 | 
			
		||||
  },
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@ava/typescript": "^1.1.1",
 | 
			
		||||
    "@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",
 | 
			
		||||
    "jasmine": "^3.6.1",
 | 
			
		||||
    "jasmine-ts": "^0.3.0",
 | 
			
		||||
    "nyc": "^15.0.1",
 | 
			
		||||
    "ts-node": "^9.0.0",
 | 
			
		||||
    "typescript": "^4.0.2"
 | 
			
		||||
  },
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "lint": "eslint . --ext .js,.jsx,.ts,.tsx,.vue,.mjs",
 | 
			
		||||
    "test": "tsc && nyc ava",
 | 
			
		||||
    "test": "nyc jasmine-ts --config=\"jasmine.json\"",
 | 
			
		||||
    "compile": "tsc"
 | 
			
		||||
  },
 | 
			
		||||
  "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);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										85
									
								
								test/spec/Node.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								test/spec/Node.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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", 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';
 | 
			
		||||
 | 
			
		||||
    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 ((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 ((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