1
0
Fork 0

Created Spec for Eventlibrary, and test for Expand-Event

This commit is contained in:
Michael Hackstein 2013-03-15 14:17:20 +01:00
parent 026e91f317
commit 5736974aa8
7 changed files with 202 additions and 385 deletions

View File

@ -1,4 +1,5 @@
/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true */
/*global _*/
/* global eventLibrary */
////////////////////////////////////////////////////////////////////////////////
@ -28,7 +29,9 @@
/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
// Example onclick = new eventLibrary.Expand(edges, nodes, start, adapter.loadNode, nodeShaper.reshapeNode)
// Example onclick = new eventLibrary.Expand(
// edges, nodes, start,
// adapter.loadNode, nodeShaper.reshapeNode)
function EventLibrary() {
this.Expand = function (edges, nodes, startCallback, loadNode, reshapeNode) {
if (edges === undefined) {
@ -64,8 +67,8 @@ function EventLibrary() {
// Helper function to easily remove all outbound edges for one node
removeOutboundEdgesFromNode = function ( node ) {
if (node._outboundCounter > 0) {
var subNodes = [];
var i;
var subNodes = [],
i;
for ( i = 0; i < edges.length; i++ ) {
if ( edges[i].source === node ) {
subNodes.push(edges[i].target);

View File

@ -3,12 +3,13 @@
<body id="jasminetestlinks" onload="">
<ul>
<li><a href="runnerAll.html">All</a></li>
<li><a href="runnerGraphViewer.html">Graph Viewer</a></li>
<li><a href="runnerEdgeShaper.html">Edge Shaper</a></li>
<li><a href="runnerNodeShaper.html">Node Shaper</a></li>
<li><a href="runnerClickExpander.html">Click Expander</a></li>
<li><a href="runnerForceLayouter.html">Force-Based Layout</a></li>
<li><a href="runnerJSONAdapter.html">JSON Adapter</a></li>
<li><a href="runnerArangoAdapter.html">Arango Adapter</a></li>
<li><a href="runnerEventLibrary.html">Event Library</a></li>
</ul>
</body>

View File

@ -15,12 +15,13 @@
<script type="text/javascript" src="../../lib/underscore.js"></script>
<script type="text/javascript" src="../../lib/jquery-1.8.3.js"></script>
<script type="text/javascript" src="../../lib/jquery.livequery.js"></script>
<script type="text/javascript" src="../clickExpander.js"></script>
<script type="text/javascript" src="../graphViewer.js"></script>
<script type="text/javascript" src="../graph/nodeShaper.js"></script>
<script type="text/javascript" src="../graph/jsonAdapter.js"></script>
<script type="text/javascript" src="../graph/arangoAdapter.js"></script>
<script type="text/javascript" src="../graph/edgeShaper.js"></script>
<script type="text/javascript" src="../graph/forceLayouter.js"></script>
<script type="text/javascript" src="../graph/eventLibrary.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="specGraphViewer/graphViewerSpec.js"></script>
@ -29,7 +30,7 @@
<script type="text/javascript" src="specNodeShaper/nodeShaperSpec.js"></script>
<script type="text/javascript" src="specEdgeShaper/edgeShaperSpec.js"></script>
<script type="text/javascript" src="specForceLayouter/forceLayouterSpec.js"></script>
<script type="text/javascript" src="specEventLibrary/eventLibrarySpec.js"></script>
<!-- run JSLINT -->
<script type="text/javascript" src="specJSLint/jsLintSpec.js"></script>

View File

@ -0,0 +1,63 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Jasmine Test Arango Adapter</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-1.3.1/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="lib/jasmine-1.3.1/jasmine.css">
<script type="text/javascript" src="lib/jasmine-1.3.1/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-1.3.1/jasmine-html.js"></script>
<script type="text/javascript" src="lib/jslint.js"></script>
<!-- include source files here... -->
<script type="text/javascript" src="../../lib/d3.v3.min.js"></script>
<script type="text/javascript" src="../../lib/underscore.js"></script>
<script type="text/javascript" src="../../lib/jquery-1.8.3.js"></script>
<script type="text/javascript" src="../../lib/jquery.livequery.js"></script>
<script type="text/javascript" src="../graph/eventLibrary.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="specEventLibrary/eventLibrarySpec.js"></script>
<!-- run JSLINT -->
<script type="text/javascript" src="specJSLint/jsLintSpec.js"></script>
<script type="text/javascript">
(function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.specFilter = function(spec) {
return htmlReporter.specFilter(spec);
};
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
execJasmine();
};
function execJasmine() {
jasmineEnv.execute();
}
})();
</script>
</head>
<body>
<h1>
<a href="jasmineTestLinks.html">Back to List</a>
</h1>
</body>
</html>

View File

@ -3,7 +3,6 @@
/*global describe, it, expect */
/*global runs, spyOn, waitsFor */
/*global window, eb, loadFixtures, document */
/*global $, _, d3*/
/*global EventLibrary*/
////////////////////////////////////////////////////////////////////////////////
@ -39,395 +38,142 @@
describe('Event Library', function () {
describe('Node Expander', function() {
beforeEach(function() {
var
nodes = [],
edges = [],
var expandEvent =
$('#foo').on('click', function() {
alert($(this).text());
});
$('#foo').trigger('click');
});
});
var layouter,
nodes,
width,
height,
offset,
linkDistance,
gravity,
standardConfig,
edgeShaper,
createNodeList = function(amount) {
var i,
nodes = [];
for (i = 0; i < amount; i++) {
nodes.push({"id": i});
}
return nodes;
},
timeOutTest = function() {
var startTime;
runs(function() {
spyOn(layouter, 'stop').andCallThrough();
startTime = (new Date()).getTime();
layouter.start();
});
waitsFor(function() {
return layouter.stop.calls.length > 0;
}, "layouter should have been stopped", 2000);
runs(function() {
// List test if not time-outed
var endTime = (new Date()).getTime(),
duration = endTime - startTime;
expect(duration).toBeInATimeCategory();
});
},
positioningTest = function() {
runs(function() {
spyOn(layouter, 'stop').andCallThrough();
layouter.start();
});
waitsFor(function() {
return layouter.stop.calls.length > 0;
}, "layouter should have been stopped", 2000);
runs(function() {
expect(nodes).toNotBeOffScreen();
});
},
dummyNodeShaper = {
"updateNodes": function() {
var changeDist = 0;
_.each(nodes, function(d) {
changeDist += Math.abs(d.px - d.x) + Math.abs(d.py - d.y);
});
return changeDist;
}
};
var eventLib;
beforeEach(function() {
width = 940;
height = 640;
offset = 10;
linkDistance = 100;
gravity = 0.5;
standardConfig = {
"nodes": [],
"links": [],
"width": width,
"height": height,
"gravity": gravity,
"distance": linkDistance
};
this.addMatchers({
toBeInATimeCategory: function() {
var duration = this.actual;
this.message = function(){
layouter.stop();
if (duration < 100) {
return "terminates super fast (0.1 s)";
}
if (duration < 1000) {
return "terminates fast (1 s)";
}
if (duration < 2000) {
return "terminates quite fast (2 s)";
}
if (duration < 5000) {
return "terminates in reasonable time (5 s)";
}
if (duration < 10000) {
return "terminates in acceptable time (10 s)";
}
return "does not terminate in acceptable time";
};
return duration < 10000;
},
toBeCloseToNode: function (n2, threshold) {
var n1 = this.actual,
xdis = n1.x - n2.x,
ydis = n1.y - n2.y,
distance = Math.sqrt(xdis*xdis + ydis*ydis);
this.message = function() {
return "Node " + n1.id
+ " should be close to Node " + n2.id
+ " but distance is " + distance;
};
threshold = threshold || 100;
return Math.abs(distance) < threshold;
},
toBeDistantToNode: function (n2, threshold) {
var n1 = this.actual,
xdis = n1.x - n2.x,
ydis = n1.y - n2.y,
distance = Math.sqrt(xdis*xdis + ydis*ydis);
this.message = function() {
if (distance - linkDistance < 0) {
return "Node " + n1.id
+ " should be distant from Node " + n2.id
+ " but distance is to short (" + distance + ")";
}
return "Node " + n1.id
+ " should be distant from Node " + n2.id
+ " but distance is to long (" + distance + ")";
};
threshold = threshold || 100;
return Math.abs(distance - linkDistance) < threshold;
},
toNotBeOffScreen: function () {
var minx = Number.MAX_VALUE,
miny = Number.MAX_VALUE,
maxx = Number.MIN_VALUE,
maxy = Number.MIN_VALUE,
nodes = this.actual;
_.each(nodes, function(node) {
minx = Math.min(minx, node.x);
miny = Math.min(miny, node.y);
maxx = Math.max(maxx, node.x);
maxy = Math.max(maxy, node.y);
});
this.message = function () {
var msg = "Errors: \n";
if (minx < offset) {
msg += "Minimal x: " + minx + " < " + offset + ", ";
}
if (maxx > width - offset) {
msg += "Maximal x: " + maxx + " > " + (width - offset) + ", ";
}
if (miny > offset) {
msg += "Minimal y: " + miny + " < " + offset + " ,";
}
if (maxy > height - offset) {
msg += "Maximal y: " + maxy + " > " + (height - offset);
}
return msg;
};
return minx > offset
&& maxx < width - offset
&& miny > offset
&& maxy < height - offset;
}
});
eventLib = new EventLibrary();
});
it('should position the first node in the centre', function() {
runs(function() {
standardConfig.nodes = createNodeList(1);
nodes = standardConfig.nodes;
edgeShaper = {"updateEdges": function(){}};
layouter = new ForceLayouter(standardConfig);
layouter.setCombinedUpdateFunction(dummyNodeShaper, edgeShaper);
spyOn(layouter, 'stop').andCallThrough();
layouter.start();
describe('Expand', function() {
var loaded,
reshaped,
nodes,
edges,
loadedNodes,
reshapedNodes,
started,
loadNodeCallback = function(node) {
loaded++;
loadedNodes.push(node);
},
reshapeNodeCallback = function(node) {
reshaped++;
reshapedNodes.push(node);
},
startCallback = function() {
started++;
},
testee;
beforeEach(function() {
loaded = 0;
reshaped = 0;
started = 0;
nodes = [];
edges = [];
loadedNodes = [];
reshapedNodes = [];
});
waitsFor(function() {
return layouter.stop.calls.length > 0;
}, "force should have been stopped", 10000);
runs(function() {
var center = {
"id": "center",
"x": width/2,
"y": height/2
it('should expand a collapsed node', function() {
var node = {
id: 0,
_outboundCounter: 0,
_inboundCounter: 0
};
expect(nodes[0]).toBeCloseToNode(center);
});
});
it('should position not linked nodes close to each other', function() {
runs(function() {
nodes = createNodeList(4);
standardConfig.nodes = nodes;
edgeShaper = {"updateEdges": function(){}};
layouter = new ForceLayouter(standardConfig);
layouter.setCombinedUpdateFunction(dummyNodeShaper, edgeShaper);
spyOn(layouter, 'stop').andCallThrough();
layouter.start();
});
waitsFor(function() {
return layouter.stop.calls.length > 0;
}, "force should have been stopped", 10000);
nodes.push(node);
testee = eventLib.Expand(
edges,
nodes,
startCallback,
loadNodeCallback,
reshapeNodeCallback
);
testee(node);
runs(function() {
expect(nodes[0]).toBeCloseToNode(nodes[1]);
expect(nodes[0]).toBeCloseToNode(nodes[2]);
expect(nodes[0]).toBeCloseToNode(nodes[3]);
expect(nodes[1]).toBeCloseToNode(nodes[2]);
expect(nodes[1]).toBeCloseToNode(nodes[3]);
expect(nodes[2]).toBeCloseToNode(nodes[3]);
});
});
it('should keep distance between linked nodes', function() {
runs(function() {
nodes = createNodeList(4);
standardConfig.nodes = nodes;
standardConfig.links = [
{"source": nodes[0], "target": nodes[1]},
{"source": nodes[0], "target": nodes[2]},
{"source": nodes[0], "target": nodes[3]},
{"source": nodes[1], "target": nodes[3]},
{"source": nodes[2], "target": nodes[3]}
];
edgeShaper = {"updateEdges": function(){}};
layouter = new ForceLayouter(standardConfig);
layouter.setCombinedUpdateFunction(dummyNodeShaper, edgeShaper);
spyOn(layouter, 'stop').andCallThrough();
layouter.start();
});
waitsFor(function() {
return layouter.stop.calls.length > 0;
}, "force should have been stopped", 10000);
runs(function() {
expect(nodes[0]).toBeDistantToNode(nodes[1]);
expect(nodes[0]).toBeDistantToNode(nodes[2]);
expect(nodes[0]).toBeDistantToNode(nodes[3]);
expect(nodes[1]).toBeDistantToNode(nodes[3]);
expect(nodes[2]).toBeDistantToNode(nodes[3]);
});
});
it('should throw an error if nodes are not defined', function() {
expect(function() {
var tmp = new ForceLayouter({"links": []});
}).toThrow("No nodes defined");
expect(function() {
var tmp = new ForceLayouter({"nodes": [],"links": []});
}).not.toThrow("No nodes defined");
});
it('should throw an error if links are not defined', function() {
expect(function() {
var tmp = new ForceLayouter({"nodes": []});
}).toThrow("No links defined");
expect(function() {
var tmp = new ForceLayouter({"nodes": [],"links": []});
}).not.toThrow("No links defined");
});
describe('tested under normal conditions (50 nodes)', function() {
beforeEach(function() {
nodes = createNodeList(50);
standardConfig.nodes = nodes;
edgeShaper = {"updateEdges": function(){}};
layouter = new ForceLayouter(standardConfig);
layouter.setCombinedUpdateFunction(dummyNodeShaper, edgeShaper);
expect(node._expanded).toBeTruthy();
expect(started).toEqual(1);
expect(reshaped).toEqual(1);
expect(loaded).toEqual(1);
expect(reshapedNodes.length).toEqual(1);
expect(reshapedNodes[0]).toEqual(node);
expect(loadedNodes.length).toEqual(1);
expect(loadedNodes[0]).toEqual(node.id);
});
it('should not position a node offscreen', function() {
positioningTest();
});
it('should terminate', function() {
timeOutTest();
});
});
describe('tested under heavy weight conditions (500 nodes)', function() {
beforeEach(function() {
nodes = createNodeList(500);
standardConfig.nodes = nodes;
edgeShaper = {"updateEdges": function(){}};
layouter = new ForceLayouter(standardConfig);
layouter.setCombinedUpdateFunction(dummyNodeShaper, edgeShaper);
it('should collapse an expanded node', function() {
var node = {
id: 0,
_expanded: true,
_outboundCounter: 0,
_inboundCounter: 0
};
nodes.push(node);
testee = eventLib.Expand(
edges,
nodes,
startCallback,
loadNodeCallback,
reshapeNodeCallback
);
testee(node);
expect(node._expanded).toBeFalsy();
expect(started).toEqual(1);
expect(reshaped).toEqual(1);
expect(loaded).toEqual(0);
expect(reshapedNodes.length).toEqual(1);
expect(reshapedNodes[0]).toEqual(node);
});
it('should not position a node offscreen', function() {
positioningTest();
});
it('should terminate', function() {
timeOutTest();
});
});
/*
describe('tested under evil stress (5000 nodes)', function() {
beforeEach(function() {
nodes = createNodeList(5000);
standardConfig.nodes = nodes;
edgeShaper = {"updateEdges": function(){}};
layouter = new ForceLayouter(standardConfig);
layouter.setCombinedUpdateFunction(dummyNodeShaper, edgeShaper);
it('should collapse a tree', function() {
var root = {
id: 0,
_expanded: true,
_outboundCounter: 2,
_inboundCounter: 0
},
c1 = {
id: 1,
_outboundCounter: 0,
_inboundCounter: 1
},
c2 = {
id: 2,
_outboundCounter: 0,
_inboundCounter: 1
};
});
it('should not position a node offscreen', function() {
positioningTest();
});
it('should terminate', function() {
timeOutTest();
});
});
*/
/*
describe('tested by the devil himself (50000 nodes)', function() {
beforeEach(function() {
nodes = createNodeList(50000);
standardConfig.nodes = nodes;
edgeShaper = {"updateEdges": function(){}};
layouter = new ForceLayouter(standardConfig);
layouter.setCombinedUpdateFunction(dummyNodeShaper, edgeShaper);
nodes.push(root);
nodes.push(c1);
nodes.push(c2);
edges.push({source: root, target: c1});
edges.push({source: root, target: c2});
});
it('should not position a node offscreen', function() {
positioningTest();
});
it('should terminate', function() {
timeOutTest();
testee = eventLib.Expand(
edges,
nodes,
startCallback,
loadNodeCallback,
reshapeNodeCallback
);
testee(root);
expect(root._expanded).toBeFalsy();
expect(started).toEqual(1);
expect(reshaped).toEqual(1);
expect(loaded).toEqual(0);
expect(nodes.length).toEqual(1);
expect(edges.length).toEqual(0);
expect(reshapedNodes.length).toEqual(1);
expect(reshapedNodes[0]).toEqual(root);
});
});
*/
});
}());

View File

@ -4,7 +4,7 @@
/*global waitsFor, runs */
/*global window, eb, loadFixtures, document */
/*global $, _, d3*/
/*global ClickExpander*/
/*global GraphViewer*/
////////////////////////////////////////////////////////////////////////////////
/// @brief Graph functionality
@ -34,12 +34,12 @@
////////////////////////////////////////////////////////////////////////////////
describe("click Expander", function() {
describe("Graph Viewer", function() {
"use strict";
var expander,
var viewer,
svg,
docSVG,
/*
nodeWithID = function(id) {
return $.grep(expander.nodes, function(e){
return e.id === id;
@ -84,7 +84,7 @@ describe("click Expander", function() {
notExistNodes = function(ids) {
_.each(ids, notExistNode);
},
*/
displayNode = function(id) {
expect($("svg #" + id)[0]).toBeDefined();
},
@ -122,6 +122,9 @@ describe("click Expander", function() {
docSVG = document.createElement("svg");
document.body.appendChild(docSVG);
svg = d3.select("svg");
expander = new ClickExpander("../generated_1000/", svg, 980, 640, 1);
});

View File

@ -75,7 +75,7 @@
edges.insertEdge = function(source, target) {
this.push({source: source, target: target});
};
startNode = 477;
startNode = 0;
adapter = new JSONAdapter(jsonPath, nodes, edges);
});
@ -94,7 +94,7 @@
});
runs(function() {
existNodes([477, 29, 159, 213, 339]);
existNodes([0, 1, 2, 3, 4]);
expect(nodes.length).toEqual(5);
});
});