| @ -0,0 +1,177 @@ | |||||
| var assert = require('assert'); | |||||
| var moment = require('moment'); | |||||
| var DataSet = require('../lib/DataSet'); | |||||
| var now = new Date(); | |||||
| // TODO: improve DataSet tests, split up in one test per function | |||||
| describe('DataSet', function () { | |||||
| it('should work', function () { | |||||
| var data = new DataSet({ | |||||
| type: { | |||||
| start: 'Date', | |||||
| end: 'Date' | |||||
| } | |||||
| }); | |||||
| // add single items with different date types | |||||
| data.add({id: 1, content: 'Item 1', start: new Date(now.valueOf())}); | |||||
| data.add({id: 2, content: 'Item 2', start: now.toISOString()}); | |||||
| data.add([ | |||||
| //{id: 3, content: 'Item 3', start: moment(now)}, // TODO: moment fails, not the same instance | |||||
| {id: 3, content: 'Item 3', start: now}, | |||||
| {id: 4, content: 'Item 4', start: '/Date(' + now.valueOf() + ')/'} | |||||
| ]); | |||||
| var items = data.get(); | |||||
| assert.equal(items.length, 4); | |||||
| items.forEach(function (item) { | |||||
| assert.ok(item.start instanceof Date); | |||||
| }); | |||||
| // get filtered fields only | |||||
| var sort = function (a, b) { | |||||
| return a.id > b.id; | |||||
| }; | |||||
| assert.deepEqual(data.get({ | |||||
| fields: ['id', 'content'] | |||||
| }).sort(sort), [ | |||||
| {id: 1, content: 'Item 1'}, | |||||
| {id: 2, content: 'Item 2'}, | |||||
| {id: 3, content: 'Item 3'}, | |||||
| {id: 4, content: 'Item 4'} | |||||
| ]); | |||||
| // convert dates | |||||
| assert.deepEqual(data.get({ | |||||
| fields: ['id', 'start'], | |||||
| type: {start: 'Number'} | |||||
| }).sort(sort), [ | |||||
| {id: 1, start: now.valueOf()}, | |||||
| {id: 2, start: now.valueOf()}, | |||||
| {id: 3, start: now.valueOf()}, | |||||
| {id: 4, start: now.valueOf()} | |||||
| ]); | |||||
| // get a single item | |||||
| assert.deepEqual(data.get(1, { | |||||
| fields: ['id', 'start'], | |||||
| type: {start: 'ISODate'} | |||||
| }), { | |||||
| id: 1, | |||||
| start: now.toISOString() | |||||
| }); | |||||
| // remove an item | |||||
| data.remove(2); | |||||
| assert.deepEqual(data.get({ | |||||
| fields: ['id'] | |||||
| }).sort(sort), [ | |||||
| {id: 1}, | |||||
| {id: 3}, | |||||
| {id: 4} | |||||
| ]); | |||||
| // add an item | |||||
| data.add({id: 5, content: 'Item 5', start: now.valueOf()}); | |||||
| assert.deepEqual(data.get({ | |||||
| fields: ['id'] | |||||
| }).sort(sort), [ | |||||
| {id: 1}, | |||||
| {id: 3}, | |||||
| {id: 4}, | |||||
| {id: 5} | |||||
| ]); | |||||
| // update an item | |||||
| data.update({id: 5, content: 'changed!'}); // update item (extend existing fields) | |||||
| data.remove(3); // remove existing item | |||||
| data.add({id: 3, other: 'bla'}); // add new item | |||||
| data.update({id: 6, content: 'created!', start: now.valueOf()}); // this item is not yet existing, create it | |||||
| assert.deepEqual(data.get().sort(sort), [ | |||||
| {id: 1, content: 'Item 1', start: now}, | |||||
| {id: 3, other: 'bla'}, | |||||
| {id: 4, content: 'Item 4', start: now}, | |||||
| {id: 5, content: 'changed!', start: now}, | |||||
| {id: 6, content: 'created!', start: now} | |||||
| ]); | |||||
| data.clear(); | |||||
| assert.equal(data.get().length, 0); | |||||
| // test filtering and sorting | |||||
| data = new DataSet(); | |||||
| data.add([ | |||||
| {id: 1, age: 30, group: 2}, | |||||
| {id: 2, age: 25, group: 4}, | |||||
| {id: 3, age: 17, group: 2}, | |||||
| {id: 4, age: 27, group: 3} | |||||
| ]); | |||||
| assert.deepEqual(data.get({order: 'age'}), [ | |||||
| {id: 3, age: 17, group: 2}, | |||||
| {id: 2, age: 25, group: 4}, | |||||
| {id: 4, age: 27, group: 3}, | |||||
| {id: 1, age: 30, group: 2} | |||||
| ]); | |||||
| assert.deepEqual(data.getIds({order: 'age'}), [3, 2, 4, 1]); | |||||
| assert.deepEqual(data.get({order: 'age', fields: ['id']}), [ | |||||
| {id: 3}, | |||||
| {id: 2}, | |||||
| {id: 4}, | |||||
| {id: 1} | |||||
| ]); | |||||
| assert.deepEqual(data.get({ | |||||
| order: 'age', | |||||
| filter: function (item) { | |||||
| return item.group == 2; | |||||
| }, | |||||
| fields: ['id'] | |||||
| }), [ | |||||
| {id: 3}, | |||||
| {id: 1} | |||||
| ]); | |||||
| assert.deepEqual(data.getIds({ | |||||
| order: 'age', | |||||
| filter: function (item) { | |||||
| return (item.group == 2); | |||||
| } | |||||
| }), [3, 1]); | |||||
| data.clear(); | |||||
| // test if the setting of the showInternalIds works locally for a single get request | |||||
| data.add({content: 'Item 1'}); | |||||
| data.add({content: 'Item 2'}); | |||||
| assert.notStrictEqual(data.get()[0].id, undefined); | |||||
| // create a dataset with initial data | |||||
| var data = new DataSet([ | |||||
| {id: 1, content: 'Item 1', start: new Date(now.valueOf())}, | |||||
| {id: 2, content: 'Item 2', start: now.toISOString()} | |||||
| ]); | |||||
| assert.deepEqual(data.getIds(), [1, 2]); | |||||
| // create a dataset with initial data and options | |||||
| var data = new DataSet([ | |||||
| {_id: 1, content: 'Item 1', start: new Date(now.valueOf())}, | |||||
| {_id: 2, content: 'Item 2', start: now.toISOString()} | |||||
| ], {fieldId: '_id'}); | |||||
| assert.deepEqual(data.getIds(), [1, 2]); | |||||
| // TODO: extensively test DataSet | |||||
| // TODO: test subscribing to events | |||||
| }); | |||||
| }); | |||||
| @ -0,0 +1,69 @@ | |||||
| var assert = require('assert'); | |||||
| var moment = require('moment'); | |||||
| var DataSet = require('../lib/DataSet'); | |||||
| var DataView = require('../lib/DataView'); | |||||
| // TODO: improve DataView tests, split up in one test per function | |||||
| describe('DataView', function () { | |||||
| it('should work', function () { | |||||
| var groups = new DataSet(); | |||||
| // add items with different groups | |||||
| groups.add([ | |||||
| {id: 1, content: 'Item 1', group: 1}, | |||||
| {id: 2, content: 'Item 2', group: 2}, | |||||
| {id: 3, content: 'Item 3', group: 2}, | |||||
| {id: 4, content: 'Item 4', group: 1}, | |||||
| {id: 5, content: 'Item 5', group: 3} | |||||
| ]); | |||||
| var group2 = new DataView(groups, { | |||||
| filter: function (item) { | |||||
| return item.group == 2; | |||||
| } | |||||
| }); | |||||
| // test getting the filtered data | |||||
| assert.deepEqual(group2.get(), [ | |||||
| {id: 2, content: 'Item 2', group: 2}, | |||||
| {id: 3, content: 'Item 3', group: 2} | |||||
| ]); | |||||
| // test filtering the view contents | |||||
| assert.deepEqual(group2.get({ | |||||
| filter: function (item) { | |||||
| return item.id > 2; | |||||
| } | |||||
| }), [ | |||||
| {id: 3, content: 'Item 3', group: 2} | |||||
| ]); | |||||
| // test event subscription | |||||
| var groupsTriggerCount = 0; | |||||
| groups.on('*', function () { | |||||
| groupsTriggerCount++; | |||||
| }); | |||||
| var group2TriggerCount = 0; | |||||
| group2.on('*', function () { | |||||
| group2TriggerCount++; | |||||
| }); | |||||
| groups.update({id:2, content: 'Item 2 (changed)'}); | |||||
| assert.equal(groupsTriggerCount, 1); | |||||
| assert.equal(group2TriggerCount, 1); | |||||
| groups.update({id:5, content: 'Item 5 (changed)'}); | |||||
| assert.equal(groupsTriggerCount, 2); | |||||
| assert.equal(group2TriggerCount, 1); | |||||
| // detach the view from groups | |||||
| group2.setData(null); | |||||
| assert.equal(groupsTriggerCount, 2); | |||||
| assert.equal(group2TriggerCount, 2); | |||||
| groups.update({id:2, content: 'Item 2 (changed again)'}); | |||||
| assert.equal(groupsTriggerCount, 3); | |||||
| assert.equal(group2TriggerCount, 2); | |||||
| }); | |||||
| }); | |||||
| @ -1,171 +0,0 @@ | |||||
| var assert = require('assert'); | |||||
| var moment = require('moment'); | |||||
| var DataSet = require('../lib/DataSet'); | |||||
| var now = new Date(); | |||||
| var data = new DataSet({ | |||||
| type: { | |||||
| start: 'Date', | |||||
| end: 'Date' | |||||
| } | |||||
| }); | |||||
| // add single items with different date types | |||||
| data.add({id: 1, content: 'Item 1', start: new Date(now.valueOf())}); | |||||
| data.add({id: 2, content: 'Item 2', start: now.toISOString()}); | |||||
| data.add([ | |||||
| //{id: 3, content: 'Item 3', start: moment(now)}, // TODO: moment fails, not the same instance | |||||
| {id: 3, content: 'Item 3', start: now}, | |||||
| {id: 4, content: 'Item 4', start: '/Date(' + now.valueOf() + ')/'} | |||||
| ]); | |||||
| var items = data.get(); | |||||
| assert.equal(items.length, 4); | |||||
| items.forEach(function (item) { | |||||
| assert.ok(item.start instanceof Date); | |||||
| }); | |||||
| // get filtered fields only | |||||
| var sort = function (a, b) { | |||||
| return a.id > b.id; | |||||
| }; | |||||
| assert.deepEqual(data.get({ | |||||
| fields: ['id', 'content'] | |||||
| }).sort(sort), [ | |||||
| {id: 1, content: 'Item 1'}, | |||||
| {id: 2, content: 'Item 2'}, | |||||
| {id: 3, content: 'Item 3'}, | |||||
| {id: 4, content: 'Item 4'} | |||||
| ]); | |||||
| // convert dates | |||||
| assert.deepEqual(data.get({ | |||||
| fields: ['id', 'start'], | |||||
| type: {start: 'Number'} | |||||
| }).sort(sort), [ | |||||
| {id: 1, start: now.valueOf()}, | |||||
| {id: 2, start: now.valueOf()}, | |||||
| {id: 3, start: now.valueOf()}, | |||||
| {id: 4, start: now.valueOf()} | |||||
| ]); | |||||
| // get a single item | |||||
| assert.deepEqual(data.get(1, { | |||||
| fields: ['id', 'start'], | |||||
| type: {start: 'ISODate'} | |||||
| }), { | |||||
| id: 1, | |||||
| start: now.toISOString() | |||||
| }); | |||||
| // remove an item | |||||
| data.remove(2); | |||||
| assert.deepEqual(data.get({ | |||||
| fields: ['id'] | |||||
| }).sort(sort), [ | |||||
| {id: 1}, | |||||
| {id: 3}, | |||||
| {id: 4} | |||||
| ]); | |||||
| // add an item | |||||
| data.add({id: 5, content: 'Item 5', start: now.valueOf()}); | |||||
| assert.deepEqual(data.get({ | |||||
| fields: ['id'] | |||||
| }).sort(sort), [ | |||||
| {id: 1}, | |||||
| {id: 3}, | |||||
| {id: 4}, | |||||
| {id: 5} | |||||
| ]); | |||||
| // update an item | |||||
| data.update({id: 5, content: 'changed!'}); // update item (extend existing fields) | |||||
| data.remove(3); // remove existing item | |||||
| data.add({id: 3, other: 'bla'}); // add new item | |||||
| data.update({id: 6, content: 'created!', start: now.valueOf()}); // this item is not yet existing, create it | |||||
| assert.deepEqual(data.get().sort(sort), [ | |||||
| {id: 1, content: 'Item 1', start: now}, | |||||
| {id: 3, other: 'bla'}, | |||||
| {id: 4, content: 'Item 4', start: now}, | |||||
| {id: 5, content: 'changed!', start: now}, | |||||
| {id: 6, content: 'created!', start: now} | |||||
| ]); | |||||
| data.clear(); | |||||
| assert.equal(data.get().length, 0); | |||||
| // test filtering and sorting | |||||
| data = new DataSet(); | |||||
| data.add([ | |||||
| {id:1, age: 30, group: 2}, | |||||
| {id:2, age: 25, group: 4}, | |||||
| {id:3, age: 17, group: 2}, | |||||
| {id:4, age: 27, group: 3} | |||||
| ]); | |||||
| assert.deepEqual(data.get({order: 'age'}), [ | |||||
| {id:3, age: 17, group: 2}, | |||||
| {id:2, age: 25, group: 4}, | |||||
| {id:4, age: 27, group: 3}, | |||||
| {id:1, age: 30, group: 2} | |||||
| ]); | |||||
| assert.deepEqual(data.getIds({order: 'age'}), [3,2,4,1]); | |||||
| assert.deepEqual(data.get({order: 'age', fields: ['id']}), [ | |||||
| {id:3}, | |||||
| {id:2}, | |||||
| {id:4}, | |||||
| {id:1} | |||||
| ]); | |||||
| assert.deepEqual(data.get({ | |||||
| order: 'age', | |||||
| filter: function (item) { | |||||
| return item.group == 2; | |||||
| }, | |||||
| fields: ['id'] | |||||
| }), [ | |||||
| {id:3}, | |||||
| {id:1} | |||||
| ]); | |||||
| assert.deepEqual(data.getIds({ | |||||
| order: 'age', | |||||
| filter: function (item) { | |||||
| return (item.group == 2); | |||||
| } | |||||
| }), [3,1]); | |||||
| data.clear(); | |||||
| // test if the setting of the showInternalIds works locally for a single get request | |||||
| data.add({content: 'Item 1'}); | |||||
| data.add({content: 'Item 2'}); | |||||
| assert.notStrictEqual(data.get()[0].id, undefined); | |||||
| // create a dataset with initial data | |||||
| var data = new DataSet([ | |||||
| {id: 1, content: 'Item 1', start: new Date(now.valueOf())}, | |||||
| {id: 2, content: 'Item 2', start: now.toISOString()} | |||||
| ]); | |||||
| assert.deepEqual(data.getIds(), [1, 2]); | |||||
| // create a dataset with initial data and options | |||||
| var data = new DataSet([ | |||||
| {_id: 1, content: 'Item 1', start: new Date(now.valueOf())}, | |||||
| {_id: 2, content: 'Item 2', start: now.toISOString()} | |||||
| ], {fieldId: '_id'}); | |||||
| assert.deepEqual(data.getIds(), [1, 2]); | |||||
| // TODO: extensively test DataSet | |||||
| // TODO: test subscribing to events | |||||
| @ -1,63 +0,0 @@ | |||||
| var assert = require('assert'); | |||||
| var moment = require('moment'); | |||||
| var DataSet = require('../lib/DataSet'); | |||||
| var DataView = require('../lib/DataView'); | |||||
| var groups = new DataSet(); | |||||
| // add items with different groups | |||||
| groups.add([ | |||||
| {id: 1, content: 'Item 1', group: 1}, | |||||
| {id: 2, content: 'Item 2', group: 2}, | |||||
| {id: 3, content: 'Item 3', group: 2}, | |||||
| {id: 4, content: 'Item 4', group: 1}, | |||||
| {id: 5, content: 'Item 5', group: 3} | |||||
| ]); | |||||
| var group2 = new DataView(groups, { | |||||
| filter: function (item) { | |||||
| return item.group == 2; | |||||
| } | |||||
| }); | |||||
| // test getting the filtered data | |||||
| assert.deepEqual(group2.get(), [ | |||||
| {id: 2, content: 'Item 2', group: 2}, | |||||
| {id: 3, content: 'Item 3', group: 2} | |||||
| ]); | |||||
| // test filtering the view contents | |||||
| assert.deepEqual(group2.get({ | |||||
| filter: function (item) { | |||||
| return item.id > 2; | |||||
| } | |||||
| }), [ | |||||
| {id: 3, content: 'Item 3', group: 2} | |||||
| ]); | |||||
| // test event subscription | |||||
| var groupsTriggerCount = 0; | |||||
| groups.on('*', function () { | |||||
| groupsTriggerCount++; | |||||
| }); | |||||
| var group2TriggerCount = 0; | |||||
| group2.on('*', function () { | |||||
| group2TriggerCount++; | |||||
| }); | |||||
| groups.update({id:2, content: 'Item 2 (changed)'}); | |||||
| assert.equal(groupsTriggerCount, 1); | |||||
| assert.equal(group2TriggerCount, 1); | |||||
| groups.update({id:5, content: 'Item 5 (changed)'}); | |||||
| assert.equal(groupsTriggerCount, 2); | |||||
| assert.equal(group2TriggerCount, 1); | |||||
| // detach the view from groups | |||||
| group2.setData(null); | |||||
| assert.equal(groupsTriggerCount, 2); | |||||
| assert.equal(group2TriggerCount, 2); | |||||
| groups.update({id:2, content: 'Item 2 (changed again)'}); | |||||
| assert.equal(groupsTriggerCount, 3); | |||||
| assert.equal(group2TriggerCount, 2); | |||||
| @ -1,179 +0,0 @@ | |||||
| var assert = require('assert'), | |||||
| fs = require('fs'), | |||||
| dot = require('../lib/network/dotparser.js'); | |||||
| fs.readFile('test/dot.txt', function (err, data) { | |||||
| data = String(data); | |||||
| var graph = dot.parseDOT(data); | |||||
| assert.deepEqual(graph, { | |||||
| "type": "digraph", | |||||
| "id": "test_graph", | |||||
| "rankdir": "LR", | |||||
| "size": "8,5", | |||||
| "font": "arial", | |||||
| "nodes": [ | |||||
| { | |||||
| "id": "node1", | |||||
| "attr": { | |||||
| "shape": "doublecircle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "node2", | |||||
| "attr": { | |||||
| "shape": "doublecircle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "node3", | |||||
| "attr": { | |||||
| "shape": "doublecircle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "node4", | |||||
| "attr": { | |||||
| "shape": "diamond", | |||||
| "color": "red" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "node5", | |||||
| "attr": { | |||||
| "shape": "square", | |||||
| "color": "blue", | |||||
| "width": 3 | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": 6, | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "A", | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "B", | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "C", | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| } | |||||
| ], | |||||
| "edges": [ | |||||
| { | |||||
| "from": "node1", | |||||
| "to": "node1", | |||||
| "type": "->", | |||||
| "attr": { | |||||
| "length": 170, | |||||
| "fontSize": 12, | |||||
| "label": "a" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "from": "node2", | |||||
| "to": "node3", | |||||
| "type": "->", | |||||
| "attr": { | |||||
| "length": 170, | |||||
| "fontSize": 12, | |||||
| "label": "b" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "from": "node1", | |||||
| "to": "node4", | |||||
| "type": "--", | |||||
| "attr": { | |||||
| "length": 170, | |||||
| "fontSize": 12, | |||||
| "label": "c" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "from": "node3", | |||||
| "to": "node4", | |||||
| "type": "->", | |||||
| "attr": { | |||||
| "length": 170, | |||||
| "fontSize": 12, | |||||
| "label": "d" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "from": "node4", | |||||
| "to": "node5", | |||||
| "type": "->", | |||||
| "attr": { | |||||
| "length": 170, | |||||
| "fontSize": 12 | |||||
| } | |||||
| }, | |||||
| { | |||||
| "from": "node5", | |||||
| "to": 6, | |||||
| "type": "->", | |||||
| "attr": { | |||||
| "length": 170, | |||||
| "fontSize": 12 | |||||
| } | |||||
| }, | |||||
| { | |||||
| "from": "A", | |||||
| "to": { | |||||
| "nodes": [ | |||||
| { | |||||
| "id": "B", | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "C", | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| } | |||||
| ] | |||||
| }, | |||||
| "type": "->", | |||||
| "attr": { | |||||
| "length": 170, | |||||
| "fontSize": 12 | |||||
| } | |||||
| } | |||||
| ], | |||||
| "subgraphs": [ | |||||
| { | |||||
| "nodes": [ | |||||
| { | |||||
| "id": "B", | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "C", | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| } | |||||
| ] | |||||
| } | |||||
| ] | |||||
| }); | |||||
| }); | |||||
| @ -0,0 +1,186 @@ | |||||
| var assert = require('assert'), | |||||
| fs = require('fs'), | |||||
| dot = require('../lib/network/dotparser.js'); | |||||
| describe('dotparser', function () { | |||||
| it('should parse a DOT file into JSON', function (done) { | |||||
| fs.readFile('test/dot.txt', function (err, data) { | |||||
| data = String(data); | |||||
| var graph = dot.parseDOT(data); | |||||
| assert.deepEqual(graph, { | |||||
| "type": "digraph", | |||||
| "id": "test_graph", | |||||
| "rankdir": "LR", | |||||
| "size": "8,5", | |||||
| "font": "arial", | |||||
| "nodes": [ | |||||
| { | |||||
| "id": "node1", | |||||
| "attr": { | |||||
| "shape": "doublecircle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "node2", | |||||
| "attr": { | |||||
| "shape": "doublecircle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "node3", | |||||
| "attr": { | |||||
| "shape": "doublecircle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "node4", | |||||
| "attr": { | |||||
| "shape": "diamond", | |||||
| "color": "red" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "node5", | |||||
| "attr": { | |||||
| "shape": "square", | |||||
| "color": "blue", | |||||
| "width": 3 | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": 6, | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "A", | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "B", | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "C", | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| } | |||||
| ], | |||||
| "edges": [ | |||||
| { | |||||
| "from": "node1", | |||||
| "to": "node1", | |||||
| "type": "->", | |||||
| "attr": { | |||||
| "length": 170, | |||||
| "fontSize": 12, | |||||
| "label": "a" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "from": "node2", | |||||
| "to": "node3", | |||||
| "type": "->", | |||||
| "attr": { | |||||
| "length": 170, | |||||
| "fontSize": 12, | |||||
| "label": "b" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "from": "node1", | |||||
| "to": "node4", | |||||
| "type": "--", | |||||
| "attr": { | |||||
| "length": 170, | |||||
| "fontSize": 12, | |||||
| "label": "c" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "from": "node3", | |||||
| "to": "node4", | |||||
| "type": "->", | |||||
| "attr": { | |||||
| "length": 170, | |||||
| "fontSize": 12, | |||||
| "label": "d" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "from": "node4", | |||||
| "to": "node5", | |||||
| "type": "->", | |||||
| "attr": { | |||||
| "length": 170, | |||||
| "fontSize": 12 | |||||
| } | |||||
| }, | |||||
| { | |||||
| "from": "node5", | |||||
| "to": 6, | |||||
| "type": "->", | |||||
| "attr": { | |||||
| "length": 170, | |||||
| "fontSize": 12 | |||||
| } | |||||
| }, | |||||
| { | |||||
| "from": "A", | |||||
| "to": { | |||||
| "nodes": [ | |||||
| { | |||||
| "id": "B", | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "C", | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| } | |||||
| ] | |||||
| }, | |||||
| "type": "->", | |||||
| "attr": { | |||||
| "length": 170, | |||||
| "fontSize": 12 | |||||
| } | |||||
| } | |||||
| ], | |||||
| "subgraphs": [ | |||||
| { | |||||
| "nodes": [ | |||||
| { | |||||
| "id": "B", | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| }, | |||||
| { | |||||
| "id": "C", | |||||
| "attr": { | |||||
| "shape": "circle" | |||||
| } | |||||
| } | |||||
| ] | |||||
| } | |||||
| ] | |||||
| }); | |||||
| done(); | |||||
| }); | |||||
| }); | |||||
| }); | |||||