1
0
Fork 0
arangodb/js/apps/system/aardvark/test/specs/graphViewer/specAdapter/abstractAdapterSpec.js

2458 lines
71 KiB
JavaScript

/*jslint indent: 2, nomen: true, maxlen: 100, white: true plusplus: true */
/*global beforeEach, afterEach */
/*global describe, it, expect, jasmine */
/*global runs, spyOn, waitsFor, waits */
/*global window, document, setTimeout */
/*global $, _, d3*/
/*global describeInterface*/
/*global AbstractAdapter*/
////////////////////////////////////////////////////////////////////////////////
/// @brief Graph functionality
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
(function () {
"use strict";
describe('Abstract Adapter', function () {
var nodes, edges,
descendant,
getCommunityNodes = function() {
return _.filter(nodes, function(n) {
return n._isCommunity;
});
},
getCommunityNodesIds = function() {
return _.pluck(getCommunityNodes(), "_id");
},
nodeWithID = function(id) {
return $.grep(nodes, function(e){
return e._id === id;
})[0];
},
edgeWithSourceAndTargetId = function(sourceId, targetId) {
return $.grep(edges, function(e){
return e.source._id === sourceId
&& e.target._id === targetId;
})[0];
},
existNode = function(id) {
var node = nodeWithID(id);
expect(node).toBeDefined();
expect(node._id).toEqual(id);
},
notExistNode = function(id) {
var node = nodeWithID(id);
expect(node).toBeUndefined();
},
existEdge = function(source, target) {
var edge = edgeWithSourceAndTargetId(source, target);
expect(edge).toBeDefined();
expect(edge.source._id).toEqual(source);
expect(edge.target._id).toEqual(target);
},
notExistEdge = function(source, target) {
var edge = edgeWithSourceAndTargetId(source, target);
expect(edge).toBeUndefined();
},
existNodes = function(ids) {
_.each(ids, existNode);
},
notExistNodes = function(ids) {
_.each(ids, notExistNode);
};
beforeEach(function() {
nodes = [];
edges = [];
descendant = {
loadNode: function(){}
};
});
describe('setup process', function() {
it('should throw an error if nodes are not given', function() {
expect(
function() {
var t = new AbstractAdapter();
}
).toThrow("The nodes have to be given.");
});
it('should throw an error if edges are not given', function() {
expect(
function() {
var t = new AbstractAdapter([]);
}
).toThrow("The edges have to be given.");
});
it('should throw an error if no inheriting class is given', function() {
expect(
function() {
var t = new AbstractAdapter([], []);
}
).toThrow("An inheriting class has to be given.");
});
it('should not throw an error if setup correctly', function() {
expect(
function() {
var t = new AbstractAdapter([], [], descendant);
}
).not.toThrow();
});
it('should create a NodeReducer instance', function() {
spyOn(window, "NodeReducer");
var nodes = [],
edges = [],
t = new AbstractAdapter(nodes, edges, descendant);
expect(window.NodeReducer).wasCalledWith();
});
it('should send the nodeReducer the configuration if given', function() {
spyOn(window, "NodeReducer");
var nodes = [],
edges = [],
config = {
prioList: ["foo", "bar", "baz"]
},
t = new AbstractAdapter(nodes, edges, descendant, config);
expect(window.NodeReducer).wasCalledWith(["foo", "bar", "baz"]);
});
it('should create a ModularityJoiner worker', function() {
spyOn(window, "WebWorkerWrapper");
var nodes = [],
edges = [],
t = new AbstractAdapter(nodes, edges, descendant);
expect(window.WebWorkerWrapper).wasCalledWith(
window.ModularityJoiner,
jasmine.any(Function)
);
});
});
describe('checking the interface', function() {
var testee;
beforeEach(function() {
testee = new AbstractAdapter([], [], descendant);
this.addMatchers({
toHaveFunction: function(func, argCounter) {
var obj = this.actual;
this.message = function(){
return testee.constructor.name
+ " should react to function "
+ func
+ " with at least "
+ argCounter
+ " arguments.";
};
if (typeof(obj[func]) !== "function") {
return false;
}
if (obj[func].length < argCounter) {
return false;
}
return true;
}
});
});
it('should offer a function to set the width', function() {
expect(testee).toHaveFunction("setWidth", 1);
});
it('should offer a function to set the height', function() {
expect(testee).toHaveFunction("setHeight", 1);
});
it('should offer a function to insert a node', function() {
expect(testee).toHaveFunction("insertNode", 1);
});
it('should offer a function to insert an edge', function() {
expect(testee).toHaveFunction("insertEdge", 1);
});
it('should offer a function to remove a node', function() {
expect(testee).toHaveFunction("removeNode", 1);
});
it('should offer a function to remove an edge', function() {
expect(testee).toHaveFunction("removeEdge", 1);
});
it('should offer a function to remove edges for a given node', function() {
expect(testee).toHaveFunction("removeEdgesForNode", 1);
});
it('should offer a function to expand a community', function() {
expect(testee).toHaveFunction("expandCommunity", 1);
});
it('should offer a function to set the node limit', function() {
expect(testee).toHaveFunction("setNodeLimit", 1);
});
it('should offer a function to set the child limit', function() {
expect(testee).toHaveFunction("setChildLimit", 1);
});
it('should offer a function to check the amount of freshly inserted nodes', function() {
expect(testee).toHaveFunction("checkSizeOfInserted", 1);
});
it('should offer a function to check the overall amount of nodes', function() {
expect(testee).toHaveFunction("checkNodeLimit", 1);
});
it('should offer a function to change to a different configuration', function() {
expect(testee).toHaveFunction("changeTo", 1);
});
it('should offer a function to get the current priority list', function() {
expect(testee).toHaveFunction("getPrioList", 0);
});
});
describe('checking nodes', function() {
var adapter;
beforeEach(function() {
adapter = new AbstractAdapter(nodes, [], descendant);
});
it('should be possible to insert a node', function() {
var newNode = {_id: 1};
adapter.insertNode(newNode);
existNode(1);
expect(nodes.length).toEqual(1);
});
it('should not add the same node twice', function() {
var newNode = {_id: 1};
adapter.insertNode(newNode);
adapter.insertNode(newNode);
existNode(1);
expect(nodes.length).toEqual(1);
});
it('should add x and y coordinates', function() {
var newNode = {_id: 1};
adapter.insertNode(newNode);
this.addMatchers({
toHaveCorrectCoordinates: function() {
var list = this.actual,
evil;
_.each(list, function(n) {
if (isNaN(n.x) || isNaN(n.y)) {
evil = n;
}
});
this.message = function() {
return "Expected " + JSON.stringify(evil) + " to contain Numbers as X and Y.";
};
return evil === undefined;
}
});
expect(nodes).toHaveCorrectCoordinates();
});
it('should set in- and outbound counters', function() {
var newNode = adapter.insertNode({_id: 1});
expect(newNode._outboundCounter).toEqual(0);
expect(newNode._inboundCounter).toEqual(0);
});
it('should set the x coordinate close to the center', function() {
var width = 200,
newNode;
adapter.setWidth(width);
newNode = adapter.insertNode({_id: 1});
expect(newNode.x).toBeGreaterThan(width / 4);
expect(newNode.x).toBeLessThan(3 * width / 4);
});
it('should set the y coordinate close to the center', function() {
var height = 200,
newNode;
adapter.setHeight(height);
newNode = adapter.insertNode({_id: 1});
expect(newNode.y).toBeGreaterThan(height / 4);
expect(newNode.y).toBeLessThan(3 * height / 4);
});
it('should encapsulate all attributes in _data', function() {
var data = {
_id: 1,
name: "Alice",
age: 42
},
newNode = adapter.insertNode(data);
expect(newNode).toBeDefined();
expect(newNode._data).toEqual(data);
});
it('should be able to delete a node', function() {
var toDelete = {_id: 1},
nodeToDelete = adapter.insertNode(toDelete);
adapter.removeNode(nodeToDelete);
notExistNode(1);
expect(nodes.length).toEqual(0);
});
});
describe('checking edges', function() {
var adapter,
source,
target,
sourceid,
targetid;
beforeEach(function() {
adapter = new AbstractAdapter(nodes, edges, descendant);
source = adapter.insertNode({_id: 1});
target = adapter.insertNode({_id: 2});
sourceid = source._id;
targetid = target._id;
});
it('should be able to insert an edge', function() {
adapter.insertEdge({
_id: "1-2",
_from: sourceid,
_to: targetid
});
existEdge(sourceid, targetid);
expect(edges.length).toEqual(1);
});
it('should not insert the same edge twice', function() {
var toInsert = {
_id: "1-2",
_from: sourceid,
_to: targetid
};
adapter.insertEdge(toInsert);
adapter.insertEdge(toInsert);
existEdge(sourceid, targetid);
expect(edges.length).toEqual(1);
});
it('should throw an error if an edge is inserted with illeagal source', function() {
expect(
function() {
adapter.insertEdge({
_id: "1-3",
_from: 3,
_to: targetid
});
}
).toThrow("Unable to insert Edge, source node not existing 3");
notExistEdge(3, targetid);
expect(edges.length).toEqual(0);
});
it('should throw an error if an edge is inserted with illeagal target', function() {
expect(
function() {
adapter.insertEdge({
_id: "1-3",
_from: sourceid,
_to: 3
});
}
).toThrow("Unable to insert Edge, target node not existing 3");
notExistEdge(sourceid, 3);
expect(edges.length).toEqual(0);
});
it('should change the in- and outbound counters accordingly', function() {
var toInsert = {
_id: "1-2",
_from: sourceid,
_to: targetid
};
adapter.insertEdge(toInsert);
expect(source._outboundCounter).toEqual(1);
expect(source._inboundCounter).toEqual(0);
expect(target._outboundCounter).toEqual(0);
expect(target._inboundCounter).toEqual(1);
});
it('should encapsulate all attributes in _data', function() {
var data = {
_id: "1-2",
_from: sourceid,
_to: targetid,
label: "MyLabel",
color: "black"
},
edge = adapter.insertEdge(data);
expect(edge._data).toBeDefined();
expect(edge._data).toEqual(data);
});
it('should be able to delete an edge', function() {
var toDelete = {
_id: "1-2",
_from: sourceid,
_to: targetid
},
edgeToDel = adapter.insertEdge(toDelete);
adapter.removeEdge(edgeToDel);
notExistEdge(sourceid, targetid);
expect(edges.length).toEqual(0);
});
it('should be able to remove all edges of a node', function() {
adapter.insertNode({_id: 3});
adapter.insertEdge({
_id: "3-1",
_from: 3,
_to: sourceid // This is nodes[0]
});
var edgeToKeep = adapter.insertEdge({
_id: "2-3",
_from: targetid, // This is nodes[1]
_to: 3
});
adapter.removeEdgesForNode(source);
existEdge(2, 3);
notExistEdge(1, 2);
notExistEdge(3, 1);
expect(edges.length).toEqual(1);
expect(edges[0]).toEqual(edgeToKeep);
});
it('should maintain in- and outboundcounter '
+ 'when removing all edges of a node', function() {
var thirdNode = adapter.insertNode({_id: 3});
adapter.insertEdge({
_id: "3-1",
_from: 3,
_to: sourceid // This is nodes[0]
});
adapter.insertEdge({
_id: "2-3",
_from: targetid, // This is nodes[1]
_to: 3
});
adapter.removeEdgesForNode(source);
expect(nodes.length).toEqual(3);
existNode(1);
existNode(2);
existNode(3);
expect(source._inboundCounter).toEqual(0);
expect(source._outboundCounter).toEqual(0);
expect(target._inboundCounter).toEqual(0);
expect(target._outboundCounter).toEqual(1);
expect(thirdNode._inboundCounter).toEqual(1);
expect(thirdNode._outboundCounter).toEqual(0);
});
});
describe('checking node exploration', function() {
var adapter,
mockReducer,
mockWrapper,
workerCB;
beforeEach(function() {
mockWrapper = {};
mockWrapper.call = function() {};
mockReducer = {};
mockReducer.getCommunity = function() {};
mockReducer.bucketNodes = function() {};
spyOn(window, "NodeReducer").andCallFake(function() {
return {
bucketNodes: function(toSort, numBuckets) {
return mockReducer.bucketNodes(toSort, numBuckets);
}
};
});
spyOn(window, "WebWorkerWrapper").andCallFake(function(c, cb) {
workerCB = cb;
return {
call: function() {
mockWrapper.call.apply(
mockWrapper,
Array.prototype.slice.call(arguments)
);
}
};
});
adapter = new AbstractAdapter(nodes, edges, descendant);
});
it('should expand a collapsed node', function() {
var node = {
_id: "0"
},
loaded = 0,
loadedNodes = [];
adapter.insertNode(node);
spyOn(descendant, "loadNode").andCallFake(function(node) {
loaded++;
loadedNodes.push(node);
});
adapter.explore(node);
expect(descendant.loadNode).wasCalled();
expect(node._expanded).toBeTruthy();
expect(loaded).toEqual(1);
expect(loadedNodes.length).toEqual(1);
expect(loadedNodes[0]).toEqual(node._id);
});
it('should collapse an expanded node', function() {
var node = {
_id: "0"
};
node = adapter.insertNode(node);
node._expanded = true;
spyOn(descendant, "loadNode");
adapter.explore(node);
expect(node._expanded).toBeFalsy();
expect(descendant.loadNode).wasNotCalled();
});
it('should collapse a tree', function() {
var root = {
_id: "0"
},
c1 = {
_id: "1"
},
c2 = {
_id: "2"
},
e1 = {
_id: "0-1",
_from: "0",
_to: "1"
},
e2 = {
_id: "0-2",
_from: "0",
_to: "2"
};
root = adapter.insertNode(root);
// Fake expansion of node
root._expanded = true;
adapter.insertNode(c1);
adapter.insertNode(c2);
adapter.insertEdge(e1);
adapter.insertEdge(e2);
spyOn(descendant, "loadNode");
adapter.explore(root);
expect(root._expanded).toBeFalsy();
expect(descendant.loadNode).wasNotCalled();
expect(nodes.length).toEqual(1);
expect(edges.length).toEqual(0);
});
it('should not remove referenced nodes on collapsing ', function() {
var root = {
_id: "0"
},
c1 = {
_id: "1"
},
c2 = {
_id: "2"
},
c3 = {
_id: "3"
},
e1 = {
_id: "0-1",
_from: "0",
_to: "1"
},
e2 = {
_id: "0-3",
_from: "0",
_to: "3"
},
e3 = {
_id: "2-1",
_from: "2",
_to: "1"
};
root = adapter.insertNode(root);
root._expanded = true;
c1 = adapter.insertNode(c1);
c2 = adapter.insertNode(c2);
adapter.insertNode(c3);
adapter.insertEdge(e1);
adapter.insertEdge(e2);
adapter.insertEdge(e3);
spyOn(descendant, "loadNode");
adapter.explore(root);
expect(root._expanded).toBeFalsy();
expect(descendant.loadNode).wasNotCalled();
expect(nodes.length).toEqual(3);
expect(edges.length).toEqual(1);
expect(root._outboundCounter).toEqual(0);
expect(c1._inboundCounter).toEqual(1);
expect(c2._outboundCounter).toEqual(1);
});
describe('with community nodes', function() {
it('should expand a community node properly', function() {
// Hack for a CommunityNode
var comm = {
_id: "*community_1"
};
comm = adapter.insertNode(comm);
comm._isCommunity = true;
spyOn(adapter, "expandCommunity");
adapter.explore(comm, function() {});
expect(adapter.expandCommunity).toHaveBeenCalledWith(comm, jasmine.any(Function));
});
it('should remove a community if last pointer to it is collapsed', function() {
runs(function() {
var c0 = {
_id: "0"
},
internal = {
_id: "internal"
},
internal2 = {
_id: "internal2"
},
c1 = {
_id: "1"
},
c2 = {
_id: "2"
},
e0 = {
_id: "0-1",
_from: "0",
_to: "1"
},
e1 = {
_id: "1-c",
_from: "1",
_to: "internal"
},
e2 = {
_id: "c-2",
_from: "internal",
_to: "2"
},
commNode;
c0 = adapter.insertNode(c0);
c1 = adapter.insertNode(c1);
c1._expanded = true;
adapter.insertNode(internal);
adapter.insertNode(internal2);
c2 = adapter.insertNode(c2);
e0 = adapter.insertEdge(e0);
e1 = adapter.insertEdge(e1);
e2 = adapter.insertEdge(e2);
spyOn(mockWrapper, "call").andCallFake(function(name) {
workerCB({
data: {
cmd: name,
result: ["internal", "internal2"]
}
});
});
adapter.setNodeLimit(3);
commNode = getCommunityNodes()[0];
expect(nodes).toEqual([c0, c1, c2, commNode]);
expect(edges).toEqual([e0, e1, e2]);
adapter.explore(c1);
expect(nodes.length).toEqual(2);
expect(edges.length).toEqual(1);
expect(nodes).toEqual([c0, c1]);
expect(edges).toEqual([e0]);
});
});
it('should not remove a community if a pointer to it still exists', function() {
runs(function() {
var c0 = {
_id: "0"
},
c1 = {
_id: "1"
},
internal = {
_id: "internal"
},
internal2 = {
_id: "internal2"
},
e0 = {
_id: "0-1",
_from: "0",
_to: "1"
},
e1 = {
_id: "0-c",
_from: "0",
_to: "internal"
},
e2 = {
_id: "1-c",
_from: "1",
_to: "internal"
},
comm;
c0 = adapter.insertNode(c0);
c1 = adapter.insertNode(c1);
c1._expanded = true;
adapter.insertNode(internal);
adapter.insertNode(internal2);
e0 = adapter.insertEdge(e0);
e1 = adapter.insertEdge(e1);
adapter.insertEdge(e2);
spyOn(mockWrapper, "call").andCallFake(function(name) {
workerCB({
data: {
cmd: name,
result: ["internal", "internal2"]
}
});
});
adapter.setNodeLimit(3);
comm = getCommunityNodes()[0];
adapter.explore(c1);
expect(nodes).toEqual([c0, c1, comm]);
expect(edges).toEqual([e0, e1]);
});
});
it('should be possible to explore a node, collapse it and explore it again', function() {
var id1 = "1",
id2 = "2",
id3 = "3",
id4 = "4",
id5 = "5",
id6 = "6",
ids = "start",
n1 = {_id: id1},
n2 = {_id: id2},
n3 = {_id: id3},
n4 = {_id: id4},
n5 = {_id: id5},
n6 = {_id: id6},
ns = {_id: ids},
intS,
int1,
int2,
int3,
int4,
int5,
int6,
es1 = {
_id: ids + "-" + id1,
_from: ids,
_to: id1
},
es2 = {
_id: ids + "-" + id2,
_from: ids,
_to: id2
},
es3 = {
_id: ids + "-" + id3,
_from: ids,
_to: id3
},
es4 = {
_id: ids + "-" + id4,
_from: ids,
_to: id4
},
es5 = {
_id: ids + "-" + id5,
_from: ids,
_to: id5
},
es6 = {
_id: ids + "-" + id6,
_from: ids,
_to: id6
};
spyOn(mockReducer, "bucketNodes").andCallFake(function(list) {
return [
{
reason: {
type: "similar"
},
nodes: [int1, int2, int3]
},
{
reason: {
type: "similar"
},
nodes: [int4, int5, int6]
}
];
});
spyOn(descendant, "loadNode").andCallFake(function() {
var inserted = {};
int1 = adapter.insertNode(n1);
int2 = adapter.insertNode(n2);
int3 = adapter.insertNode(n3);
int4 = adapter.insertNode(n4);
int5 = adapter.insertNode(n5);
int6 = adapter.insertNode(n6);
inserted.id1 = int1;
inserted.id2 = int2;
inserted.id3 = int3;
inserted.id4 = int4;
inserted.id5 = int5;
inserted.id6 = int6;
adapter.insertEdge(es1);
adapter.insertEdge(es2);
adapter.insertEdge(es3);
adapter.insertEdge(es4);
adapter.insertEdge(es5);
adapter.insertEdge(es6);
adapter.checkSizeOfInserted(inserted);
});
adapter.setChildLimit(2);
expect(nodes).toEqual([]);
intS = adapter.insertNode(ns);
expect(nodes).toEqual([intS]);
adapter.explore(intS);
expect(nodes.length).toEqual(3);
expect(edges.length).toEqual(6);
expect(mockReducer.bucketNodes).wasCalledWith(
[int1, int2, int3, int4, int5, int6], 2
);
expect(intS._expanded).toBeTruthy();
adapter.explore(intS);
expect(nodes.length).toEqual(1);
expect(edges.length).toEqual(0);
expect(intS._expanded).toBeFalsy();
adapter.setChildLimit(3);
adapter.explore(intS);
expect(intS._expanded).toBeTruthy();
expect(nodes.length).toEqual(3);
expect(edges.length).toEqual(6);
expect(mockReducer.bucketNodes).wasCalledWith(
[int1, int2, int3, int4, int5, int6], 3
);
});
it('should be possible to propagate collapsing through a community', function() {
var id1 = "1",
id2 = "2",
id3 = "3",
id4 = "4",
id5 = "5",
ids = "start",
n1 = {_id: id1},
n2 = {_id: id2},
n3 = {_id: id3},
n4 = {_id: id4},
n5 = {_id: id5},
ns = {_id: ids},
intS,
int1,
int2,
int3,
int4,
int5,
es1 = {
_id: ids + "-" + id1,
_from: ids,
_to: id1
},
es2 = {
_id: ids + "-" + id2,
_from: ids,
_to: id2
},
e13 = {
_id: id1 + "-" + id3,
_from: id1,
_to: id3
},
e24 = {
_id: id2 + "-" + id4,
_from: id2,
_to: id4
},
e35 = {
_id: id3 + "-" + id5,
_from: id3,
_to: id5
};
spyOn(mockWrapper, "call").andCallFake(function(name) {
if (name === "getCommunity") {
workerCB({
data: {
cmd: name,
result: [id2, id3]
}
});
}
});
spyOn(descendant, "loadNode").andCallFake(function(n) {
if (n === ids) {
int1 = adapter.insertNode(n1);
int2 = adapter.insertNode(n2);
adapter.insertEdge(es1);
adapter.insertEdge(es2);
return;
}
if (n === id1) {
int3 = adapter.insertNode(n3);
adapter.insertEdge(e13);
return;
}
if (n === id2) {
int4 = adapter.insertNode(n4);
adapter.insertEdge(e24);
return;
}
if (n === id3) {
int5 = adapter.insertNode(n5);
adapter.insertEdge(e35);
return;
}
});
adapter.setChildLimit(2);
expect(nodes).toEqual([]);
intS = adapter.insertNode(ns);
expect(nodes).toEqual([intS]);
adapter.explore(intS);
expect(nodes).toEqual([intS, int1, int2]);
adapter.explore(int1);
expect(nodes).toEqual([intS, int1, int2, int3]);
adapter.explore(int2);
adapter.explore(int3);
adapter.setNodeLimit(5);
expect(mockWrapper.call).wasCalledWith("getCommunity", 5);
expect(nodes.length).toEqual(5);
expect(edges.length).toEqual(5);
expect(int1._expanded).toBeTruthy();
adapter.explore(int1);
expect(int1._expanded).toBeFalsy();
expect(nodes.length).toEqual(4);
expect(edges.length).toEqual(3);
});
});
});
describe('checking communities', function() {
var adapter,
mockReducer,
mockWrapper,
workerCB;
beforeEach(function() {
mockWrapper = {};
mockWrapper.call = function() {};
mockReducer = {};
mockReducer.getCommunity = function() {};
mockReducer.bucketNodes = function() {};
spyOn(window, "NodeReducer").andCallFake(function() {
return {
getCommunity: function(limit, focus) {
if (focus !== undefined) {
return mockReducer.getCommunity(limit, focus);
}
return mockReducer.getCommunity(limit);
},
bucketNodes: function(toSort, numBuckets) {
return mockReducer.bucketNodes(toSort, numBuckets);
}
};
});
spyOn(window, "WebWorkerWrapper").andCallFake(function(c, cb) {
workerCB = cb;
return {
call: function() {
mockWrapper.call.apply(
mockWrapper,
Array.prototype.slice.call(arguments)
);
}
};
});
adapter = new AbstractAdapter(nodes, edges, descendant);
});
/*
it('should not take any action if no limit is set', function() {
spyOn(mockWrapper, "call");
adapter.insertNode({_id: 1});
adapter.insertNode({_id: 2});
adapter.insertNode({_id: 3});
adapter.insertNode({_id: 4});
adapter.insertNode({_id: 5});
adapter.checkNodeLimit();
expect(mockWrapper.call).wasNotCalled();
});
it('should take a given focus into account', function() {
var n1, limit;
spyOn(mockWrapper, "call").andCallFake(function(name) {
workerCB({
data: {
cmd: name,
result: [2, 4]
}
});
});
limit = 2;
adapter.setNodeLimit(limit);
n1 = adapter.insertNode({_id: 1});
adapter.insertNode({_id: 2});
adapter.insertNode({_id: 3});
adapter.insertNode({_id: 4});
adapter.insertNode({_id: 5});
adapter.checkNodeLimit(n1);
expect(mockWrapper.call).toHaveBeenCalledWith("getCommunity", limit, n1._id);
});
it('should create a community if too many nodes are added', function() {
var n1, n2, commId;
spyOn(mockWrapper, "call").andCallFake(function(name) {
workerCB({
data: {
cmd: name,
result: [1, 2]
}
});
});
adapter.setNodeLimit(2);
n1 = adapter.insertNode({_id: 1});
n2 = adapter.insertNode({_id: 2});
adapter.insertNode({_id: 3});
adapter.checkNodeLimit();
expect(mockWrapper.call).wasCalledWith("getCommunity", 2);
expect(getCommunityNodesIds().length).toEqual(1);
notExistNode([1, 2]);
existNode(3);
});
it('should create a community if limit is set to small', function() {
var n1, n2, commId;
spyOn(mockWrapper, "call").andCallFake(function(name) {
workerCB({
data: {
cmd: name,
result: [1, 2]
}
});
});
n1 = adapter.insertNode({_id: 1});
n2 = adapter.insertNode({_id: 2});
adapter.insertNode({_id: 3});
adapter.setNodeLimit(2);
expect(mockWrapper.call).wasCalledWith("getCommunity", 2);
expect(getCommunityNodesIds().length).toEqual(1);
notExistNode([1, 2]);
existNode(3);
});
it('should create proper attributes for the community', function() {
var n1, n2, n3, n4, n5, com;
spyOn(mockWrapper, "call").andCallFake(function(name) {
workerCB({
data: {
cmd: name,
result: [1, 2, 3, 4, 5]
}
});
});
n1 = adapter.insertNode({_id: 1});
n2 = adapter.insertNode({_id: 2});
n3 = adapter.insertNode({_id: 3});
n4 = adapter.insertNode({_id: 4});
n5 = adapter.insertNode({_id: 5});
adapter.setNodeLimit(2);
com = getCommunityNodes()[0];
expect(com.x).toBeDefined();
expect(com.y).toBeDefined();
expect(com._size).toEqual(5);
});
it('should not trigger getCommunity multiple times', function() {
spyOn(mockWrapper, "call").andCallFake(function(name) {
setTimeout(function() {
workerCB({
data: {
cmd: name,
result: [1, 2]
}
});
}, 200);
});
adapter.insertNode({_id: 1});
adapter.insertNode({_id: 2});
adapter.insertNode({_id: 3});
adapter.insertNode({_id: 4});
adapter.insertNode({_id: 5});
adapter.insertNode({_id: 6});
adapter.setNodeLimit(5);
adapter.setNodeLimit(4);
adapter.setNodeLimit(3);
adapter.setNodeLimit(2);
adapter.setNodeLimit(1);
expect(mockWrapper.call).wasCalledWith("getCommunity", 5);
expect(mockWrapper.call.calls.length).toEqual(1);
});
it('should be able to trigger getCommunity after it returns', function() {
var send;
runs(function() {
send = false;
spyOn(mockWrapper, "call").andCallFake(function(name) {
if (!send) {
setTimeout(function() {
send = true;
workerCB({
data: {
cmd: name,
result: [1, 2]
}
});
}, 200);
}
});
adapter.insertNode({_id: 1});
adapter.insertNode({_id: 2});
adapter.insertNode({_id: 3});
adapter.insertNode({_id: 4});
adapter.insertNode({_id: 5});
adapter.insertNode({_id: 6});
adapter.setNodeLimit(5);
adapter.setNodeLimit(4);
expect(mockWrapper.call).wasCalledWith("getCommunity", 5);
expect(mockWrapper.call.calls.length).toEqual(1);
});
waitsFor(function() {
return send;
});
runs(function() {
adapter.setNodeLimit(3);
expect(mockWrapper.call).wasCalledWith("getCommunity", 3);
expect(mockWrapper.call.calls.length).toEqual(2);
});
});
it('should connect edges to communities', function() {
var n1, n2, comm, e1, e2, e3;
spyOn(mockWrapper, "call").andCallFake(function(name) {
workerCB({
data: {
cmd: name,
result: [1, 2]
}
});
});
n1 = adapter.insertNode({_id: 1});
n2 = adapter.insertNode({_id: 2});
adapter.insertNode({_id: 3});
e1 = adapter.insertEdge({
_id: "1-2",
_from: 1,
_to: 2
});
e2 = adapter.insertEdge({
_id: "2-3",
_from: 2,
_to: 3
});
e3 = adapter.insertEdge({
_id: "3-1",
_from: 3,
_to: 1
});
adapter.setNodeLimit(2);
comm = getCommunityNodes()[0];
notExistEdge(1, 2);
expect(e2.source).toEqual(comm);
expect(e3.target).toEqual(comm);
});
*/
describe('if a community allready exists', function() {
var n1, n2, n3, n4,
e1, e2, e3, comm,
fakeData;
beforeEach(function() {
fakeData = [1, 2];
spyOn(mockWrapper, "call").andCallFake(function(name) {
workerCB({
data: {
cmd: name,
result: fakeData
}
});
});
n1 = adapter.insertNode({_id: 1});
n2 = adapter.insertNode({_id: 2});
n3 = adapter.insertNode({_id: 3});
n4 = adapter.insertNode({_id: 4});
e1 = adapter.insertEdge({
_id: "1-2",
_from: 1,
_to: 2
});
e2 = adapter.insertEdge({
_id: "2-3",
_from: 2,
_to: 3
});
e3 = adapter.insertEdge({
_id: "3-1",
_from: 3,
_to: 1
});
adapter.setNodeLimit(3);
comm = getCommunityNodes()[0];
});
/*
it('should be able to expand the community', function() {
adapter.setNodeLimit(10);
adapter.expandCommunity(comm);
expect(getCommunityNodes().length).toEqual(1);
expect(comm._expanded).toBeTruthy();
expect(nodes.length).toEqual(3);
expect(edges.length).toEqual(2);
//existEdge(1, 2);
existEdge(comm._id, 3);
existEdge(3, comm._id);
existNodes([comm._id, 3, 4]);
});
*/
it('should collapse another community if limit is to small', function() {
fakeData = [3, 4];
adapter.expandCommunity(comm);
expect(getCommunityNodes().length).toEqual(2);
var comm2 = getCommunityNodes()[1];
expect(comm).not.toEqual(comm2);
expect(mockWrapper.call).wasCalled();
expect(nodes.length).toEqual(2);
existNodes([comm._id, comm2._id]);
expect(comm._expanded).toBeTruthy();
expect(comm2._expanded).toBeFalsy();
notExistNodes([1, 2, 3, 4]);
});
/*
it('should collapse another community if limit is further reduced', function() {
fakeData = [3, 4];
adapter.setNodeLimit(2);
expect(getCommunityNodes().length).toEqual(2);
var comm2 = getCommunityNodes()[1];
expect(comm).not.toEqual(comm2);
expect(mockWrapper.call).wasCalled();
expect(nodes.length).toEqual(2);
notExistNodes([1, 2, 3, 4]);
});
it('should be possible to insert an edge targeting a node in the community', function() {
var e = adapter.insertEdge({
_id: "4-2",
_from: 4,
_to: 2
});
expect(e.source).toEqual(n4);
expect(e.target).toEqual(comm);
expect(e._target).toEqual(n2);
expect(comm.getDissolveInfo().edges.inbound).toEqual([e3, e]);
});
it('should be possible to insert an edge starting'
+ ' from a node in the community', function() {
var e = adapter.insertEdge({
_id: "2-4",
_from: 2,
_to: 4
});
expect(e.source).toEqual(comm);
expect(e._source).toEqual(n2);
expect(e.target).toEqual(n4);
expect(comm.getDissolveInfo().edges.outbound).toEqual([e2, e]);
});
*/
});
});
describe('checking information of modularity joiner', function() {
var adapter,
source,
target,
sourceid,
targetid,
mockWrapper,
mockReducer,
workerCB;
beforeEach(function() {
mockReducer = {};
mockReducer.bucketNodes = function() {};
spyOn(window, "NodeReducer").andCallFake(function(v, e) {
return {
bucketNodes: function(toSort, numBuckets) {
return mockReducer.bucketNodes(toSort, numBuckets);
}
};
});
mockWrapper = {};
mockWrapper.call = function() {};
spyOn(window, "WebWorkerWrapper").andCallFake(function(c, cb) {
workerCB = cb;
return {
call: function() {
mockWrapper.call.apply(
mockWrapper,
Array.prototype.slice.call(arguments)
);
}
};
});
adapter = new AbstractAdapter(nodes, edges, descendant);
source = adapter.insertNode({_id: "1"});
target = adapter.insertNode({_id: "2"});
sourceid = source._id;
targetid = target._id;
});
it('should be informed if an edge is inserted', function() {
spyOn(mockWrapper, "call");
adapter.insertEdge({
_id: "1-2",
_from: sourceid,
_to: targetid
});
expect(mockWrapper.call).wasCalledWith("insertEdge", sourceid, targetid);
});
it('should be informed if an edge is removed', function() {
var toDelete = {
_id: "1-2",
_from: sourceid,
_to: targetid
},
edgeToDel = adapter.insertEdge(toDelete);
spyOn(mockWrapper, "call");
adapter.removeEdge(edgeToDel);
expect(mockWrapper.call).wasCalledWith("deleteEdge", sourceid, targetid);
});
it('should be informed if all edges for a node are removed', function() {
var toDelete1 = {
_id: "1-2",
_from: sourceid,
_to: targetid
},
toDelete2 = {
_id: "2-1",
_from: targetid,
_to: sourceid
};
adapter.insertEdge(toDelete1);
adapter.insertEdge(toDelete2);
spyOn(mockWrapper, "call");
adapter.removeEdgesForNode(source);
expect(mockWrapper.call).wasCalledWith("deleteEdge", sourceid, targetid);
expect(mockWrapper.call).wasCalledWith("deleteEdge", targetid, sourceid);
});
it('should remove all edges of a community if it is joined', function() {
var n1, n2, n3, n4,
e1, e2, e3, e4,
eout, ein;
n1 = {
_id: "n1"
};
n2 = {
_id: "n2"
};
n3 = {
_id: "n3"
};
n4 = {
_id: "n4"
};
e1 = {
_id: "n1-n2",
_from: n1._id,
_to: n2._id
};
e2 = {
_id: "n2-n3",
_from: n2._id,
_to: n3._id
};
e3 = {
_id: "n3-n4",
_from: n3._id,
_to: n4._id
};
e4 = {
_id: "n4-n1",
_from: n4._id,
_to: n1._id
};
eout = {
_id: "n1-1",
_from: n1._id,
_to: source._id
};
ein = {
_id: "2-n1",
_from: target._id,
_to: n1._id
};
adapter.insertNode(n1);
adapter.insertNode(n2);
adapter.insertNode(n3);
adapter.insertNode(n4);
adapter.insertEdge(e1);
adapter.insertEdge(e2);
adapter.insertEdge(e3);
adapter.insertEdge(e4);
adapter.insertEdge(eout);
adapter.insertEdge(ein);
spyOn(mockWrapper, "call").andCallFake(function(name) {
if (name === "getCommunity") {
workerCB({
data: {
cmd: name,
result: [n1._id, n2._id, n3._id, n4._id]
}
});
}
});
adapter.setNodeLimit(3);
expect(mockWrapper.call).wasCalledWith("deleteEdge", n1._id, n2._id);
expect(mockWrapper.call).wasCalledWith("deleteEdge", n2._id, n3._id);
expect(mockWrapper.call).wasCalledWith("deleteEdge", n3._id, n4._id);
expect(mockWrapper.call).wasCalledWith("deleteEdge", n4._id, n1._id);
expect(mockWrapper.call).wasCalledWith("deleteEdge", n1._id, source._id);
expect(mockWrapper.call).wasCalledWith("deleteEdge", target._id, n1._id);
// 1 time getCommunity, 7 times deleteEdge
expect(mockWrapper.call.calls.length).toEqual(7);
});
it('should not be informed of edges connected to communities', function() {
var n1, n2, n3,
e1, e2;
n1 = {
_id: "n1"
};
n2 = {
_id: "n2"
};
n3 = {
_id: "n3"
};
e1 = {
_id: "n1-n2",
_from: n1._id,
_to: n2._id
};
e2 = {
_id: "n2-n3",
_from: n2._id,
_to: n3._id
};
adapter.insertNode(n1);
adapter.insertNode(n2);
adapter.insertNode(n3);
adapter.insertEdge(e1);
spyOn(mockWrapper, "call").andCallFake(function(name) {
if (name === "getCommunity") {
workerCB({
data: {
cmd: name,
result: [n1._id, n2._id]
}
});
}
});
adapter.setNodeLimit(3);
adapter.insertEdge(e2);
expect(mockWrapper.call).not.wasCalledWith("insertEdge", n2._id, n3._id);
});
it('should be informed if a community is dissolved', function() {
var n1, n2, n3,
e1, e2;
n1 = {
_id: "n1"
};
n2 = {
_id: "n2"
};
n3 = {
_id: "n3"
};
e1 = {
_id: "n1-n2",
_from: n1._id,
_to: n2._id
};
e2 = {
_id: "n2-n3",
_from: n2._id,
_to: n3._id
};
adapter.insertNode(n1);
adapter.insertNode(n2);
adapter.insertNode(n3);
adapter.insertEdge(e1);
adapter.insertEdge(e2);
spyOn(mockWrapper, "call").andCallFake(function(name) {
if (name === "getCommunity") {
workerCB({
data: {
cmd: name,
result: [n1._id, n2._id, n3._id]
}
});
}
});
adapter.setNodeLimit(3);
expect(mockWrapper.call).wasCalledWith("deleteEdge", n1._id, n2._id);
expect(mockWrapper.call).wasCalledWith("deleteEdge", n2._id, n3._id);
adapter.setNodeLimit(100);
adapter.dissolveCommunity(getCommunityNodes()[0]);
expect(mockWrapper.call).wasCalledWith("insertEdge", n1._id, n2._id);
expect(mockWrapper.call).wasCalledWith("insertEdge", n2._id, n3._id);
});
it('should be informed to remove edges if nodes are added to a bucket', function() {
var centroid = {
_id: "center"
},
s1 = {
_id: "s_1"
},
s2 = {
_id: "s_2"
},
s3 = {
_id: "s_3"
},
s4 = {
_id: "s_4"
},
s5 = {
_id: "s_5"
},
s6 = {
_id: "s_6"
},
s7 = {
_id: "s_7"
},
s8 = {
_id: "s_8"
},
ec1 = {
_id: "c1",
_from: "center",
_to: "s_1"
},
ec2 = {
_id: "c2",
_from: "center",
_to: "s_2"
},
ec3 = {
_id: "c3",
_from: "center",
_to: "s_3"
},
ec4 = {
_id: "c4",
_from: "center",
_to: "s_4"
},
ec5 = {
_id: "c5",
_from: "center",
_to: "s_5"
},
ec6 = {
_id: "c6",
_from: "center",
_to: "s_6"
},
ec7 = {
_id: "c7",
_from: "center",
_to: "s_7"
},
ec8 = {
_id: "c8",
_from: "center",
_to: "s_8"
},
inserted = [s1, s2, s3, s4, s5, s6, s7, s8],
limit = 3;
spyOn(mockReducer, "bucketNodes").andCallFake(function() {
return [
{
reason: {
type: "similar",
example: s1
},
nodes: [s1, s2]
},
{
reason: {
type: "similar",
example: s3
},
nodes: [s3, s4, s5, s6, s7]
},
{
reason: {
type: "similar",
example: s8
},
nodes: [s8]
}
];
});
adapter.setChildLimit(limit);
adapter.insertNode(centroid);
adapter.insertNode(s1);
adapter.insertNode(s2);
adapter.insertNode(s3);
adapter.insertNode(s4);
adapter.insertNode(s5);
adapter.insertNode(s6);
adapter.insertNode(s7);
adapter.insertNode(s8);
adapter.insertEdge(ec1);
adapter.insertEdge(ec2);
adapter.insertEdge(ec3);
adapter.insertEdge(ec4);
adapter.insertEdge(ec5);
adapter.insertEdge(ec6);
adapter.insertEdge(ec7);
adapter.insertEdge(ec8);
spyOn(mockWrapper, "call");
adapter.checkSizeOfInserted(inserted);
expect(mockReducer.bucketNodes).wasCalledWith(inserted, limit);
expect(mockWrapper.call).toHaveBeenCalledWith("deleteEdge", "center", "s_1");
expect(mockWrapper.call).toHaveBeenCalledWith("deleteEdge", "center", "s_2");
expect(mockWrapper.call).toHaveBeenCalledWith("deleteEdge", "center", "s_3");
expect(mockWrapper.call).toHaveBeenCalledWith("deleteEdge", "center", "s_4");
expect(mockWrapper.call).toHaveBeenCalledWith("deleteEdge", "center", "s_5");
expect(mockWrapper.call).toHaveBeenCalledWith("deleteEdge", "center", "s_6");
expect(mockWrapper.call).toHaveBeenCalledWith("deleteEdge", "center", "s_7");
expect(mockWrapper.call.calls.length).toEqual(7);
});
it('should not be informed about edges targeting at communities', function() {
var centroid = {
_id: "center"
},
s1 = {
_id: "s_1"
},
s2 = {
_id: "s_2"
},
ec1 = {
_id: "c1",
_from: "center",
_to: "s_1"
},
ec2 = {
_id: "c2",
_from: "center",
_to: "s_2"
},
comSource = {
_id: "comsource",
_from: "s_1",
_to: "1"
},
comTarget = {
_id: "comtarget",
_from: "1",
_to: "s_1"
},
inserted = [s1, s2],
limit = 1;
spyOn(mockReducer, "bucketNodes").andCallFake(function() {
return [
{
reason: {
type: "similar",
example: s1
},
nodes: [s1, s2]
}
];
});
adapter.setChildLimit(limit);
adapter.insertNode(centroid);
adapter.insertNode(s1);
adapter.insertNode(s2);
adapter.insertEdge(ec1);
adapter.insertEdge(ec2);
adapter.checkSizeOfInserted(inserted);
expect(mockReducer.bucketNodes).wasCalledWith(inserted, limit);
spyOn(mockWrapper, "call");
adapter.insertEdge(comSource);
adapter.insertEdge(comTarget);
expect(mockWrapper.call).wasNotCalled();
});
it('should never be informed about edges concerning communities', function() {
var fakeData, n1, n2, n3, n4, e1, e2, e3, comm;
adapter.removeNode(source);
adapter.removeNode(target);
expect(nodes.length).toEqual(0);
fakeData = [1, 2];
spyOn(mockWrapper, "call").andCallFake(function(name) {
if (name === "getCommunity") {
workerCB({
data: {
cmd: name,
result: fakeData
}
});
}
});
n1 = adapter.insertNode({_id: 1});
n2 = adapter.insertNode({_id: 2});
n3 = adapter.insertNode({_id: 3});
n4 = adapter.insertNode({_id: 4});
e1 = adapter.insertEdge({
_id: "1-2",
_from: 1,
_to: 2
});
e2 = adapter.insertEdge({
_id: "2-3",
_from: 2,
_to: 3
});
e3 = adapter.insertEdge({
_id: "3-1",
_from: 3,
_to: 1
});
expect(mockWrapper.call).wasCalledWith("insertEdge", 1, 2);
expect(mockWrapper.call).wasCalledWith("insertEdge", 2, 3);
expect(mockWrapper.call).wasCalledWith("insertEdge", 3, 1);
expect(mockWrapper.call.calls.length).toEqual(3);
adapter.setNodeLimit(3);
comm = getCommunityNodes()[0];
expect(mockWrapper.call).wasCalledWith("getCommunity", 3);
expect(mockWrapper.call).wasCalledWith("deleteEdge", 1, 2);
expect(mockWrapper.call).wasCalledWith("deleteEdge", 2, 3);
expect(mockWrapper.call).wasCalledWith("deleteEdge", 3, 1);
expect(mockWrapper.call.calls.length).toEqual(7);
fakeData = [3, 4];
adapter.setNodeLimit(2);
expect(mockWrapper.call).wasCalledWith("getCommunity", 2);
expect(mockWrapper.call.calls.length).toEqual(8);
});
it('should be informed properly if a community is removed during collapsing', function() {
runs(function() {
var c0 = {
_id: "0"
},
internal = {
_id: "internal"
},
internal2 = {
_id: "internal2"
},
c1 = {
_id: "1"
},
c2 = {
_id: "2"
},
e0 = {
_id: "0-1",
_from: "0",
_to: "1"
},
e1 = {
_id: "1-c",
_from: "1",
_to: "internal"
},
e2 = {
_id: "c-2",
_from: "internal",
_to: "2"
},
commNode;
spyOn(mockWrapper, "call").andCallFake(function(name) {
workerCB({
data: {
cmd: name,
result: ["internal", "internal2"]
}
});
});
adapter.insertNode(c0);
c1 = adapter.insertNode(c1);
c1._expanded = true;
adapter.insertNode(internal);
adapter.insertNode(internal2);
adapter.insertNode(c2);
adapter.insertEdge(e0);
adapter.insertEdge(e1);
adapter.insertEdge(e2);
expect(mockWrapper.call).wasCalledWith("insertEdge", e0._from, e0._to);
expect(mockWrapper.call).wasCalledWith("insertEdge", e1._from, e1._to);
expect(mockWrapper.call).wasCalledWith("insertEdge", e2._from, e2._to);
expect(mockWrapper.call.calls.length).toEqual(3);
adapter.setNodeLimit(3);
expect(mockWrapper.call).wasCalledWith("getCommunity", 3);
expect(mockWrapper.call).wasCalledWith("deleteEdge", e1._from, e1._to);
expect(mockWrapper.call).wasCalledWith("deleteEdge", e2._from, e2._to);
expect(mockWrapper.call.calls.length).toEqual(6);
adapter.explore(c1);
expect(mockWrapper.call.calls.length).toEqual(6);
});
});
it('should be informed if a node is explored, collapsed and explored again', function() {
var id1 = "1",
id2 = "2",
id3 = "3",
id4 = "4",
id5 = "5",
id6 = "6",
ids = "start",
n1 = {_id: id1},
n2 = {_id: id2},
n3 = {_id: id3},
n4 = {_id: id4},
n5 = {_id: id5},
n6 = {_id: id6},
ns = {_id: ids},
intS,
int1,
int2,
int3,
int4,
int5,
int6,
es1 = {
_id: ids + "-" + id1,
_from: ids,
_to: id1
},
es2 = {
_id: ids + "-" + id2,
_from: ids,
_to: id2
},
es3 = {
_id: ids + "-" + id3,
_from: ids,
_to: id3
},
es4 = {
_id: ids + "-" + id4,
_from: ids,
_to: id4
},
es5 = {
_id: ids + "-" + id5,
_from: ids,
_to: id5
},
es6 = {
_id: ids + "-" + id6,
_from: ids,
_to: id6
};
spyOn(mockWrapper, "call");
spyOn(mockReducer, "bucketNodes").andCallFake(function(list) {
return [
{
reason: {
type: "similar"
},
nodes: [int1, int2, int3]
},
{
reason: {
type: "similar"
},
nodes: [int4, int5, int6]
}
];
});
spyOn(descendant, "loadNode").andCallFake(function() {
var inserted = {};
int1 = adapter.insertNode(n1);
int2 = adapter.insertNode(n2);
int3 = adapter.insertNode(n3);
int4 = adapter.insertNode(n4);
int5 = adapter.insertNode(n5);
int6 = adapter.insertNode(n6);
inserted.id1 = int1;
inserted.id2 = int2;
inserted.id3 = int3;
inserted.id4 = int4;
inserted.id5 = int5;
inserted.id6 = int6;
adapter.insertEdge(es1);
adapter.insertEdge(es2);
adapter.insertEdge(es3);
adapter.insertEdge(es4);
adapter.insertEdge(es5);
adapter.insertEdge(es6);
expect(mockWrapper.call).wasCalledWith("insertEdge", ids, id1);
expect(mockWrapper.call).wasCalledWith("insertEdge", ids, id2);
expect(mockWrapper.call).wasCalledWith("insertEdge", ids, id3);
expect(mockWrapper.call).wasCalledWith("insertEdge", ids, id4);
expect(mockWrapper.call).wasCalledWith("insertEdge", ids, id5);
expect(mockWrapper.call).wasCalledWith("insertEdge", ids, id6);
expect(mockWrapper.call.calls.length).toEqual(6);
mockWrapper.call.calls.length = 0;
adapter.checkSizeOfInserted(inserted);
expect(mockWrapper.call).wasCalledWith("deleteEdge", ids, id1);
expect(mockWrapper.call).wasCalledWith("deleteEdge", ids, id2);
expect(mockWrapper.call).wasCalledWith("deleteEdge", ids, id3);
expect(mockWrapper.call).wasCalledWith("deleteEdge", ids, id4);
expect(mockWrapper.call).wasCalledWith("deleteEdge", ids, id5);
expect(mockWrapper.call).wasCalledWith("deleteEdge", ids, id6);
expect(mockWrapper.call.calls.length).toEqual(6);
mockWrapper.call.calls.length = 0;
});
adapter.setChildLimit(2);
intS = adapter.insertNode(ns);
expect(mockWrapper.call.calls.length).toEqual(0);
adapter.explore(intS);
expect(edges.length).toEqual(6);
adapter.explore(intS);
expect(edges.length).toEqual(0);
expect(mockWrapper.call.calls.length).toEqual(0);
mockWrapper.call.calls.length = 0;
adapter.explore(intS);
expect(edges.length).toEqual(6);
});
it('should be informed properly about propagating'
+ ' a collapse through a community', function() {
var id1 = "1",
id2 = "2",
id3 = "3",
id4 = "4",
id5 = "5",
ids = "start",
n1 = {_id: id1},
n2 = {_id: id2},
n3 = {_id: id3},
n4 = {_id: id4},
n5 = {_id: id5},
ns = {_id: ids},
intS,
int1,
int2,
int3,
int4,
int5,
es1 = {
_id: ids + "-" + id1,
_from: ids,
_to: id1
},
es2 = {
_id: ids + "-" + id2,
_from: ids,
_to: id2
},
e13 = {
_id: id1 + "-" + id3,
_from: id1,
_to: id3
},
e24 = {
_id: id2 + "-" + id4,
_from: id2,
_to: id4
},
e35 = {
_id: id3 + "-" + id5,
_from: id3,
_to: id5
};
spyOn(mockWrapper, "call").andCallFake(function(name) {
if (name === "getCommunity") {
workerCB({
data: {
cmd: name,
result: [id2, id3]
}
});
}
});
spyOn(descendant, "loadNode").andCallFake(function(n) {
if (n === ids) {
int1 = adapter.insertNode(n1);
int2 = adapter.insertNode(n2);
adapter.insertEdge(es1);
adapter.insertEdge(es2);
expect(mockWrapper.call).wasCalledWith("insertEdge", ids, id1);
expect(mockWrapper.call).wasCalledWith("insertEdge", ids, id2);
expect(mockWrapper.call.calls.length).toEqual(2);
mockWrapper.call.calls.length = 0;
return;
}
if (n === id1) {
int3 = adapter.insertNode(n3);
adapter.insertEdge(e13);
expect(mockWrapper.call).wasCalledWith("insertEdge", id1, id3);
expect(mockWrapper.call.calls.length).toEqual(1);
mockWrapper.call.calls.length = 0;
return;
}
if (n === id2) {
int4 = adapter.insertNode(n4);
adapter.insertEdge(e24);
expect(mockWrapper.call).wasCalledWith("insertEdge", id2, id4);
expect(mockWrapper.call.calls.length).toEqual(1);
mockWrapper.call.calls.length = 0;
return;
}
if (n === id3) {
int5 = adapter.insertNode(n5);
adapter.insertEdge(e35);
expect(mockWrapper.call).wasCalledWith("insertEdge", id3, id5);
expect(mockWrapper.call.calls.length).toEqual(1);
mockWrapper.call.calls.length = 0;
return;
}
});
adapter.setChildLimit(2);
intS = adapter.insertNode(ns);
adapter.explore(intS);
adapter.explore(int1);
adapter.explore(int2);
adapter.explore(int3);
adapter.setNodeLimit(5);
expect(mockWrapper.call).wasCalledWith("getCommunity", 5);
expect(mockWrapper.call).wasCalledWith("deleteEdge", ids, id2);
expect(mockWrapper.call).wasCalledWith("deleteEdge", id1, id3);
expect(mockWrapper.call).wasCalledWith("deleteEdge", id2, id4);
expect(mockWrapper.call).wasCalledWith("deleteEdge", id3, id5);
expect(mockWrapper.call.calls.length).toEqual(5);
mockWrapper.call.calls.length = 0;
expect(int1._expanded).toBeTruthy();
adapter.explore(int1);
expect(int1._expanded).toBeFalsy();
expect(mockWrapper.call.calls.length).toEqual(0);
});
});
describe('checking many child nodes', function() {
var adapter, mockReducer;
beforeEach(function() {
mockReducer = {};
mockReducer.getPrioList = function() {};
mockReducer.changePrioList = function() {};
mockReducer.bucketNodes = function() {};
spyOn(window, "NodeReducer").andCallFake(function(v, e) {
return {
bucketNodes: function(toSort, numBuckets) {
return mockReducer.bucketNodes(toSort, numBuckets);
},
changePrioList: function(list) {
return mockReducer.changePrioList(list);
},
getPrioList: function() {
return mockReducer.getPrioList();
}
};
});
adapter = new AbstractAdapter(nodes, edges, descendant);
});
it('should be able to change the reducer to a new prioList', function() {
spyOn(mockReducer,"changePrioList");
var list = ["a", "b", "c"],
config = {
prioList: list
};
adapter.changeTo(config);
expect(mockReducer.changePrioList).wasCalledWith(list);
});
it('should be able to return the current prioList', function() {
spyOn(mockReducer,"getPrioList");
adapter.getPrioList();
expect(mockReducer.getPrioList).wasCalled();
});
it('should not take any action if the limit is high enough', function() {
adapter.setChildLimit(5);
spyOn(mockReducer, "bucketNodes");
var n1, n2, n3, n4, n5,
inserted = {};
n1 = adapter.insertNode({_id: 1 });
n2 = adapter.insertNode({_id: 2 });
n3 = adapter.insertNode({_id: 3 });
n4 = adapter.insertNode({_id: 4 });
n5 = adapter.insertNode({_id: 5 });
_.each(nodes, function(n) {
inserted[n._id] = n;
});
adapter.checkSizeOfInserted(inserted);
expect(mockReducer.bucketNodes).wasNotCalled();
});
it('should bucket nodes if limit is to small', function() {
var n1, n2, n3, n4, n5,
inserted = [],
limit = 2;
spyOn(mockReducer, "bucketNodes").andCallFake(function() {
return [
{
reason: {
type: "similar",
example: n1
},
nodes: [n1, n2]
},
{
reason: {
type: "similar",
example: n3
},
nodes: [n3, n4, n5]
}
];
});
adapter.setChildLimit(limit);
n1 = adapter.insertNode({_id: "1" });
n2 = adapter.insertNode({_id: "2" });
n3 = adapter.insertNode({_id: "3" });
n4 = adapter.insertNode({_id: "4" });
n5 = adapter.insertNode({_id: "5" });
_.each(nodes, function(n) {
inserted.push(n);
});
adapter.checkSizeOfInserted(inserted);
expect(mockReducer.bucketNodes).wasCalledWith(inserted, limit);
expect(nodes.length).toEqual(2);
expect(getCommunityNodes().length).toEqual(2);
notExistNodes(["1", "2", "3", "4", "5"]);
});
it('should not display single nodes as buckets', function() {
var n1, n2, n3, n4, n5,
inserted = [],
limit = 3;
spyOn(mockReducer, "bucketNodes").andCallFake(function() {
return [
{
reason: {
type: "similar",
example: n1
},
nodes: [n1]
},
{
reason: {
type: "similar",
example: n3
},
nodes: [n3, n4, n5]
},
{
reason: {
type: "similar",
example: n2
},
nodes: [n2]
}
];
});
adapter.setChildLimit(limit);
n1 = adapter.insertNode({_id: "1" });
n2 = adapter.insertNode({_id: "2" });
n3 = adapter.insertNode({_id: "3" });
n4 = adapter.insertNode({_id: "4" });
n5 = adapter.insertNode({_id: "5" });
_.each(nodes, function(n) {
inserted.push(n);
});
adapter.checkSizeOfInserted(inserted);
expect(mockReducer.bucketNodes).wasCalledWith(inserted, limit);
expect(nodes.length).toEqual(3);
expect(getCommunityNodes().length).toEqual(1);
notExistNodes(["3", "4", "5"]);
existNodes(["1", "2"]);
});
it('should display the reason why a community has been joined', function() {
var n1, n2, n3, n4, n5,
com1, com2,
inserted = [],
limit = 3;
spyOn(mockReducer, "bucketNodes").andCallFake(function() {
return [
{
reason: {
type: "similar",
example: n1
},
nodes: [n1, n2]
},
{
reason: {
key: "type",
value: "example"
},
nodes: [n3, n4, n5]
}
];
});
adapter.setChildLimit(limit);
n1 = adapter.insertNode({_id: "1" });
n2 = adapter.insertNode({_id: "2" });
n3 = adapter.insertNode({_id: "3" });
n4 = adapter.insertNode({_id: "4" });
n5 = adapter.insertNode({_id: "5" });
_.each(nodes, function(n) {
inserted.push(n);
});
adapter.checkSizeOfInserted(inserted);
expect(mockReducer.bucketNodes).wasCalledWith(inserted, limit);
expect(nodes.length).toEqual(2);
expect(getCommunityNodes().length).toEqual(2);
notExistNodes(["1", "2", "3", "4", "5"]);
_.each(getCommunityNodes(), function(c) {
if (c._size === 2) {
com1 = c;
return;
}
if (c._size === 3) {
com2 = c;
return;
}
// Should never be reached
expect(true).toBeFalsy();
});
expect(com1._reason).toEqual({
type: "similar",
example: n1
});
expect(com2._reason).toEqual({
key: "type",
value: "example"
});
});
});
});
}());