| @ -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(); | |||
| }); | |||
| }); | |||
| }); | |||