diff --git a/html/admin/js/graphViewer/graph/abstractAdapter.js b/html/admin/js/graphViewer/graph/abstractAdapter.js index c382d44a03..20ec6e0889 100644 --- a/html/admin/js/graphViewer/graph/abstractAdapter.js +++ b/html/admin/js/graphViewer/graph/abstractAdapter.js @@ -124,10 +124,10 @@ function AbstractAdapter(nodes, edges) { source = findNode(data._from); target = findNode(data._to); if (!source) { - throw "Unable to insert Edge, source node not existing " + edge._from; + throw "Unable to insert Edge, source node not existing " + data._from; } if (!target) { - throw "Unable to insert Edge, target node not existing " + edge._to; + throw "Unable to insert Edge, target node not existing " + data._to; } edge.source = source; edge.target = target; @@ -323,9 +323,8 @@ function AbstractAdapter(nodes, edges) { }, checkSizeOfInserted = function (inserted) { - var buckets; if (_.size(inserted) > childLimit) { - buckets = reducer.bucketNodes(_.values(inserted), childLimit); + var buckets = reducer.bucketNodes(_.values(inserted), childLimit); _.each(buckets, function(b) { if (b.length > 1) { var ids = _.map(b, function(n) { diff --git a/html/admin/js/graphViewer/graph/arangoAdapter.js b/html/admin/js/graphViewer/graph/arangoAdapter.js index 0f0338e741..a6b42e5084 100644 --- a/html/admin/js/graphViewer/graph/arangoAdapter.js +++ b/html/admin/js/graphViewer/graph/arangoAdapter.js @@ -367,7 +367,7 @@ function ArangoAdapter(nodes, edges, config) { processData: false, success: function() { absAdapter.removeEdgesForNode(nodeToRemove); - permanentlyRemoveEdgesOfNode(nodeToRemove._id); + permanentlyRemoveEdgesOfNode(nodeToRemove._id); absAdapter.removeNode(nodeToRemove); if (callback !== undefined && _.isFunction(callback)) { callback(); diff --git a/html/admin/js/graphViewer/jasmine_test/specAdapter/abstractAdapterSpec.js b/html/admin/js/graphViewer/jasmine_test/specAdapter/abstractAdapterSpec.js new file mode 100644 index 0000000000..de4cd85294 --- /dev/null +++ b/html/admin/js/graphViewer/jasmine_test/specAdapter/abstractAdapterSpec.js @@ -0,0 +1,725 @@ +/*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, eb, loadFixtures, document */ +/*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, + + getCommunityNodes = function() { + return _.filter(nodes, function(n) { + return String(n._id).match(/^\*community/); + }); + }, + + 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 = []; + }); + + 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 not throw an error if setup correctly', function() { + expect( + function() { + var t = new AbstractAdapter([], []); + } + ).not.toThrow(); + }); + + }); + + + describe('checking the interface', function() { + var testee; + + beforeEach(function() { + testee = new AbstractAdapter([], []); + 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); + }); + }); + + describe('checking nodes', function() { + + var adapter; + + beforeEach(function() { + adapter = new AbstractAdapter(nodes, []); + }); + + 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 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); + 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 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 communities', function() { + + var adapter, mockReducer; + + beforeEach(function() { + mockReducer = {}; + mockReducer.getCommunity = function() {}; + mockReducer.bucketNodes = function() {}; + spyOn(window, "NodeReducer").andCallFake(function(v, e) { + 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); + } + }; + }); + adapter = new AbstractAdapter(nodes, edges); + }); + + it('should not take any action if no limit is set', function() { + spyOn(mockReducer, "getCommunity"); + adapter.insertNode({_id: 1}); + adapter.insertNode({_id: 2}); + adapter.insertNode({_id: 3}); + adapter.insertNode({_id: 4}); + adapter.insertNode({_id: 5}); + adapter.checkNodeLimit(); + expect(mockReducer.getCommunity).wasNotCalled(); + }); + + it('should take a given focus into account', function() { + var n1, limit; + spyOn(mockReducer, "getCommunity").andCallFake(function() { + return [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(mockReducer.getCommunity).toHaveBeenCalledWith(limit, n1); + }); + + it('should create a community if too many nodes are added', function() { + var n1, n2, commId; + spyOn(mockReducer, "getCommunity").andCallFake(function() { + return [1, 2]; + }); + adapter.setNodeLimit(2); + n1 = adapter.insertNode({_id: 1}); + n2 = adapter.insertNode({_id: 2}); + adapter.insertNode({_id: 3}); + adapter.checkNodeLimit(); + expect(mockReducer.getCommunity).wasCalledWith(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(mockReducer, "getCommunity").andCallFake(function() { + return [1, 2]; + }); + n1 = adapter.insertNode({_id: 1}); + n2 = adapter.insertNode({_id: 2}); + adapter.insertNode({_id: 3}); + adapter.setNodeLimit(2); + expect(mockReducer.getCommunity).wasCalledWith(2); + expect(getCommunityNodesIds().length).toEqual(1); + notExistNode([1, 2]); + existNode(3); + }); + + it('should connect edges to communities', function() { + var n1, n2, comm, e1, e2, e3; + spyOn(mockReducer, "getCommunity").andCallFake(function() { + return [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; + + beforeEach(function() { + mockReducer.getCommunity = function() { + return [1, 2]; + }; + 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(0); + expect(nodes.length).toEqual(4); + expect(edges.length).toEqual(3); + existEdge(1, 2); + existEdge(2, 3); + existEdge(3, 1); + existNodes([1,2,3,4]); + }); + + it('should collapse another community if limit is to small', function() { + spyOn(mockReducer, "getCommunity").andCallFake(function() { + return [3, 4]; + }); + adapter.expandCommunity(comm); + expect(getCommunityNodes().length).toEqual(1); + var comm2 = getCommunityNodes()[0]; + expect(comm).not.toEqual(comm2); + expect(mockReducer.getCommunity).wasCalled(); + expect(nodes.length).toEqual(3); + existNodes([1, 2]); + notExistNodes([3, 4]); + }); + + it('should collapse another community if limit is further reduced', function() { + spyOn(mockReducer, "getCommunity").andCallFake(function() { + return [3, 4]; + }); + adapter.setNodeLimit(2); + expect(getCommunityNodes().length).toEqual(2); + var comm2 = getCommunityNodes()[1]; + expect(comm).not.toEqual(comm2); + expect(mockReducer.getCommunity).wasCalled(); + expect(nodes.length).toEqual(2); + notExistNodes([1, 2, 3, 4]); + }); + + }); + + }); + + describe('checking many child nodes', function() { + + var adapter, mockReducer; + + beforeEach(function() { + mockReducer = {}; + mockReducer.getCommunity = function() {}; + mockReducer.bucketNodes = function() {}; + spyOn(window, "NodeReducer").andCallFake(function(v, e) { + 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); + } + }; + }); + adapter = new AbstractAdapter(nodes, edges); + }); + + 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 [ + [n1, n2], + [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 [ + [n1], + [n3, n4, n5], + [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]); + }); + + }); + + }); +}()); diff --git a/html/admin/js/graphViewer/jasmine_test/specAdapter/foxxAdapterSpec.js b/html/admin/js/graphViewer/jasmine_test/specAdapter/foxxAdapterSpec.js index 7b84161502..0878471864 100644 --- a/html/admin/js/graphViewer/jasmine_test/specAdapter/foxxAdapterSpec.js +++ b/html/admin/js/graphViewer/jasmine_test/specAdapter/foxxAdapterSpec.js @@ -5,7 +5,7 @@ /*global window, eb, loadFixtures, document */ /*global $, _, d3*/ /*global describeInterface*/ -/*global ArangoAdapter*/ +/*global FoxxAdapter*/ //////////////////////////////////////////////////////////////////////////////// /// @brief Graph functionality @@ -40,19 +40,16 @@ describe('Foxx Adapter', function () { - describeInterface(new FoxxAdapter([], [], { - nodeCollection: "", - edgeCollection: "" - })); + describeInterface(new FoxxAdapter([], [], "foxx/route")); + + describeIntegeration(new FoxxAdapter([], [], "foxx/route")); var adapter, nodes, edges, arangodb = "http://localhost:8529", nodesCollection, - altNodesCollection, edgesCollection, - altEdgesCollection, mockCollection, callbackCheck, checkCallbackFunction = function() { @@ -163,11 +160,6 @@ beforeEach(function() { nodes = []; edges = []; - mockCollection = {}; - nodesCollection = "TestNodes321"; - edgesCollection = "TestEdges321"; - altNodesCollection = "TestNodes654"; - altEdgesCollection = "TestEdges654"; this.addMatchers({ toHaveCorrectCoordinates: function() { @@ -193,7 +185,7 @@ it('should throw an error if no nodes are given', function() { expect( function() { - var t = new ArangoAdapter(); + var t = new FoxxAdapter(); } ).toThrow("The nodes have to be given."); }); @@ -201,90 +193,61 @@ it('should throw an error if no edges are given', function() { expect( function() { - var t = new ArangoAdapter([]); + var t = new FoxxAdapter([]); } ).toThrow("The edges have to be given."); }); - it('should throw an error if no nodeCollection is given', function() { + it('should throw an error if no route is given', function() { expect( function() { - var t = new ArangoAdapter([], [], { + var t = new FoxxAdapter([], [], { edgeCollection: "" }); } - ).toThrow("The nodeCollection has to be given."); + ).toThrow("The route has to be given."); }); - - it('should throw an error if no edgeCollection is given', function() { - expect( - function() { - var t = new ArangoAdapter([], [], { - nodeCollection: "" - }); - } - ).toThrow("The edgeCollection has to be given."); - }); - - it('should not throw an error if everything is given', function() { - expect( - function() { - var t = new ArangoAdapter([], [], { - nodeCollection: "", - edgeCollection: "" - }); - } - ).not.toThrow(); - }); - - it('should automatically determine the host of not given', function() { - var adapter = new ArangoAdapter( + + it('should automatically determine the host of relative route is given', function() { + var route = "foxx/route" + adapter = new FoxxAdapter( nodes, edges, - { - nodeCollection: nodesCollection, - edgeCollection: edgesCollection, - width: 100, - height: 40 - } + route ), args, host; spyOn($, "ajax"); adapter.createNode({}, function() {}); args = $.ajax.mostRecentCall.args[0]; - host = window.location.protocol + "//" + window.location.host; + host = window.location.protocol + "//" + window.location.host + "/" + route; expect(args.url).toContain(host); }); it('should create a nodeReducer instance', function() { spyOn(window, "NodeReducer"); - var adapter = new ArangoAdapter( + var adapter = new FoxxAdapter( nodes, edges, - { - nodeCollection: nodesCollection, - edgeCollection: edgesCollection, - width: 100, - height: 40 - } + "foxx/route" ); expect(window.NodeReducer).wasCalledWith(nodes, edges); }); describe('setup correctly', function() { - var traversalQuery, - filterQuery, - childrenQuery, + var edgeRoute, + nodeRoute, + queryRoute, loadGraph, requests; beforeEach(function() { var self = this, - host = window.location.protocol + "//" + window.location.host, - apibase = host + "/_api/", - apiCursor = apibase + 'cursor'; + route = "foxx/route" + host = window.location.protocol + "//" + + window.location.host + "/" + + route; self.fakeReducerRequest = function() {}; self.fakeReducerBucketRequest = function() {}; spyOn(window, "NodeReducer").andCallFake(function(v, e) { @@ -300,73 +263,23 @@ } }; }); - adapter = new ArangoAdapter( + adapter = new FoxxAdapter( nodes, edges, - { - nodeCollection: nodesCollection, - edgeCollection: edgesCollection, - width: 100, - height: 40 - } + route ); - traversalQuery = function(id, nods, edgs, undirected) { - var dir; - if (undirected === true) { - dir = "any"; - } else { - dir = "outbound"; - } - return JSON.stringify({ - query: "RETURN TRAVERSAL(@@nodes, @@edges, @id, @dir," - + " {strategy: \"depthfirst\",maxDepth: 1,paths: true})", - bindVars: { - id: id, - "@nodes": nods, - dir: dir, - "@edges": edgs - } - }); - }; - filterQuery = function(v, nods, edgs, undirected) { - var dir; - if (undirected === true) { - dir = "any"; - } else { - dir = "outbound"; - } - return JSON.stringify({ - query: "FOR n IN @@nodes FILTER n.id == @value" - + " RETURN TRAVERSAL(@@nodes, @@edges, n._id, @dir," - + " {strategy: \"depthfirst\",maxDepth: 1,paths: true})", - bindVars: { - value: v, - "@nodes": nods, - dir: dir, - "@edges": edgs - } - }); - }; - childrenQuery = function(id, nods, edgs) { - return JSON.stringify({ - query: "FOR u IN @@nodes FILTER u._id == @id" - + " LET g = ( FOR l in @@edges FILTER l._from == u._id RETURN 1 )" - + " RETURN length(g)", - bindVars: { - id: id, - "@nodes": nods, - "@edges": edgs - } - }); - }; - loadGraph = function(vars) { - var nid = vars.id, - ncol = vars["@nodes"], - ecol = vars["@edges"], - res = [], - inner = [], - first = {}, - node1 = readNode(ncol, nid); + edgeRoute = host + "/edges"; + nodeRoute = host + "/nodes"; + queryRoute = host + "/query"; + + loadGraph = function(data) { + var res = [], + nid, + ncol = nodesCollection, + ecol = edgesCollection, + inner = [], + first = {}, + node1 = readNode(ncol, nid); res.push(inner); first.vertex = node1; first.path = { @@ -386,10 +299,10 @@ requests = {}; - requests.cursor = function(data) { + requests.query = function(data) { return { type: 'POST', - url: apiCursor, + url: queryRoute, data: data, contentType: 'application/json', dataType: 'json', @@ -398,98 +311,62 @@ processData: false }; }; - requests.node = function(col) { - var read = apibase + "document?collection=" + col, - write = apibase + "document/", - base = { - cache: false, - dataType: "json", - contentType: "application/json", - processData: false, - success: jasmine.any(Function), - error: jasmine.any(Function) - }; + requests.node = function() { + var base = { + cache: false, + dataType: "json", + contentType: "application/json", + processData: false, + success: jasmine.any(Function), + error: jasmine.any(Function) + }; return { create: function(data) { - return $.extend(base, {url: read, type: "POST", data: JSON.stringify(data)}); + return $.extend(base, {url: nodeRoute, type: "POST", data: JSON.stringify(data)}); }, patch: function(id, data) { - return $.extend(base, {url: write + id, type: "PUT", data: JSON.stringify(data)}); + return $.extend(base, {url: nodeRoute + "/" + id, type: "PUT", data: JSON.stringify(data)}); }, del: function(id) { - return $.extend(base, {url: write + id, type: "DELETE"}); + return $.extend(base, {url: nodeRoute + "/" + id, type: "DELETE"}); } }; }; requests.edge = function(col) { - var create = apibase + "edge?collection=" + col, - base = { - cache: false, - dataType: "json", - contentType: "application/json", - processData: false, - success: jasmine.any(Function), - error: jasmine.any(Function) - }; + var base = { + cache: false, + dataType: "json", + contentType: "application/json", + processData: false, + success: jasmine.any(Function), + error: jasmine.any(Function) + }; return { create: function(from, to, data) { + data = $.extend(data, {_from: from, _to: to}); return $.extend(base, { - url: create + "&from=" + from + "&to=" + to, + url: edgeRoute, type: "POST", data: JSON.stringify(data) }); + }, + patch: function(id, data) { + return $.extend(base, {url: edgeRoute + "/" + id, type: "PUT", data: JSON.stringify(data)}); + }, + del: function(id) { + return $.extend(base, {url: edgeRoute + "/" + id, type: "DELETE"}); } }; }; }); - it('should offer lists of available collections', function() { - var collections = [], - sys1 = {id: "1", name: "_sys1", status: 3, type: 2}, - sys2 = {id: "2", name: "_sys2", status: 2, type: 2}, - doc1 = {id: "3", name: "doc1", status: 3, type: 2}, - doc2 = {id: "4", name: "doc2", status: 2, type: 2}, - doc3 = {id: "5", name: "doc3", status: 3, type: 2}, - edge1 = {id: "6", name: "edge1", status: 3, type: 3}, - edge2 = {id: "7", name: "edge2", status: 2, type: 3}; - - collections.push(sys1); - collections.push(sys2); - collections.push(doc1); - collections.push(doc2); - collections.push(doc3); - collections.push(edge1); - collections.push(edge2); - - spyOn($, "ajax").andCallFake(function(request) { - request.success({collections: collections}); - }); - - adapter.getCollections(function(docs, edge) { - expect(docs).toContain("doc1"); - expect(docs).toContain("doc2"); - expect(docs).toContain("doc3"); - - expect(docs.length).toEqual(3); - - expect(edge).toContain("edge1"); - expect(edge).toContain("edge2"); - - expect(edge.length).toEqual(2); - }); - }); - - it('should be able to load a tree node from ' - + 'ArangoDB by internal _id attribute', function() { + it('should be able to load by internal _id attribute', function() { var c0, c1, c2, c3, c4; runs(function() { spyOn($, "ajax").andCallFake(function(request) { - var vars = JSON.parse(request.data).bindVars; - if (vars !== undefined) { - request.success({result: loadGraph(vars)}); - } + request.success({result: loadGraph(JSON.parse(request.data))}); }); c0 = insertNode(nodesCollection, 0); @@ -504,7 +381,7 @@ insertEdge(edgesCollection, c0, c4); callbackCheck = false; - adapter.loadNodeFromTreeById(c0, checkCallbackFunction); + adapter.loadNode(c0, checkCallbackFunction); }); waitsFor(function() { diff --git a/html/admin/js/graphViewer/jasmine_test/specAdapter/interfaceSpec.js b/html/admin/js/graphViewer/jasmine_test/specAdapter/interfaceSpec.js index 299302a30f..1b41efa18d 100644 --- a/html/admin/js/graphViewer/jasmine_test/specAdapter/interfaceSpec.js +++ b/html/admin/js/graphViewer/jasmine_test/specAdapter/interfaceSpec.js @@ -1,5 +1,5 @@ /*jslint indent: 2, nomen: true, maxlen: 100, white: true plusplus: true */ -/*global it, expect */ +/*global it, expect, describe*/ //////////////////////////////////////////////////////////////////////////////// @@ -33,6 +33,7 @@ var describeInterface = function (testee) { "use strict"; + describe('checking the interface', function() { it('should comply to the Adapter Interface', function() { this.addMatchers({ toHaveFunction: function(func, argCounter) { @@ -69,7 +70,13 @@ var describeInterface = function (testee) { expect(testee).toHaveFunction("setNodeLimit", 2); expect(testee).toHaveFunction("setChildLimit", 1); expect(testee).toHaveFunction("expandCommunity", 2); - }); + }); + }; + +var describeIntegeration = function(testee) { + "use strict"; + +};