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