diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..6e63b6e0 --- /dev/null +++ b/.babelrc @@ -0,0 +1,6 @@ +{ + "presets": [ + ["@babel/preset-env", { "targets": { "node": "current" } }], + "@babel/preset-typescript" + ] +} diff --git a/.gitignore b/.gitignore index e95aa58f..7e51b575 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /node_modules /.vscode .idea/ +dist/ diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..6413b404 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,5 @@ +{ + "arrowParens": "always", + "trailingComma": "all", + "singleQuote": true +} diff --git a/lib/alg/components.js b/lib/alg/components.js index 74d4e870..daa1b6ff 100644 --- a/lib/alg/components.js +++ b/lib/alg/components.js @@ -1,4 +1,4 @@ -var _ = require("../lodash"); +var _ = require('../lodash'); module.exports = components; @@ -15,7 +15,7 @@ function components(g) { _.each(g.predecessors(v), dfs); } - _.each(g.nodes(), function(v) { + _.each(g.nodes(), function (v) { cmpt = []; dfs(v); if (cmpt.length) { diff --git a/lib/alg/dfs.js b/lib/alg/dfs.js index f64b2fb7..6ec6af89 100644 --- a/lib/alg/dfs.js +++ b/lib/alg/dfs.js @@ -1,4 +1,4 @@ -var _ = require("../lodash"); +var _ = require('../lodash'); module.exports = dfs; @@ -19,12 +19,12 @@ function dfs(g, vs, order) { var acc = []; var visited = {}; - _.each(vs, function(v) { + _.each(vs, function (v) { if (!g.hasNode(v)) { - throw new Error("Graph does not have node: " + v); + throw new Error('Graph does not have node: ' + v); } - doDfs(g, v, order === "post", visited, navigation, acc); + doDfs(g, v, order === 'post', visited, navigation, acc); }); return acc; } @@ -33,10 +33,14 @@ function doDfs(g, v, postorder, visited, navigation, acc) { if (!_.has(visited, v)) { visited[v] = true; - if (!postorder) { acc.push(v); } - _.each(navigation(v), function(w) { + if (!postorder) { + acc.push(v); + } + _.each(navigation(v), function (w) { doDfs(g, w, postorder, visited, navigation, acc); }); - if (postorder) { acc.push(v); } + if (postorder) { + acc.push(v); + } } } diff --git a/lib/alg/dijkstra-all.js b/lib/alg/dijkstra-all.js index df265280..186d07ad 100644 --- a/lib/alg/dijkstra-all.js +++ b/lib/alg/dijkstra-all.js @@ -1,10 +1,14 @@ -var dijkstra = require("./dijkstra"); -var _ = require("../lodash"); +var dijkstra = require('./dijkstra'); +var _ = require('../lodash'); module.exports = dijkstraAll; function dijkstraAll(g, weightFunc, edgeFunc) { - return _.transform(g.nodes(), function(acc, v) { - acc[v] = dijkstra(g, v, weightFunc, edgeFunc); - }, {}); + return _.transform( + g.nodes(), + function (acc, v) { + acc[v] = dijkstra(g, v, weightFunc, edgeFunc); + }, + {}, + ); } diff --git a/lib/alg/dijkstra.js b/lib/alg/dijkstra.js index 1e1a6974..46c06326 100644 --- a/lib/alg/dijkstra.js +++ b/lib/alg/dijkstra.js @@ -1,14 +1,20 @@ -var _ = require("../lodash"); -var PriorityQueue = require("../data/priority-queue"); +var _ = require('../lodash'); +var PriorityQueue = require('../data/priority-queue'); module.exports = dijkstra; var DEFAULT_WEIGHT_FUNC = _.constant(1); function dijkstra(g, source, weightFn, edgeFn) { - return runDijkstra(g, String(source), + return runDijkstra( + g, + String(source), weightFn || DEFAULT_WEIGHT_FUNC, - edgeFn || function(v) { return g.outEdges(v); }); + edgeFn || + function (v) { + return g.outEdges(v); + }, + ); } function runDijkstra(g, source, weightFn, edgeFn) { @@ -16,15 +22,20 @@ function runDijkstra(g, source, weightFn, edgeFn) { var pq = new PriorityQueue(); var v, vEntry; - var updateNeighbors = function(edge) { + var updateNeighbors = function (edge) { var w = edge.v !== v ? edge.v : edge.w; var wEntry = results[w]; var weight = weightFn(edge); var distance = vEntry.distance + weight; if (weight < 0) { - throw new Error("dijkstra does not allow negative edge weights. " + - "Bad edge: " + edge + " Weight: " + weight); + throw new Error( + 'dijkstra does not allow negative edge weights. ' + + 'Bad edge: ' + + edge + + ' Weight: ' + + weight, + ); } if (distance < wEntry.distance) { @@ -34,7 +45,7 @@ function runDijkstra(g, source, weightFn, edgeFn) { } }; - g.nodes().forEach(function(v) { + g.nodes().forEach(function (v) { var distance = v === source ? 0 : Number.POSITIVE_INFINITY; results[v] = { distance: distance }; pq.add(v, distance); diff --git a/lib/alg/find-cycles.js b/lib/alg/find-cycles.js index 9b59492c..0e622111 100644 --- a/lib/alg/find-cycles.js +++ b/lib/alg/find-cycles.js @@ -1,10 +1,12 @@ -var _ = require("../lodash"); -var tarjan = require("./tarjan"); +var _ = require('../lodash'); +var tarjan = require('./tarjan'); module.exports = findCycles; function findCycles(g) { - return _.filter(tarjan(g), function(cmpt) { - return cmpt.length > 1 || (cmpt.length === 1 && g.hasEdge(cmpt[0], cmpt[0])); + return _.filter(tarjan(g), function (cmpt) { + return ( + cmpt.length > 1 || (cmpt.length === 1 && g.hasEdge(cmpt[0], cmpt[0])) + ); }); } diff --git a/lib/alg/floyd-warshall.js b/lib/alg/floyd-warshall.js index b79da4d2..8bd15805 100644 --- a/lib/alg/floyd-warshall.js +++ b/lib/alg/floyd-warshall.js @@ -1,39 +1,44 @@ -var _ = require("../lodash"); +var _ = require('../lodash'); module.exports = floydWarshall; var DEFAULT_WEIGHT_FUNC = _.constant(1); function floydWarshall(g, weightFn, edgeFn) { - return runFloydWarshall(g, + return runFloydWarshall( + g, weightFn || DEFAULT_WEIGHT_FUNC, - edgeFn || function(v) { return g.outEdges(v); }); + edgeFn || + function (v) { + return g.outEdges(v); + }, + ); } function runFloydWarshall(g, weightFn, edgeFn) { var results = {}; var nodes = g.nodes(); - nodes.forEach(function(v) { + nodes.forEach(function (v) { results[v] = {}; results[v][v] = { distance: 0 }; - nodes.forEach(function(w) { + nodes.forEach(function (w) { if (v !== w) { results[v][w] = { distance: Number.POSITIVE_INFINITY }; } }); - edgeFn(v).forEach(function(edge) { + edgeFn(v).forEach(function (edge) { var w = edge.v === v ? edge.w : edge.v; var d = weightFn(edge); results[v][w] = { distance: d, predecessor: v }; }); }); - nodes.forEach(function(k) { + nodes.forEach(function (k) { var rowK = results[k]; - nodes.forEach(function(i) { + nodes.forEach(function (i) { var rowI = results[i]; - nodes.forEach(function(j) { + nodes.forEach(function (j) { var ik = rowI[k]; var kj = rowK[j]; var ij = rowI[j]; diff --git a/lib/alg/index.js b/lib/alg/index.js index 2c3d76f2..36a6dc8a 100644 --- a/lib/alg/index.js +++ b/lib/alg/index.js @@ -1,13 +1,13 @@ module.exports = { - components: require("./components"), - dijkstra: require("./dijkstra"), - dijkstraAll: require("./dijkstra-all"), - findCycles: require("./find-cycles"), - floydWarshall: require("./floyd-warshall"), - isAcyclic: require("./is-acyclic"), - postorder: require("./postorder"), - preorder: require("./preorder"), - prim: require("./prim"), - tarjan: require("./tarjan"), - topsort: require("./topsort") + components: require('./components'), + dijkstra: require('./dijkstra'), + dijkstraAll: require('./dijkstra-all'), + findCycles: require('./find-cycles'), + floydWarshall: require('./floyd-warshall'), + isAcyclic: require('./is-acyclic'), + postorder: require('./postorder'), + preorder: require('./preorder'), + prim: require('./prim'), + tarjan: require('./tarjan'), + topsort: require('./topsort'), }; diff --git a/lib/alg/is-acyclic.js b/lib/alg/is-acyclic.js index eff4ef0b..56595063 100644 --- a/lib/alg/is-acyclic.js +++ b/lib/alg/is-acyclic.js @@ -1,4 +1,4 @@ -var topsort = require("./topsort"); +var topsort = require('./topsort'); module.exports = isAcyclic; diff --git a/lib/alg/postorder.js b/lib/alg/postorder.js index 1d82313f..5a2c8e86 100644 --- a/lib/alg/postorder.js +++ b/lib/alg/postorder.js @@ -1,7 +1,7 @@ -var dfs = require("./dfs"); +var dfs = require('./dfs'); module.exports = postorder; function postorder(g, vs) { - return dfs(g, vs, "post"); + return dfs(g, vs, 'post'); } diff --git a/lib/alg/preorder.js b/lib/alg/preorder.js index cf333cd8..db54b587 100644 --- a/lib/alg/preorder.js +++ b/lib/alg/preorder.js @@ -1,7 +1,7 @@ -var dfs = require("./dfs"); +var dfs = require('./dfs'); module.exports = preorder; function preorder(g, vs) { - return dfs(g, vs, "pre"); + return dfs(g, vs, 'pre'); } diff --git a/lib/alg/prim.js b/lib/alg/prim.js index df560402..8e6b3357 100644 --- a/lib/alg/prim.js +++ b/lib/alg/prim.js @@ -1,6 +1,6 @@ -var _ = require("../lodash"); -var Graph = require("../graph"); -var PriorityQueue = require("../data/priority-queue"); +var _ = require('../lodash'); +var Graph = require('../graph'); +var PriorityQueue = require('../data/priority-queue'); module.exports = prim; @@ -26,7 +26,7 @@ function prim(g, weightFunc) { return result; } - _.each(g.nodes(), function(v) { + _.each(g.nodes(), function (v) { pq.add(v, Number.POSITIVE_INFINITY); result.setNode(v); }); @@ -40,7 +40,7 @@ function prim(g, weightFunc) { if (_.has(parents, v)) { result.setEdge(v, parents[v]); } else if (init) { - throw new Error("Input graph is not connected: " + g); + throw new Error('Input graph is not connected: ' + g); } else { init = true; } diff --git a/lib/alg/tarjan.js b/lib/alg/tarjan.js index 080aa01b..6f8b88fb 100644 --- a/lib/alg/tarjan.js +++ b/lib/alg/tarjan.js @@ -1,4 +1,4 @@ -var _ = require("../lodash"); +var _ = require('../lodash'); module.exports = tarjan; @@ -9,14 +9,14 @@ function tarjan(g) { var results = []; function dfs(v) { - var entry = visited[v] = { + var entry = (visited[v] = { onStack: true, lowlink: index, - index: index++ - }; + index: index++, + }); stack.push(v); - g.successors(v).forEach(function(w) { + g.successors(v).forEach(function (w) { if (!_.has(visited, w)) { dfs(w); entry.lowlink = Math.min(entry.lowlink, visited[w].lowlink); @@ -37,7 +37,7 @@ function tarjan(g) { } } - g.nodes().forEach(function(v) { + g.nodes().forEach(function (v) { if (!_.has(visited, v)) { dfs(v); } diff --git a/lib/alg/topsort.js b/lib/alg/topsort.js index 6cd8a5d1..64a76953 100644 --- a/lib/alg/topsort.js +++ b/lib/alg/topsort.js @@ -1,4 +1,4 @@ -var _ = require("../lodash"); +var _ = require('../lodash'); module.exports = topsort; topsort.CycleException = CycleException; @@ -32,4 +32,4 @@ function topsort(g) { } function CycleException() {} -CycleException.prototype = new Error(); // must be an instance of Error to pass testing \ No newline at end of file +CycleException.prototype = new Error(); // must be an instance of Error to pass testing diff --git a/lib/data/priority-queue.js b/lib/data/priority-queue.js index 92bf3bbc..83a9e107 100644 --- a/lib/data/priority-queue.js +++ b/lib/data/priority-queue.js @@ -1,4 +1,4 @@ -var _ = require("../lodash"); +var _ = require('../lodash'); module.exports = PriorityQueue; @@ -17,21 +17,23 @@ function PriorityQueue() { /** * Returns the number of elements in the queue. Takes `O(1)` time. */ -PriorityQueue.prototype.size = function() { +PriorityQueue.prototype.size = function () { return this._arr.length; }; /** * Returns the keys that are in the queue. Takes `O(n)` time. */ -PriorityQueue.prototype.keys = function() { - return this._arr.map(function(x) { return x.key; }); +PriorityQueue.prototype.keys = function () { + return this._arr.map(function (x) { + return x.key; + }); }; /** * Returns `true` if **key** is in the queue and `false` if not. */ -PriorityQueue.prototype.has = function(key) { +PriorityQueue.prototype.has = function (key) { return _.has(this._keyIndices, key); }; @@ -41,7 +43,7 @@ PriorityQueue.prototype.has = function(key) { * * @param {Object} key */ -PriorityQueue.prototype.priority = function(key) { +PriorityQueue.prototype.priority = function (key) { var index = this._keyIndices[key]; if (index !== undefined) { return this._arr[index].priority; @@ -52,9 +54,9 @@ PriorityQueue.prototype.priority = function(key) { * Returns the key for the minimum element in this queue. If the queue is * empty this function throws an Error. Takes `O(1)` time. */ -PriorityQueue.prototype.min = function() { +PriorityQueue.prototype.min = function () { if (this.size() === 0) { - throw new Error("Queue underflow"); + throw new Error('Queue underflow'); } return this._arr[0].key; }; @@ -67,14 +69,14 @@ PriorityQueue.prototype.min = function() { * @param {Object} key the key to add * @param {Number} priority the initial priority for the key */ -PriorityQueue.prototype.add = function(key, priority) { +PriorityQueue.prototype.add = function (key, priority) { var keyIndices = this._keyIndices; key = String(key); if (!_.has(keyIndices, key)) { var arr = this._arr; var index = arr.length; keyIndices[key] = index; - arr.push({key: key, priority: priority}); + arr.push({ key: key, priority: priority }); this._decrease(index); return true; } @@ -84,7 +86,7 @@ PriorityQueue.prototype.add = function(key, priority) { /** * Removes and returns the smallest key in the queue. Takes `O(log n)` time. */ -PriorityQueue.prototype.removeMin = function() { +PriorityQueue.prototype.removeMin = function () { this._swap(0, this._arr.length - 1); var min = this._arr.pop(); delete this._keyIndices[min.key]; @@ -99,17 +101,24 @@ PriorityQueue.prototype.removeMin = function() { * @param {Object} key the key for which to raise priority * @param {Number} priority the new priority for the key */ -PriorityQueue.prototype.decrease = function(key, priority) { +PriorityQueue.prototype.decrease = function (key, priority) { var index = this._keyIndices[key]; if (priority > this._arr[index].priority) { - throw new Error("New priority is greater than current priority. " + - "Key: " + key + " Old: " + this._arr[index].priority + " New: " + priority); + throw new Error( + 'New priority is greater than current priority. ' + + 'Key: ' + + key + + ' Old: ' + + this._arr[index].priority + + ' New: ' + + priority, + ); } this._arr[index].priority = priority; this._decrease(index); }; -PriorityQueue.prototype._heapify = function(i) { +PriorityQueue.prototype._heapify = function (i) { var arr = this._arr; var l = 2 * i; var r = l + 1; @@ -126,7 +135,7 @@ PriorityQueue.prototype._heapify = function(i) { } }; -PriorityQueue.prototype._decrease = function(index) { +PriorityQueue.prototype._decrease = function (index) { var arr = this._arr; var priority = arr[index].priority; var parent; @@ -140,7 +149,7 @@ PriorityQueue.prototype._decrease = function(index) { } }; -PriorityQueue.prototype._swap = function(i, j) { +PriorityQueue.prototype._swap = function (i, j) { var arr = this._arr; var keyIndices = this._keyIndices; var origArrI = arr[i]; diff --git a/lib/graph.js b/lib/graph.js index d3e5bd4f..f545f409 100644 --- a/lib/graph.js +++ b/lib/graph.js @@ -1,12 +1,12 @@ -"use strict"; +'use strict'; -var _ = require("./lodash"); +var _ = require('./lodash'); module.exports = Graph; -var DEFAULT_EDGE_NAME = "\x00"; -var GRAPH_NODE = "\x00"; -var EDGE_KEY_DELIM = "\x01"; +var DEFAULT_EDGE_NAME = '\x00'; +var GRAPH_NODE = '\x00'; +var EDGE_KEY_DELIM = '\x01'; // Implementation notes: // @@ -19,9 +19,9 @@ var EDGE_KEY_DELIM = "\x01"; // we're going to get to a performant hashtable in JavaScript. function Graph(opts) { - this._isDirected = _.has(opts, "directed") ? opts.directed : true; - this._isMultigraph = _.has(opts, "multigraph") ? opts.multigraph : false; - this._isCompound = _.has(opts, "compound") ? opts.compound : false; + this._isDirected = _.has(opts, 'directed') ? opts.directed : true; + this._isMultigraph = _.has(opts, 'multigraph') ? opts.multigraph : false; + this._isCompound = _.has(opts, 'compound') ? opts.compound : false; // Label for the graph itself this._label = undefined; @@ -69,34 +69,32 @@ Graph.prototype._nodeCount = 0; /* Number of edges in the graph. Should only be changed by the implementation. */ Graph.prototype._edgeCount = 0; - /* === Graph functions ========= */ -Graph.prototype.isDirected = function() { +Graph.prototype.isDirected = function () { return this._isDirected; }; -Graph.prototype.isMultigraph = function() { +Graph.prototype.isMultigraph = function () { return this._isMultigraph; }; -Graph.prototype.isCompound = function() { +Graph.prototype.isCompound = function () { return this._isCompound; }; -Graph.prototype.setGraph = function(label) { +Graph.prototype.setGraph = function (label) { this._label = label; return this; }; -Graph.prototype.graph = function() { +Graph.prototype.graph = function () { return this._label; }; - /* === Node functions ========== */ -Graph.prototype.setDefaultNodeLabel = function(newDefault) { +Graph.prototype.setDefaultNodeLabel = function (newDefault) { if (!_.isFunction(newDefault)) { newDefault = _.constant(newDefault); } @@ -104,32 +102,32 @@ Graph.prototype.setDefaultNodeLabel = function(newDefault) { return this; }; -Graph.prototype.nodeCount = function() { +Graph.prototype.nodeCount = function () { return this._nodeCount; }; -Graph.prototype.nodes = function() { +Graph.prototype.nodes = function () { return _.keys(this._nodes); }; -Graph.prototype.sources = function() { +Graph.prototype.sources = function () { var self = this; - return _.filter(this.nodes(), function(v) { + return _.filter(this.nodes(), function (v) { return _.isEmpty(self._in[v]); }); }; -Graph.prototype.sinks = function() { +Graph.prototype.sinks = function () { var self = this; - return _.filter(this.nodes(), function(v) { + return _.filter(this.nodes(), function (v) { return _.isEmpty(self._out[v]); }); }; -Graph.prototype.setNodes = function(vs, value) { +Graph.prototype.setNodes = function (vs, value) { var args = arguments; var self = this; - _.each(vs, function(v) { + _.each(vs, function (v) { if (args.length > 1) { self.setNode(v, value); } else { @@ -139,7 +137,7 @@ Graph.prototype.setNodes = function(vs, value) { return this; }; -Graph.prototype.setNode = function(v, value) { +Graph.prototype.setNode = function (v, value) { if (_.has(this._nodes, v)) { if (arguments.length > 1) { this._nodes[v] = value; @@ -161,23 +159,25 @@ Graph.prototype.setNode = function(v, value) { return this; }; -Graph.prototype.node = function(v) { +Graph.prototype.node = function (v) { return this._nodes[v]; }; -Graph.prototype.hasNode = function(v) { +Graph.prototype.hasNode = function (v) { return _.has(this._nodes, v); }; -Graph.prototype.removeNode = function(v) { +Graph.prototype.removeNode = function (v) { var self = this; if (_.has(this._nodes, v)) { - var removeEdge = function(e) { self.removeEdge(self._edgeObjs[e]); }; + var removeEdge = function (e) { + self.removeEdge(self._edgeObjs[e]); + }; delete this._nodes[v]; if (this._isCompound) { this._removeFromParentsChildList(v); delete this._parent[v]; - _.each(this.children(v), function(child) { + _.each(this.children(v), function (child) { self.setParent(child); }); delete this._children[v]; @@ -193,22 +193,25 @@ Graph.prototype.removeNode = function(v) { return this; }; -Graph.prototype.setParent = function(v, parent) { +Graph.prototype.setParent = function (v, parent) { if (!this._isCompound) { - throw new Error("Cannot set parent in a non-compound graph"); + throw new Error('Cannot set parent in a non-compound graph'); } if (_.isUndefined(parent)) { parent = GRAPH_NODE; } else { // Coerce parent to string - parent += ""; - for (var ancestor = parent; + parent += ''; + for ( + var ancestor = parent; !_.isUndefined(ancestor); - ancestor = this.parent(ancestor)) { + ancestor = this.parent(ancestor) + ) { if (ancestor === v) { - throw new Error("Setting " + parent+ " as parent of " + v + - " would create a cycle"); + throw new Error( + 'Setting ' + parent + ' as parent of ' + v + ' would create a cycle', + ); } } @@ -222,11 +225,11 @@ Graph.prototype.setParent = function(v, parent) { return this; }; -Graph.prototype._removeFromParentsChildList = function(v) { +Graph.prototype._removeFromParentsChildList = function (v) { delete this._children[this._parent[v]][v]; }; -Graph.prototype.parent = function(v) { +Graph.prototype.parent = function (v) { if (this._isCompound) { var parent = this._parent[v]; if (parent !== GRAPH_NODE) { @@ -235,7 +238,7 @@ Graph.prototype.parent = function(v) { } }; -Graph.prototype.children = function(v) { +Graph.prototype.children = function (v) { if (_.isUndefined(v)) { v = GRAPH_NODE; } @@ -252,21 +255,21 @@ Graph.prototype.children = function(v) { } }; -Graph.prototype.predecessors = function(v) { +Graph.prototype.predecessors = function (v) { var predsV = this._preds[v]; if (predsV) { return _.keys(predsV); } }; -Graph.prototype.successors = function(v) { +Graph.prototype.successors = function (v) { var sucsV = this._sucs[v]; if (sucsV) { return _.keys(sucsV); } }; -Graph.prototype.neighbors = function(v) { +Graph.prototype.neighbors = function (v) { var preds = this.predecessors(v); if (preds) { return _.union(preds, this.successors(v)); @@ -283,23 +286,23 @@ Graph.prototype.isLeaf = function (v) { return neighbors.length === 0; }; -Graph.prototype.filterNodes = function(filter) { +Graph.prototype.filterNodes = function (filter) { var copy = new this.constructor({ directed: this._isDirected, multigraph: this._isMultigraph, - compound: this._isCompound + compound: this._isCompound, }); copy.setGraph(this.graph()); var self = this; - _.each(this._nodes, function(value, v) { + _.each(this._nodes, function (value, v) { if (filter(v)) { copy.setNode(v, value); } }); - _.each(this._edgeObjs, function(e) { + _.each(this._edgeObjs, function (e) { if (copy.hasNode(e.v) && copy.hasNode(e.w)) { copy.setEdge(e, self.edge(e)); } @@ -319,7 +322,7 @@ Graph.prototype.filterNodes = function(filter) { } if (this._isCompound) { - _.each(copy.nodes(), function(v) { + _.each(copy.nodes(), function (v) { copy.setParent(v, findParent(v)); }); } @@ -329,7 +332,7 @@ Graph.prototype.filterNodes = function(filter) { /* === Edge functions ========== */ -Graph.prototype.setDefaultEdgeLabel = function(newDefault) { +Graph.prototype.setDefaultEdgeLabel = function (newDefault) { if (!_.isFunction(newDefault)) { newDefault = _.constant(newDefault); } @@ -337,18 +340,18 @@ Graph.prototype.setDefaultEdgeLabel = function(newDefault) { return this; }; -Graph.prototype.edgeCount = function() { +Graph.prototype.edgeCount = function () { return this._edgeCount; }; -Graph.prototype.edges = function() { +Graph.prototype.edges = function () { return _.values(this._edgeObjs); }; -Graph.prototype.setPath = function(vs, value) { +Graph.prototype.setPath = function (vs, value) { var self = this; var args = arguments; - _.reduce(vs, function(v, w) { + _.reduce(vs, function (v, w) { if (args.length > 1) { self.setEdge(v, w, value); } else { @@ -363,12 +366,12 @@ Graph.prototype.setPath = function(vs, value) { * setEdge(v, w, [value, [name]]) * setEdge({ v, w, [name] }, [value]) */ -Graph.prototype.setEdge = function() { +Graph.prototype.setEdge = function () { var v, w, name, value; var valueSpecified = false; var arg0 = arguments[0]; - if (typeof arg0 === "object" && arg0 !== null && "v" in arg0) { + if (typeof arg0 === 'object' && arg0 !== null && 'v' in arg0) { v = arg0.v; w = arg0.w; name = arg0.name; @@ -386,10 +389,10 @@ Graph.prototype.setEdge = function() { } } - v = "" + v; - w = "" + w; + v = '' + v; + w = '' + w; if (!_.isUndefined(name)) { - name = "" + name; + name = '' + name; } var e = edgeArgsToId(this._isDirected, v, w, name); @@ -401,7 +404,7 @@ Graph.prototype.setEdge = function() { } if (!_.isUndefined(name) && !this._isMultigraph) { - throw new Error("Cannot set a named edge when isMultigraph = false"); + throw new Error('Cannot set a named edge when isMultigraph = false'); } // It didn't exist, so we need to create it. @@ -409,7 +412,9 @@ Graph.prototype.setEdge = function() { this.setNode(v); this.setNode(w); - this._edgeLabels[e] = valueSpecified ? value : this._defaultEdgeLabelFn(v, w, name); + this._edgeLabels[e] = valueSpecified + ? value + : this._defaultEdgeLabelFn(v, w, name); var edgeObj = edgeArgsToObj(this._isDirected, v, w, name); // Ensure we add undirected edges in a consistent way. @@ -426,24 +431,27 @@ Graph.prototype.setEdge = function() { return this; }; -Graph.prototype.edge = function(v, w, name) { - var e = (arguments.length === 1 - ? edgeObjToId(this._isDirected, arguments[0]) - : edgeArgsToId(this._isDirected, v, w, name)); +Graph.prototype.edge = function (v, w, name) { + var e = + arguments.length === 1 + ? edgeObjToId(this._isDirected, arguments[0]) + : edgeArgsToId(this._isDirected, v, w, name); return this._edgeLabels[e]; }; -Graph.prototype.hasEdge = function(v, w, name) { - var e = (arguments.length === 1 - ? edgeObjToId(this._isDirected, arguments[0]) - : edgeArgsToId(this._isDirected, v, w, name)); +Graph.prototype.hasEdge = function (v, w, name) { + var e = + arguments.length === 1 + ? edgeObjToId(this._isDirected, arguments[0]) + : edgeArgsToId(this._isDirected, v, w, name); return _.has(this._edgeLabels, e); }; -Graph.prototype.removeEdge = function(v, w, name) { - var e = (arguments.length === 1 - ? edgeObjToId(this._isDirected, arguments[0]) - : edgeArgsToId(this._isDirected, v, w, name)); +Graph.prototype.removeEdge = function (v, w, name) { + var e = + arguments.length === 1 + ? edgeObjToId(this._isDirected, arguments[0]) + : edgeArgsToId(this._isDirected, v, w, name); var edge = this._edgeObjs[e]; if (edge) { v = edge.v; @@ -459,29 +467,33 @@ Graph.prototype.removeEdge = function(v, w, name) { return this; }; -Graph.prototype.inEdges = function(v, u) { +Graph.prototype.inEdges = function (v, u) { var inV = this._in[v]; if (inV) { var edges = _.values(inV); if (!u) { return edges; } - return _.filter(edges, function(edge) { return edge.v === u; }); + return _.filter(edges, function (edge) { + return edge.v === u; + }); } }; -Graph.prototype.outEdges = function(v, w) { +Graph.prototype.outEdges = function (v, w) { var outV = this._out[v]; if (outV) { var edges = _.values(outV); if (!w) { return edges; } - return _.filter(edges, function(edge) { return edge.w === w; }); + return _.filter(edges, function (edge) { + return edge.w === w; + }); } }; -Graph.prototype.nodeEdges = function(v, w) { +Graph.prototype.nodeEdges = function (v, w) { var inEdges = this.inEdges(v, w); if (inEdges) { return inEdges.concat(this.outEdges(v, w)); @@ -497,30 +509,37 @@ function incrementOrInitEntry(map, k) { } function decrementOrRemoveEntry(map, k) { - if (!--map[k]) { delete map[k]; } + if (!--map[k]) { + delete map[k]; + } } function edgeArgsToId(isDirected, v_, w_, name) { - var v = "" + v_; - var w = "" + w_; + var v = '' + v_; + var w = '' + w_; if (!isDirected && v > w) { var tmp = v; v = w; w = tmp; } - return v + EDGE_KEY_DELIM + w + EDGE_KEY_DELIM + - (_.isUndefined(name) ? DEFAULT_EDGE_NAME : name); + return ( + v + + EDGE_KEY_DELIM + + w + + EDGE_KEY_DELIM + + (_.isUndefined(name) ? DEFAULT_EDGE_NAME : name) + ); } function edgeArgsToObj(isDirected, v_, w_, name) { - var v = "" + v_; - var w = "" + w_; + var v = '' + v_; + var w = '' + w_; if (!isDirected && v > w) { var tmp = v; v = w; w = tmp; } - var edgeObj = { v: v, w: w }; + var edgeObj = { v: v, w: w }; if (name) { edgeObj.name = name; } diff --git a/lib/index.js b/lib/index.js index 756e0ab6..9fb7a78f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,5 +1,5 @@ // Includes only the "core" of graphlib module.exports = { - Graph: require("./graph"), - version: require("./version") + Graph: require('./graph'), + version: require('./version'), }; diff --git a/lib/json.js b/lib/json.js index 8db651e2..daf2d9b4 100644 --- a/lib/json.js +++ b/lib/json.js @@ -1,9 +1,9 @@ -var _ = require("./lodash"); -var Graph = require("./graph"); +var _ = require('./lodash'); +var Graph = require('./graph'); module.exports = { write: write, - read: read + read: read, }; function write(g) { @@ -11,10 +11,10 @@ function write(g) { options: { directed: g.isDirected(), multigraph: g.isMultigraph(), - compound: g.isCompound() + compound: g.isCompound(), }, nodes: writeNodes(g), - edges: writeEdges(g) + edges: writeEdges(g), }; if (!_.isUndefined(g.graph())) { json.value = _.clone(g.graph()); @@ -23,7 +23,7 @@ function write(g) { } function writeNodes(g) { - return _.map(g.nodes(), function(v) { + return _.map(g.nodes(), function (v) { var nodeValue = g.node(v); var parent = g.parent(v); var node = { v: v }; @@ -38,7 +38,7 @@ function writeNodes(g) { } function writeEdges(g) { - return _.map(g.edges(), function(e) { + return _.map(g.edges(), function (e) { var edgeValue = g.edge(e); var edge = { v: e.v, w: e.w }; if (!_.isUndefined(e.name)) { @@ -53,13 +53,13 @@ function writeEdges(g) { function read(json) { var g = new Graph(json.options).setGraph(json.value); - _.each(json.nodes, function(entry) { + _.each(json.nodes, function (entry) { g.setNode(entry.v, entry.value); if (entry.parent) { g.setParent(entry.v, entry.parent); } }); - _.each(json.edges, function(entry) { + _.each(json.edges, function (entry) { g.setEdge({ v: entry.v, w: entry.w, name: entry.name }, entry.value); }); return g; diff --git a/lib/lodash.js b/lib/lodash.js index 8c6d7b6f..8acd7de6 100644 --- a/lib/lodash.js +++ b/lib/lodash.js @@ -3,25 +3,25 @@ var lodash; -if (typeof require === "function") { +if (typeof require === 'function') { try { lodash = { - clone: require("lodash.clone"), - constant: require("lodash.constant"), - each: require("lodash.foreach"), - filter: require("lodash.filter"), - has: require("lodash.has"), + clone: require('lodash.clone'), + constant: require('lodash.constant'), + each: require('lodash.foreach'), + filter: require('lodash.filter'), + has: require('lodash.has'), isArray: Array.isArray, - isEmpty: require("lodash.isempty"), - isFunction: require("lodash.isfunction"), - isUndefined: require("lodash.isundefined"), - keys: require("lodash.keys"), - map: require("lodash.map"), - reduce: require("lodash.reduce"), - size: require("lodash.size"), - transform: require("lodash.transform"), - union: require("lodash.union"), - values: require("lodash.values") + isEmpty: require('lodash.isempty'), + isFunction: require('lodash.isfunction'), + isUndefined: require('lodash.isundefined'), + keys: require('lodash.keys'), + map: require('lodash.map'), + reduce: require('lodash.reduce'), + size: require('lodash.size'), + transform: require('lodash.transform'), + union: require('lodash.union'), + values: require('lodash.values'), }; } catch (e) { // continue regardless of error diff --git a/package.json b/package.json index 980366f0..d506af60 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ ], "scripts": { "test": "mocha -R dot 'test/**/*test.js'", - "lint": "eslint '*.js' 'lib/**/*.js' 'test/**/*test.js'" + "lint": "eslint '*.js' 'lib/**/*.js' 'test/**/*test.js'", + "format": "prettier --write 'lib/**/*.js' 'test/**/*.js'" }, "dependencies": { "lodash.clone": "^4.5.0", @@ -37,15 +38,21 @@ "lodash.values": "^4.3.0" }, "devDependencies": { + "@babel/preset-env": "^7.13.15", + "@babel/preset-typescript": "^7.13.0", "@snyk/lodash": "^4.17.15-patch", "benchmark": "^2.1.4", "chai": "^4.1.2", "eslint": "^6.8.0", + "jest": "^27.0.0-next.8", "mocha": "^6.1.4", + "prettier": "^2.2.1", "requirejs": "^2.3.5", "seedrandom": "^2.4.3", "semver": "^5.5.0", "sprintf": "^0.1.5", + "ts-node": "^9.1.1", + "typescript": "~4.2.4", "uglify-js": "^3.3.10" }, "repository": { diff --git a/test/alg/all-shortest-paths-test.js b/test/alg/all-shortest-paths-test.js index 956a9326..44b0eca2 100644 --- a/test/alg/all-shortest-paths-test.js +++ b/test/alg/all-shortest-paths-test.js @@ -1,126 +1,130 @@ -var expect = require("../chai").expect; -var Graph = require("../..").Graph; +var expect = require('../chai').expect; +var Graph = require('../..').Graph; exports.tests = tests; function tests(sp) { - describe("allShortestPaths", function() { - it("returns 0 for the node itself", function() { + describe('allShortestPaths', function () { + it('returns 0 for the node itself', function () { var g = new Graph(); - g.setNode("a"); - expect(sp(g)).to.eql({ a: { a: { distance: 0 } }}); + g.setNode('a'); + expect(sp(g)).to.eql({ a: { a: { distance: 0 } } }); }); - it("returns the distance and path from all nodes to other nodes", function() { + it('returns the distance and path from all nodes to other nodes', function () { var g = new Graph(); - g.setEdge("a", "b"); - g.setEdge("b", "c"); + g.setEdge('a', 'b'); + g.setEdge('b', 'c'); expect(sp(g)).to.eql({ a: { a: { distance: 0 }, - b: { distance: 1, predecessor: "a" }, - c: { distance: 2, predecessor: "b" } + b: { distance: 1, predecessor: 'a' }, + c: { distance: 2, predecessor: 'b' }, }, b: { a: { distance: Number.POSITIVE_INFINITY }, b: { distance: 0 }, - c: { distance: 1, predecessor: "b" } + c: { distance: 1, predecessor: 'b' }, }, c: { a: { distance: Number.POSITIVE_INFINITY }, b: { distance: Number.POSITIVE_INFINITY }, - c: { distance: 0 } - } + c: { distance: 0 }, + }, }); }); - it("uses an optionally supplied weight function", function() { + it('uses an optionally supplied weight function', function () { var g = new Graph(); - g.setEdge("a", "b", 2); - g.setEdge("b", "c", 3); + g.setEdge('a', 'b', 2); + g.setEdge('b', 'c', 3); expect(sp(g, weightFn(g))).to.eql({ a: { a: { distance: 0 }, - b: { distance: 2, predecessor: "a" }, - c: { distance: 5, predecessor: "b" } + b: { distance: 2, predecessor: 'a' }, + c: { distance: 5, predecessor: 'b' }, }, b: { a: { distance: Number.POSITIVE_INFINITY }, b: { distance: 0 }, - c: { distance: 3, predecessor: "b" } + c: { distance: 3, predecessor: 'b' }, }, c: { a: { distance: Number.POSITIVE_INFINITY }, b: { distance: Number.POSITIVE_INFINITY }, - c: { distance: 0 } - } + c: { distance: 0 }, + }, }); }); - it("uses an optionally supplied incident function", function() { + it('uses an optionally supplied incident function', function () { var g = new Graph(); - g.setEdge("a", "b"); - g.setEdge("b", "c"); + g.setEdge('a', 'b'); + g.setEdge('b', 'c'); - expect(sp(g, undefined, function(v) { return g.inEdges(v); })).to.eql({ + expect( + sp(g, undefined, function (v) { + return g.inEdges(v); + }), + ).to.eql({ a: { a: { distance: 0 }, b: { distance: Number.POSITIVE_INFINITY }, - c: { distance: Number.POSITIVE_INFINITY } + c: { distance: Number.POSITIVE_INFINITY }, }, b: { - a: { distance: 1, predecessor: "b" }, + a: { distance: 1, predecessor: 'b' }, b: { distance: 0 }, - c: { distance: Number.POSITIVE_INFINITY } + c: { distance: Number.POSITIVE_INFINITY }, }, c: { - a: { distance: 2, predecessor: "b" }, - b: { distance: 1, predecessor: "c" }, - c: { distance: 0 } - } + a: { distance: 2, predecessor: 'b' }, + b: { distance: 1, predecessor: 'c' }, + c: { distance: 0 }, + }, }); }); - it("works with undirected graphs", function() { + it('works with undirected graphs', function () { var g = new Graph({ directed: false }); - g.setEdge("a", "b", 1); - g.setEdge("b", "c", 2); - g.setEdge("c", "a", 4); - g.setEdge("b", "d", 6); + g.setEdge('a', 'b', 1); + g.setEdge('b', 'c', 2); + g.setEdge('c', 'a', 4); + g.setEdge('b', 'd', 6); expect(sp(g, weightFn(g), g.nodeEdges.bind(g))).to.eql({ a: { a: { distance: 0 }, - b: { distance: 1, predecessor: "a" }, - c: { distance: 3, predecessor: "b" }, - d: { distance: 7, predecessor: "b" }, + b: { distance: 1, predecessor: 'a' }, + c: { distance: 3, predecessor: 'b' }, + d: { distance: 7, predecessor: 'b' }, }, b: { - a: { distance: 1, predecessor: "b" }, + a: { distance: 1, predecessor: 'b' }, b: { distance: 0 }, - c: { distance: 2, predecessor: "b" }, - d: { distance: 6, predecessor: "b" }, + c: { distance: 2, predecessor: 'b' }, + d: { distance: 6, predecessor: 'b' }, }, c: { - a: { distance: 3, predecessor: "b" }, - b: { distance: 2, predecessor: "c" }, + a: { distance: 3, predecessor: 'b' }, + b: { distance: 2, predecessor: 'c' }, c: { distance: 0 }, - d: { distance: 8, predecessor: "b" }, + d: { distance: 8, predecessor: 'b' }, }, d: { - a: { distance: 7, predecessor: "b" }, - b: { distance: 6, predecessor: "d" }, - c: { distance: 8, predecessor: "b" }, + a: { distance: 7, predecessor: 'b' }, + b: { distance: 6, predecessor: 'd' }, + c: { distance: 8, predecessor: 'b' }, d: { distance: 0 }, - } + }, }); }); }); } function weightFn(g) { - return function(e) { + return function (e) { return g.edge(e); }; } diff --git a/test/alg/components-test.js b/test/alg/components-test.js index 12e7543d..27154f5d 100644 --- a/test/alg/components-test.js +++ b/test/alg/components-test.js @@ -1,39 +1,50 @@ -var expect = require("../chai").expect; -var _ = require("@snyk/lodash"); -var Graph = require("../..").Graph; -var components = require("../..").alg.components; +var expect = require('../chai').expect; +var _ = require('@snyk/lodash'); +var Graph = require('../..').Graph; +var components = require('../..').alg.components; -describe("alg.components", function() { - it("returns an empty list for an empty graph", function() { +describe('alg.components', function () { + it('returns an empty list for an empty graph', function () { expect(components(new Graph({ directed: false }))).to.be.empty; }); - it("returns singleton lists for unconnected nodes", function() { + it('returns singleton lists for unconnected nodes', function () { var g = new Graph({ directed: false }); - g.setNode("a"); - g.setNode("b"); + g.setNode('a'); + g.setNode('b'); - var result = _.sortBy(components(g), function(arr) { return _.min(arr); }); - expect(result).to.eql([["a"], ["b"]]); + var result = _.sortBy(components(g), function (arr) { + return _.min(arr); + }); + expect(result).to.eql([['a'], ['b']]); }); - it("returns a list of nodes in a component", function() { + it('returns a list of nodes in a component', function () { var g = new Graph({ directed: false }); - g.setEdge("a", "b"); - g.setEdge("b", "c"); + g.setEdge('a', 'b'); + g.setEdge('b', 'c'); - var result = _.map(components(g), function(xs) { return _.sortBy(xs); }); - expect(result).to.eql([["a", "b", "c"]]); + var result = _.map(components(g), function (xs) { + return _.sortBy(xs); + }); + expect(result).to.eql([['a', 'b', 'c']]); }); - it("returns nodes connected by a neighbor relationship in a digraph", function() { + it('returns nodes connected by a neighbor relationship in a digraph', function () { var g = new Graph(); - g.setPath(["a", "b", "c", "a"]); - g.setEdge("d", "c"); - g.setEdge("e", "f"); + g.setPath(['a', 'b', 'c', 'a']); + g.setEdge('d', 'c'); + g.setEdge('e', 'f'); - var result = _.sortBy(_.map(components(g), - function(xs) { return _.sortBy(xs); }), "0"); - expect(result).to.eql([["a", "b", "c", "d"], ["e", "f"]]); + var result = _.sortBy( + _.map(components(g), function (xs) { + return _.sortBy(xs); + }), + '0', + ); + expect(result).to.eql([ + ['a', 'b', 'c', 'd'], + ['e', 'f'], + ]); }); }); diff --git a/test/alg/dijkstra-all-test.js b/test/alg/dijkstra-all-test.js index b7de355e..c3bb444b 100644 --- a/test/alg/dijkstra-all-test.js +++ b/test/alg/dijkstra-all-test.js @@ -1,24 +1,26 @@ -var expect = require("../chai").expect; -var Graph = require("../..").Graph; -var dijkstraAll = require("../..").alg.dijkstraAll; -var allShortestPathsTest = require("./all-shortest-paths-test"); +var expect = require('../chai').expect; +var Graph = require('../..').Graph; +var dijkstraAll = require('../..').alg.dijkstraAll; +var allShortestPathsTest = require('./all-shortest-paths-test'); -describe("alg.dijkstraAll", function() { +describe('alg.dijkstraAll', function () { allShortestPathsTest.tests(dijkstraAll); - it("throws an Error if it encounters a negative edge weight", function() { + it('throws an Error if it encounters a negative edge weight', function () { var g = new Graph(); - g.setEdge("a", "b", 1); - g.setEdge("a", "c", -2); - g.setEdge("b", "d", 3); - g.setEdge("c", "d", 3); + g.setEdge('a', 'b', 1); + g.setEdge('a', 'c', -2); + g.setEdge('b', 'd', 3); + g.setEdge('c', 'd', 3); - expect(function() { dijkstraAll(g, weight(g)); }).to.throw(); + expect(function () { + dijkstraAll(g, weight(g)); + }).to.throw(); }); }); function weight(g) { - return function(e) { + return function (e) { return g.edge(e); }; } diff --git a/test/alg/dijkstra-test.js b/test/alg/dijkstra-test.js index bfb77737..3ed18fe7 100644 --- a/test/alg/dijkstra-test.js +++ b/test/alg/dijkstra-test.js @@ -1,90 +1,96 @@ -var expect = require("../chai").expect; +var expect = require('../chai').expect; -var Graph = require("../..").Graph; -var dijkstra = require("../..").alg.dijkstra; +var Graph = require('../..').Graph; +var dijkstra = require('../..').alg.dijkstra; -describe("alg.dijkstra", function() { - it("assigns distance 0 for the source node", function() { +describe('alg.dijkstra', function () { + it('assigns distance 0 for the source node', function () { var g = new Graph(); - g.setNode("source"); - expect(dijkstra(g, "source")).to.eql({ source: { distance: 0 } }); + g.setNode('source'); + expect(dijkstra(g, 'source')).to.eql({ source: { distance: 0 } }); }); - it("returns Number.POSITIVE_INFINITY for unconnected nodes", function() { + it('returns Number.POSITIVE_INFINITY for unconnected nodes', function () { var g = new Graph(); - g.setNode("a"); - g.setNode("b"); - expect(dijkstra(g, "a")).to.eql({ + g.setNode('a'); + g.setNode('b'); + expect(dijkstra(g, 'a')).to.eql({ a: { distance: 0 }, - b: { distance: Number.POSITIVE_INFINITY } + b: { distance: Number.POSITIVE_INFINITY }, }); }); - it("returns the distance and path from the source node to other nodes", function() { + it('returns the distance and path from the source node to other nodes', function () { var g = new Graph(); - g.setPath(["a", "b", "c"]); - g.setEdge("b", "d"); - expect(dijkstra(g, "a")).to.eql({ + g.setPath(['a', 'b', 'c']); + g.setEdge('b', 'd'); + expect(dijkstra(g, 'a')).to.eql({ a: { distance: 0 }, - b: { distance: 1, predecessor: "a" }, - c: { distance: 2, predecessor: "b" }, - d: { distance: 2, predecessor: "b" } + b: { distance: 1, predecessor: 'a' }, + c: { distance: 2, predecessor: 'b' }, + d: { distance: 2, predecessor: 'b' }, }); }); - it("works for undirected graphs", function() { + it('works for undirected graphs', function () { var g = new Graph({ directed: false }); - g.setPath(["a", "b", "c"]); - g.setEdge("b", "d"); - expect(dijkstra(g, "a")).to.eql({ + g.setPath(['a', 'b', 'c']); + g.setEdge('b', 'd'); + expect(dijkstra(g, 'a')).to.eql({ a: { distance: 0 }, - b: { distance: 1, predecessor: "a" }, - c: { distance: 2, predecessor: "b" }, - d: { distance: 2, predecessor: "b" } + b: { distance: 1, predecessor: 'a' }, + c: { distance: 2, predecessor: 'b' }, + d: { distance: 2, predecessor: 'b' }, }); }); - it("uses an optionally supplied weight function", function() { + it('uses an optionally supplied weight function', function () { var g = new Graph(); - g.setEdge("a", "b", 1); - g.setEdge("a", "c", 2); - g.setEdge("b", "d", 3); - g.setEdge("c", "d", 3); + g.setEdge('a', 'b', 1); + g.setEdge('a', 'c', 2); + g.setEdge('b', 'd', 3); + g.setEdge('c', 'd', 3); - expect(dijkstra(g, "a", weightFn(g))).to.eql({ + expect(dijkstra(g, 'a', weightFn(g))).to.eql({ a: { distance: 0 }, - b: { distance: 1, predecessor: "a" }, - c: { distance: 2, predecessor: "a" }, - d: { distance: 4, predecessor: "b" } + b: { distance: 1, predecessor: 'a' }, + c: { distance: 2, predecessor: 'a' }, + d: { distance: 4, predecessor: 'b' }, }); }); - it("uses an optionally supplied edge function", function() { + it('uses an optionally supplied edge function', function () { var g = new Graph(); - g.setPath(["a", "c", "d"]); - g.setEdge("b", "c"); + g.setPath(['a', 'c', 'd']); + g.setEdge('b', 'c'); - expect(dijkstra(g, "d", undefined, function(e) { return g.inEdges(e); })).to.eql({ - a: { distance: 2, predecessor: "c" }, - b: { distance: 2, predecessor: "c" }, - c: { distance: 1, predecessor: "d" }, - d: { distance: 0 } + expect( + dijkstra(g, 'd', undefined, function (e) { + return g.inEdges(e); + }), + ).to.eql({ + a: { distance: 2, predecessor: 'c' }, + b: { distance: 2, predecessor: 'c' }, + c: { distance: 1, predecessor: 'd' }, + d: { distance: 0 }, }); }); - it("throws an Error if it encounters a negative edge weight", function() { + it('throws an Error if it encounters a negative edge weight', function () { var g = new Graph(); - g.setEdge("a", "b", 1); - g.setEdge("a", "c", -2); - g.setEdge("b", "d", 3); - g.setEdge("c", "d", 3); + g.setEdge('a', 'b', 1); + g.setEdge('a', 'c', -2); + g.setEdge('b', 'd', 3); + g.setEdge('c', 'd', 3); - expect(function() { dijkstra(g, "a", weightFn(g)); }).to.throw(); + expect(function () { + dijkstra(g, 'a', weightFn(g)); + }).to.throw(); }); }); function weightFn(g) { - return function(e) { + return function (e) { return g.edge(e); }; } diff --git a/test/alg/find-cycles-test.js b/test/alg/find-cycles-test.js index 62da33a6..31a4dd3e 100644 --- a/test/alg/find-cycles-test.js +++ b/test/alg/find-cycles-test.js @@ -1,50 +1,55 @@ -var _ = require("@snyk/lodash"); -var expect = require("../chai").expect; -var Graph = require("../..").Graph; -var findCycles = require("../..").alg.findCycles; +var _ = require('@snyk/lodash'); +var expect = require('../chai').expect; +var Graph = require('../..').Graph; +var findCycles = require('../..').alg.findCycles; -describe("alg.findCycles", function() { - it("returns an empty array for an empty graph", function() { +describe('alg.findCycles', function () { + it('returns an empty array for an empty graph', function () { expect(findCycles(new Graph())).to.eql([]); }); - it("returns an empty array if the graph has no cycles", function() { + it('returns an empty array if the graph has no cycles', function () { var g = new Graph(); - g.setPath(["a", "b", "c"]); + g.setPath(['a', 'b', 'c']); expect(findCycles(g)).to.eql([]); }); - it("returns a single entry for a cycle of 1 node", function() { + it('returns a single entry for a cycle of 1 node', function () { var g = new Graph(); - g.setPath(["a", "a"]); - expect(sort(findCycles(g))).to.eql([["a"]]); + g.setPath(['a', 'a']); + expect(sort(findCycles(g))).to.eql([['a']]); }); - it("returns a single entry for a cycle of 2 nodes", function() { + it('returns a single entry for a cycle of 2 nodes', function () { var g = new Graph(); - g.setPath(["a", "b", "a"]); - expect(sort(findCycles(g))).to.eql([["a", "b"]]); + g.setPath(['a', 'b', 'a']); + expect(sort(findCycles(g))).to.eql([['a', 'b']]); }); - it("returns a single entry for a triangle", function() { + it('returns a single entry for a triangle', function () { var g = new Graph(); - g.setPath(["a", "b", "c", "a"]); - expect(sort(findCycles(g))).to.eql([["a", "b", "c"]]); + g.setPath(['a', 'b', 'c', 'a']); + expect(sort(findCycles(g))).to.eql([['a', 'b', 'c']]); }); - it("returns multiple entries for multiple cycles", function() { + it('returns multiple entries for multiple cycles', function () { var g = new Graph(); - g.setPath(["a", "b", "a"]); - g.setPath(["c", "d", "e", "c"]); - g.setPath(["f", "g", "g"]); - g.setNode("h"); - expect(sort(findCycles(g))).to.eql([["a", "b"], ["c", "d", "e"], ["g"]]); + g.setPath(['a', 'b', 'a']); + g.setPath(['c', 'd', 'e', 'c']); + g.setPath(['f', 'g', 'g']); + g.setNode('h'); + expect(sort(findCycles(g))).to.eql([['a', 'b'], ['c', 'd', 'e'], ['g']]); }); }); // A helper that sorts components and their contents function sort(cmpts) { - return _.sortBy(_.map(cmpts, function(cmpt) { - return _.sortBy(cmpt); - }), function(cmpts) { return cmpts[0]; }); + return _.sortBy( + _.map(cmpts, function (cmpt) { + return _.sortBy(cmpt); + }), + function (cmpts) { + return cmpts[0]; + }, + ); } diff --git a/test/alg/floyd-warshall-test.js b/test/alg/floyd-warshall-test.js index 700c0ccb..d026d83f 100644 --- a/test/alg/floyd-warshall-test.js +++ b/test/alg/floyd-warshall-test.js @@ -1,62 +1,62 @@ -var expect = require("../chai").expect; -var Graph = require("../..").Graph; -var floydWarshall = require("../..").alg.floydWarshall; -var allShortestPathsTest = require("./all-shortest-paths-test"); +var expect = require('../chai').expect; +var Graph = require('../..').Graph; +var floydWarshall = require('../..').alg.floydWarshall; +var allShortestPathsTest = require('./all-shortest-paths-test'); -describe("alg.floydWarshall", function() { +describe('alg.floydWarshall', function () { allShortestPathsTest.tests(floydWarshall); - it("handles negative weights", function() { + it('handles negative weights', function () { var g = new Graph(); - g.setEdge("a", "b", 1); - g.setEdge("a", "c", -2); - g.setEdge("b", "d", 3); - g.setEdge("c", "d", 3); + g.setEdge('a', 'b', 1); + g.setEdge('a', 'c', -2); + g.setEdge('b', 'd', 3); + g.setEdge('c', 'd', 3); expect(floydWarshall(g, weightFn(g))).to.eql({ a: { - a: { distance: 0 }, - b: { distance: 1, predecessor: "a" }, - c: { distance: -2, predecessor: "a" }, - d: { distance: 1, predecessor: "c" } + a: { distance: 0 }, + b: { distance: 1, predecessor: 'a' }, + c: { distance: -2, predecessor: 'a' }, + d: { distance: 1, predecessor: 'c' }, }, b: { a: { distance: Number.POSITIVE_INFINITY }, b: { distance: 0 }, c: { distance: Number.POSITIVE_INFINITY }, - d: { distance: 3, predecessor: "b" } + d: { distance: 3, predecessor: 'b' }, }, c: { a: { distance: Number.POSITIVE_INFINITY }, b: { distance: Number.POSITIVE_INFINITY }, c: { distance: 0 }, - d: { distance: 3, predecessor: "c" } + d: { distance: 3, predecessor: 'c' }, }, d: { a: { distance: Number.POSITIVE_INFINITY }, b: { distance: Number.POSITIVE_INFINITY }, c: { distance: Number.POSITIVE_INFINITY }, - d: { distance: 0 } - } + d: { distance: 0 }, + }, }); }); - it("does include negative weight self edges", function() { + it('does include negative weight self edges', function () { var g = new Graph(); - g.setEdge("a", "a", -1); + g.setEdge('a', 'a', -1); // In the case of a negative cycle the distance is not well-defined beyond // having a negative value along the diagonal. expect(floydWarshall(g, weightFn(g))).to.eql({ a: { - a: { distance: -2, predecessor: "a" } - } + a: { distance: -2, predecessor: 'a' }, + }, }); }); }); function weightFn(g) { - return function(edge) { + return function (edge) { return g.edge(edge); }; } diff --git a/test/alg/is-acyclic-test.js b/test/alg/is-acyclic-test.js index 03c8f8d1..6979424b 100644 --- a/test/alg/is-acyclic-test.js +++ b/test/alg/is-acyclic-test.js @@ -1,27 +1,29 @@ -var expect = require("../chai").expect; -var Graph = require("../..").Graph; -var isAcyclic = require("../..").alg.isAcyclic; +var expect = require('../chai').expect; +var Graph = require('../..').Graph; +var isAcyclic = require('../..').alg.isAcyclic; -describe("alg.isAcyclic", function() { - it("returns true if the graph has no cycles", function() { +describe('alg.isAcyclic', function () { + it('returns true if the graph has no cycles', function () { var g = new Graph(); - g.setPath(["a", "b", "c"]); + g.setPath(['a', 'b', 'c']); expect(isAcyclic(g)).to.be.true; }); - it("returns false if the graph has at least one cycle", function() { + it('returns false if the graph has at least one cycle', function () { var g = new Graph(); - g.setPath(["a", "b", "c", "a"]); + g.setPath(['a', 'b', 'c', 'a']); expect(isAcyclic(g)).to.be.false; }); - it("returns false if the graph has a cycle of 1 node", function() { + it('returns false if the graph has a cycle of 1 node', function () { var g = new Graph(); - g.setPath(["a", "a"]); + g.setPath(['a', 'a']); expect(isAcyclic(g)).to.be.false; }); - it("rethrows non-CycleException errors", function() { - expect(function() { isAcyclic(undefined); }).to.throw(); + it('rethrows non-CycleException errors', function () { + expect(function () { + isAcyclic(undefined); + }).to.throw(); }); }); diff --git a/test/alg/postorder-test.js b/test/alg/postorder-test.js index 1deec40e..ffb9b24c 100644 --- a/test/alg/postorder-test.js +++ b/test/alg/postorder-test.js @@ -1,67 +1,69 @@ -var _ = require("@snyk/lodash"); -var expect = require("../chai").expect; -var Graph = require("../..").Graph; -var postorder = require("../..").alg.postorder; +var _ = require('@snyk/lodash'); +var expect = require('../chai').expect; +var Graph = require('../..').Graph; +var postorder = require('../..').alg.postorder; -describe("alg.postorder", function() { - it("returns the root for a singleton graph", function() { +describe('alg.postorder', function () { + it('returns the root for a singleton graph', function () { var g = new Graph(); - g.setNode("a"); - expect(postorder(g, "a")).to.eql(["a"]); + g.setNode('a'); + expect(postorder(g, 'a')).to.eql(['a']); }); - it("visits each node in the graph once", function() { + it('visits each node in the graph once', function () { var g = new Graph(); - g.setPath(["a", "b", "d", "e"]); - g.setPath(["a", "c", "d", "e"]); + g.setPath(['a', 'b', 'd', 'e']); + g.setPath(['a', 'c', 'd', 'e']); - var nodes = postorder(g, "a"); - expect(_.sortBy(nodes)).to.eql(["a", "b", "c", "d", "e"]); + var nodes = postorder(g, 'a'); + expect(_.sortBy(nodes)).to.eql(['a', 'b', 'c', 'd', 'e']); }); - it("works for a tree", function() { + it('works for a tree', function () { var g = new Graph(); - g.setEdge("a", "b"); - g.setPath(["a", "c", "d"]); - g.setEdge("c", "e"); + g.setEdge('a', 'b'); + g.setPath(['a', 'c', 'd']); + g.setEdge('c', 'e'); - var nodes = postorder(g, "a"); - expect(_.sortBy(nodes)).to.eql(["a", "b", "c", "d", "e"]); - expect(nodes.indexOf("b")).to.be.lt(nodes.indexOf("a")); - expect(nodes.indexOf("c")).to.be.lt(nodes.indexOf("a")); - expect(nodes.indexOf("d")).to.be.lt(nodes.indexOf("c")); - expect(nodes.indexOf("e")).to.be.lt(nodes.indexOf("c")); + var nodes = postorder(g, 'a'); + expect(_.sortBy(nodes)).to.eql(['a', 'b', 'c', 'd', 'e']); + expect(nodes.indexOf('b')).to.be.lt(nodes.indexOf('a')); + expect(nodes.indexOf('c')).to.be.lt(nodes.indexOf('a')); + expect(nodes.indexOf('d')).to.be.lt(nodes.indexOf('c')); + expect(nodes.indexOf('e')).to.be.lt(nodes.indexOf('c')); }); - it("works for an array of roots", function() { + it('works for an array of roots', function () { var g = new Graph(); - g.setEdge("a", "b"); - g.setEdge("c", "d"); - g.setNode("e"); - g.setNode("f"); + g.setEdge('a', 'b'); + g.setEdge('c', 'd'); + g.setNode('e'); + g.setNode('f'); - var nodes = postorder(g, ["a", "b", "c", "e"]); - expect(_.sortBy(nodes)).to.eql(["a", "b", "c", "d", "e"]); - expect(nodes.indexOf("b")).to.be.lt(nodes.indexOf("a")); - expect(nodes.indexOf("d")).to.be.lt(nodes.indexOf("c")); + var nodes = postorder(g, ['a', 'b', 'c', 'e']); + expect(_.sortBy(nodes)).to.eql(['a', 'b', 'c', 'd', 'e']); + expect(nodes.indexOf('b')).to.be.lt(nodes.indexOf('a')); + expect(nodes.indexOf('d')).to.be.lt(nodes.indexOf('c')); }); - it("works for multiple connected roots", function() { + it('works for multiple connected roots', function () { var g = new Graph(); - g.setEdge("a", "b"); - g.setEdge("a", "c"); - g.setEdge("d", "c"); + g.setEdge('a', 'b'); + g.setEdge('a', 'c'); + g.setEdge('d', 'c'); - var nodes = postorder(g, ["a", "d"]); - expect(_.sortBy(nodes)).to.eql(["a", "b", "c", "d"]); - expect(nodes.indexOf("b")).to.be.lt(nodes.indexOf("a")); - expect(nodes.indexOf("c")).to.be.lt(nodes.indexOf("a")); - expect(nodes.indexOf("c")).to.be.lt(nodes.indexOf("d")); + var nodes = postorder(g, ['a', 'd']); + expect(_.sortBy(nodes)).to.eql(['a', 'b', 'c', 'd']); + expect(nodes.indexOf('b')).to.be.lt(nodes.indexOf('a')); + expect(nodes.indexOf('c')).to.be.lt(nodes.indexOf('a')); + expect(nodes.indexOf('c')).to.be.lt(nodes.indexOf('d')); }); - it("fails if root is not in the graph", function() { + it('fails if root is not in the graph', function () { var g = new Graph(); - g.setNode("a"); - expect(function() { postorder(g, "b"); }).to.throw(); + g.setNode('a'); + expect(function () { + postorder(g, 'b'); + }).to.throw(); }); }); diff --git a/test/alg/preorder-test.js b/test/alg/preorder-test.js index 4d725bfe..af35e2a6 100644 --- a/test/alg/preorder-test.js +++ b/test/alg/preorder-test.js @@ -1,54 +1,56 @@ -var _ = require("@snyk/lodash"); -var expect = require("../chai").expect; -var Graph = require("../..").Graph; -var preorder = require("../..").alg.preorder; +var _ = require('@snyk/lodash'); +var expect = require('../chai').expect; +var Graph = require('../..').Graph; +var preorder = require('../..').alg.preorder; -describe("alg.preorder", function() { - it("returns the root for a singleton graph", function() { +describe('alg.preorder', function () { + it('returns the root for a singleton graph', function () { var g = new Graph(); - g.setNode("a"); - expect(preorder(g, "a")).to.eql(["a"]); + g.setNode('a'); + expect(preorder(g, 'a')).to.eql(['a']); }); - it("visits each node in the graph once", function() { + it('visits each node in the graph once', function () { var g = new Graph(); - g.setPath(["a", "b", "d", "e"]); - g.setPath(["a", "c", "d", "e"]); + g.setPath(['a', 'b', 'd', 'e']); + g.setPath(['a', 'c', 'd', 'e']); - var nodes = preorder(g, "a"); - expect(_.sortBy(nodes)).to.eql(["a", "b", "c", "d", "e"]); + var nodes = preorder(g, 'a'); + expect(_.sortBy(nodes)).to.eql(['a', 'b', 'c', 'd', 'e']); }); - it("works for a tree", function() { + it('works for a tree', function () { var g = new Graph(); - g.setEdge("a", "b"); - g.setPath(["a", "c", "d"]); - g.setEdge("c", "e"); - - var nodes = preorder(g, "a"); - expect(_.sortBy(nodes)).to.eql(["a", "b", "c", "d", "e"]); - expect(nodes.indexOf("b")).to.be.gt(nodes.indexOf("a")); - expect(nodes.indexOf("c")).to.be.gt(nodes.indexOf("a")); - expect(nodes.indexOf("d")).to.be.gt(nodes.indexOf("c")); - expect(nodes.indexOf("e")).to.be.gt(nodes.indexOf("c")); + g.setEdge('a', 'b'); + g.setPath(['a', 'c', 'd']); + g.setEdge('c', 'e'); + + var nodes = preorder(g, 'a'); + expect(_.sortBy(nodes)).to.eql(['a', 'b', 'c', 'd', 'e']); + expect(nodes.indexOf('b')).to.be.gt(nodes.indexOf('a')); + expect(nodes.indexOf('c')).to.be.gt(nodes.indexOf('a')); + expect(nodes.indexOf('d')).to.be.gt(nodes.indexOf('c')); + expect(nodes.indexOf('e')).to.be.gt(nodes.indexOf('c')); }); - it("works for an array of roots", function() { + it('works for an array of roots', function () { var g = new Graph(); - g.setEdge("a", "b"); - g.setEdge("c", "d"); - g.setNode("e"); - g.setNode("f"); - - var nodes = preorder(g, ["a", "c", "e"]); - expect(_.sortBy(nodes)).to.eql(["a", "b", "c", "d", "e"]); - expect(nodes.indexOf("b")).to.be.gt(nodes.indexOf("a")); - expect(nodes.indexOf("d")).to.be.gt(nodes.indexOf("c")); + g.setEdge('a', 'b'); + g.setEdge('c', 'd'); + g.setNode('e'); + g.setNode('f'); + + var nodes = preorder(g, ['a', 'c', 'e']); + expect(_.sortBy(nodes)).to.eql(['a', 'b', 'c', 'd', 'e']); + expect(nodes.indexOf('b')).to.be.gt(nodes.indexOf('a')); + expect(nodes.indexOf('d')).to.be.gt(nodes.indexOf('c')); }); - it("fails if root is not in the graph", function() { + it('fails if root is not in the graph', function () { var g = new Graph(); - g.setNode("a"); - expect(function() { preorder(g, "b"); }).to.throw(); + g.setNode('a'); + expect(function () { + preorder(g, 'b'); + }).to.throw(); }); }); diff --git a/test/alg/prim-test.js b/test/alg/prim-test.js index e94fef9d..f47c87d3 100644 --- a/test/alg/prim-test.js +++ b/test/alg/prim-test.js @@ -1,10 +1,10 @@ -var _ = require("@snyk/lodash"); -var expect = require("../chai").expect; -var Graph = require("../..").Graph; -var prim = require("../..").alg.prim; +var _ = require('@snyk/lodash'); +var expect = require('../chai').expect; +var Graph = require('../..').Graph; +var prim = require('../..').alg.prim; -describe("alg.prim", function() { - it("returns an empty graph for an empty input", function() { +describe('alg.prim', function () { + it('returns an empty graph for an empty input', function () { var source = new Graph(); var g = prim(source, weightFn(source)); @@ -12,45 +12,47 @@ describe("alg.prim", function() { expect(g.edgeCount()).to.equal(0); }); - it("returns a single node graph for a graph with a single node", function() { + it('returns a single node graph for a graph with a single node', function () { var source = new Graph(); - source.setNode("a"); + source.setNode('a'); var g = prim(source, weightFn(source)); - expect(g.nodes()).to.eql(["a"]); + expect(g.nodes()).to.eql(['a']); expect(g.edgeCount()).to.equal(0); }); - it("returns a deterministic result given an optimal solution", function() { + it('returns a deterministic result given an optimal solution', function () { var source = new Graph(); - source.setEdge("a", "b", 1); - source.setEdge("b", "c", 2); - source.setEdge("b", "d", 3); + source.setEdge('a', 'b', 1); + source.setEdge('b', 'c', 2); + source.setEdge('b', 'd', 3); // This edge should not be in the min spanning tree - source.setEdge("c", "d", 20); + source.setEdge('c', 'd', 20); // This edge should not be in the min spanning tree - source.setEdge("c", "e", 60); - source.setEdge("d", "e", 1); + source.setEdge('c', 'e', 60); + source.setEdge('d', 'e', 1); var g = prim(source, weightFn(source)); - expect(_.sortBy(g.neighbors("a"))).to.eql(["b"]); - expect(_.sortBy(g.neighbors("b"))).to.eql(["a", "c", "d"]); - expect(_.sortBy(g.neighbors("c"))).to.eql(["b"]); - expect(_.sortBy(g.neighbors("d"))).to.eql(["b", "e"]); - expect(_.sortBy(g.neighbors("e"))).to.eql(["d"]); + expect(_.sortBy(g.neighbors('a'))).to.eql(['b']); + expect(_.sortBy(g.neighbors('b'))).to.eql(['a', 'c', 'd']); + expect(_.sortBy(g.neighbors('c'))).to.eql(['b']); + expect(_.sortBy(g.neighbors('d'))).to.eql(['b', 'e']); + expect(_.sortBy(g.neighbors('e'))).to.eql(['d']); }); - it("throws an Error for unconnected graphs", function() { + it('throws an Error for unconnected graphs', function () { var source = new Graph(); - source.setNode("a"); - source.setNode("b"); + source.setNode('a'); + source.setNode('b'); - expect(function() { prim(source, weightFn(source)); }).to.throw(); + expect(function () { + prim(source, weightFn(source)); + }).to.throw(); }); }); function weightFn(g) { - return function(edge) { + return function (edge) { return g.edge(edge); }; } diff --git a/test/alg/tarjan-test.js b/test/alg/tarjan-test.js index 89529277..16a5c84c 100644 --- a/test/alg/tarjan-test.js +++ b/test/alg/tarjan-test.js @@ -1,44 +1,49 @@ -var _ = require("@snyk/lodash"); -var expect = require("../chai").expect; -var Graph = require("../..").Graph; -var tarjan = require("../..").alg.tarjan; +var _ = require('@snyk/lodash'); +var expect = require('../chai').expect; +var Graph = require('../..').Graph; +var tarjan = require('../..').alg.tarjan; -describe("alg.tarjan", function() { - it("returns an empty array for an empty graph", function() { +describe('alg.tarjan', function () { + it('returns an empty array for an empty graph', function () { expect(tarjan(new Graph())).to.eql([]); }); - it("returns singletons for nodes not in a strongly connected component", function() { + it('returns singletons for nodes not in a strongly connected component', function () { var g = new Graph(); - g.setPath(["a", "b", "c"]); - g.setEdge("d", "c"); - expect(sort(tarjan(g))).to.eql([["a"], ["b"], ["c"], ["d"]]); + g.setPath(['a', 'b', 'c']); + g.setEdge('d', 'c'); + expect(sort(tarjan(g))).to.eql([['a'], ['b'], ['c'], ['d']]); }); - it("returns a single component for a cycle of 1 edge", function() { + it('returns a single component for a cycle of 1 edge', function () { var g = new Graph(); - g.setPath(["a", "b", "a"]); - expect(sort(tarjan(g))).to.eql([["a", "b"]]); + g.setPath(['a', 'b', 'a']); + expect(sort(tarjan(g))).to.eql([['a', 'b']]); }); - it("returns a single component for a triangle", function() { + it('returns a single component for a triangle', function () { var g = new Graph(); - g.setPath(["a", "b", "c", "a"]); - expect(sort(tarjan(g))).to.eql([["a", "b", "c"]]); + g.setPath(['a', 'b', 'c', 'a']); + expect(sort(tarjan(g))).to.eql([['a', 'b', 'c']]); }); - it("can find multiple components", function() { + it('can find multiple components', function () { var g = new Graph(); - g.setPath(["a", "b", "a"]); - g.setPath(["c", "d", "e", "c"]); - g.setNode("f"); - expect(sort(tarjan(g))).to.eql([["a", "b"], ["c", "d", "e"], ["f"]]); + g.setPath(['a', 'b', 'a']); + g.setPath(['c', 'd', 'e', 'c']); + g.setNode('f'); + expect(sort(tarjan(g))).to.eql([['a', 'b'], ['c', 'd', 'e'], ['f']]); }); }); // A helper that sorts components and their contents function sort(cmpts) { - return _.sortBy(_.map(cmpts, function(cmpt) { - return _.sortBy(cmpt); - }), function(cmpts) { return cmpts[0]; }); + return _.sortBy( + _.map(cmpts, function (cmpt) { + return _.sortBy(cmpt); + }), + function (cmpts) { + return cmpts[0]; + }, + ); } diff --git a/test/alg/topsort-test.js b/test/alg/topsort-test.js index abb8b488..2a8fde9f 100644 --- a/test/alg/topsort-test.js +++ b/test/alg/topsort-test.js @@ -1,48 +1,54 @@ -var expect = require("../chai").expect; -var _ = require("@snyk/lodash"); -var Graph = require("../..").Graph; -var topsort = require("../..").alg.topsort; +var expect = require('../chai').expect; +var _ = require('@snyk/lodash'); +var Graph = require('../..').Graph; +var topsort = require('../..').alg.topsort; -describe("alg.topsort", function() { - it("returns an empty array for an empty graph", function() { +describe('alg.topsort', function () { + it('returns an empty array for an empty graph', function () { expect(topsort(new Graph())).to.be.empty; }); - it("sorts nodes such that earlier nodes have directed edges to later nodes", function() { + it('sorts nodes such that earlier nodes have directed edges to later nodes', function () { var g = new Graph(); - g.setPath(["b", "c", "a"]); - expect(topsort(g)).to.eql(["b", "c", "a"]); + g.setPath(['b', 'c', 'a']); + expect(topsort(g)).to.eql(['b', 'c', 'a']); }); - it("works for a diamond", function() { + it('works for a diamond', function () { var g = new Graph(); - g.setPath(["a", "b", "d"]); - g.setPath(["a", "c", "d"]); + g.setPath(['a', 'b', 'd']); + g.setPath(['a', 'c', 'd']); var result = topsort(g); - expect(_.indexOf(result, "a")).to.equal(0); - expect(_.indexOf(result, "b")).to.be.lt(_.indexOf(result, "d")); - expect(_.indexOf(result, "c")).to.be.lt(_.indexOf(result, "d")); - expect(_.indexOf(result, "d")).to.equal(3); + expect(_.indexOf(result, 'a')).to.equal(0); + expect(_.indexOf(result, 'b')).to.be.lt(_.indexOf(result, 'd')); + expect(_.indexOf(result, 'c')).to.be.lt(_.indexOf(result, 'd')); + expect(_.indexOf(result, 'd')).to.equal(3); }); - it("throws CycleException if there is a cycle #1", function() { + it('throws CycleException if there is a cycle #1', function () { var g = new Graph(); - g.setPath(["b", "c", "a", "b"]); - expect(function() { topsort(g); }).to.throw(topsort.CycleException); + g.setPath(['b', 'c', 'a', 'b']); + expect(function () { + topsort(g); + }).to.throw(topsort.CycleException); }); - it("throws CycleException if there is a cycle #2", function() { + it('throws CycleException if there is a cycle #2', function () { var g = new Graph(); - g.setPath(["b", "c", "a", "b"]); - g.setEdge("b", "d"); - expect(function() { topsort(g); }).to.throw(topsort.CycleException); + g.setPath(['b', 'c', 'a', 'b']); + g.setEdge('b', 'd'); + expect(function () { + topsort(g); + }).to.throw(topsort.CycleException); }); - it("throws CycleException if there is a cycle #3", function() { + it('throws CycleException if there is a cycle #3', function () { var g = new Graph(); - g.setPath(["b", "c", "a", "b"]); - g.setNode("d"); - expect(function() { topsort(g); }).to.throw(topsort.CycleException); + g.setPath(['b', 'c', 'a', 'b']); + g.setNode('d'); + expect(function () { + topsort(g); + }).to.throw(topsort.CycleException); }); }); diff --git a/test/chai.js b/test/chai.js index ba88ca65..152bcefc 100644 --- a/test/chai.js +++ b/test/chai.js @@ -1,4 +1,4 @@ -var chai = require("chai"); +var chai = require('chai'); module.exports = chai; diff --git a/test/data/priority-queue-test.js b/test/data/priority-queue-test.js index 7e778c71..ac7327b1 100644 --- a/test/data/priority-queue-test.js +++ b/test/data/priority-queue-test.js @@ -1,131 +1,140 @@ -var _ = require("@snyk/lodash"); -var expect = require("../chai").expect; -var PriorityQueue = require("../../lib/data/priority-queue"); +var _ = require('@snyk/lodash'); +var expect = require('../chai').expect; +var PriorityQueue = require('../../lib/data/priority-queue'); -describe("data.PriorityQueue", function() { +describe('data.PriorityQueue', function () { var pq; - beforeEach(function() { + beforeEach(function () { pq = new PriorityQueue(); }); - describe("size", function() { - it("returns 0 for an empty queue", function() { + describe('size', function () { + it('returns 0 for an empty queue', function () { expect(pq.size()).to.equal(0); }); - it("returns the number of elements in the queue", function() { - pq.add("a", 1); + it('returns the number of elements in the queue', function () { + pq.add('a', 1); expect(pq.size()).to.equal(1); - pq.add("b", 2); + pq.add('b', 2); expect(pq.size()).to.equal(2); }); }); - describe("keys", function() { - it("returns all of the keys in the queue", function() { - pq.add("a", 1); + describe('keys', function () { + it('returns all of the keys in the queue', function () { + pq.add('a', 1); pq.add(1, 2); pq.add(false, 3); pq.add(undefined, 4); pq.add(null, 5); expect(_.sortBy(pq.keys())).to.eql( - _.sortBy(["a", "1", "false", "undefined", "null"])); + _.sortBy(['a', '1', 'false', 'undefined', 'null']), + ); }); }); - describe("has", function() { - it("returns true if the key is in the queue", function() { - pq.add("a", 1); - expect(pq.has("a")).to.be.true; + describe('has', function () { + it('returns true if the key is in the queue', function () { + pq.add('a', 1); + expect(pq.has('a')).to.be.true; }); - it("returns false if the key is not in the queue", function() { - expect(pq.has("a")).to.be.false; + it('returns false if the key is not in the queue', function () { + expect(pq.has('a')).to.be.false; }); }); - describe("priority", function() { - it("returns the current priority for the key", function() { - pq.add("a", 1); - pq.add("b", 2); - expect(pq.priority("a")).to.equal(1); - expect(pq.priority("b")).to.equal(2); + describe('priority', function () { + it('returns the current priority for the key', function () { + pq.add('a', 1); + pq.add('b', 2); + expect(pq.priority('a')).to.equal(1); + expect(pq.priority('b')).to.equal(2); }); - it("returns undefined if the key is not in the queue", function() { - expect(pq.priority("foo")).to.be.undefined; + it('returns undefined if the key is not in the queue', function () { + expect(pq.priority('foo')).to.be.undefined; }); }); - describe("min", function() { - it("throws an error if there is no element in the queue", function() { - expect(function() { pq.min(); }).to.throw(); + describe('min', function () { + it('throws an error if there is no element in the queue', function () { + expect(function () { + pq.min(); + }).to.throw(); }); - it("returns the smallest element", function() { - pq.add("b", 2); - pq.add("a", 1); - expect(pq.min()).to.equal("a"); + it('returns the smallest element', function () { + pq.add('b', 2); + pq.add('a', 1); + expect(pq.min()).to.equal('a'); }); - it("does not remove the minimum element from the queue", function() { - pq.add("b", 2); - pq.add("a", 1); + it('does not remove the minimum element from the queue', function () { + pq.add('b', 2); + pq.add('a', 1); pq.min(); expect(pq.size()).to.equal(2); }); }); - describe("add", function() { - it("adds the key to the queue", function() { - pq.add("a", 1); - expect(pq.keys()).to.eql(["a"]); + describe('add', function () { + it('adds the key to the queue', function () { + pq.add('a', 1); + expect(pq.keys()).to.eql(['a']); }); - it("returns true if the key was added", function() { - expect(pq.add("a", 1)).to.be.true; + it('returns true if the key was added', function () { + expect(pq.add('a', 1)).to.be.true; }); - it("returns false if the key already exists in the queue", function() { - pq.add("a", 1); - expect(pq.add("a", 1)).to.be.false; + it('returns false if the key already exists in the queue', function () { + pq.add('a', 1); + expect(pq.add('a', 1)).to.be.false; }); }); - describe("removeMin", function() { - it("removes the minimum element from the queue", function() { - pq.add("b", 2); - pq.add("a", 1); - pq.add("c", 3); - pq.add("e", 5); - pq.add("d", 4); - expect(pq.removeMin()).to.equal("a"); - expect(pq.removeMin()).to.equal("b"); - expect(pq.removeMin()).to.equal("c"); - expect(pq.removeMin()).to.equal("d"); - expect(pq.removeMin()).to.equal("e"); - }); - - it("throws an error if there is no element in the queue", function() { - expect(function() { pq.removeMin(); }).to.throw(); + describe('removeMin', function () { + it('removes the minimum element from the queue', function () { + pq.add('b', 2); + pq.add('a', 1); + pq.add('c', 3); + pq.add('e', 5); + pq.add('d', 4); + expect(pq.removeMin()).to.equal('a'); + expect(pq.removeMin()).to.equal('b'); + expect(pq.removeMin()).to.equal('c'); + expect(pq.removeMin()).to.equal('d'); + expect(pq.removeMin()).to.equal('e'); + }); + + it('throws an error if there is no element in the queue', function () { + expect(function () { + pq.removeMin(); + }).to.throw(); }); }); - describe("decrease", function() { - it("decreases the priority of a key", function() { - pq.add("a", 1); - pq.decrease("a", -1); - expect(pq.priority("a")).to.equal(-1); + describe('decrease', function () { + it('decreases the priority of a key', function () { + pq.add('a', 1); + pq.decrease('a', -1); + expect(pq.priority('a')).to.equal(-1); }); - it("raises an error if the key is not in the queue", function() { - expect(function() { pq.decrease("a", -1); }).to.throw(); + it('raises an error if the key is not in the queue', function () { + expect(function () { + pq.decrease('a', -1); + }).to.throw(); }); - it("raises an error if the new priority is greater than current", function() { - pq.add("a", 1); - expect(function() { pq.decrease("a", 2); }).to.throw(); + it('raises an error if the new priority is greater than current', function () { + pq.add('a', 1); + expect(function () { + pq.decrease('a', 2); + }).to.throw(); }); }); }); diff --git a/test/graph-test.js b/test/graph-test.js index e9961dbf..04869c16 100644 --- a/test/graph-test.js +++ b/test/graph-test.js @@ -1,48 +1,48 @@ -var _ = require("@snyk/lodash"); -var expect = require("./chai").expect; -var Graph = require("..").Graph; +var _ = require('@snyk/lodash'); +var expect = require('./chai').expect; +var Graph = require('..').Graph; -describe("Graph", function() { +describe('Graph', function () { var g; - beforeEach(function() { + beforeEach(function () { g = new Graph(); }); - describe("initial state", function() { - it("has no nodes", function() { + describe('initial state', function () { + it('has no nodes', function () { expect(g.nodeCount()).to.equal(0); }); - it("has no edges", function() { + it('has no edges', function () { expect(g.edgeCount()).to.equal(0); }); - it("has no attributes", function() { + it('has no attributes', function () { expect(g.graph()).to.be.undefined; }); - it("defaults to a simple directed graph", function() { + it('defaults to a simple directed graph', function () { expect(g.isDirected()).to.be.true; expect(g.isCompound()).to.be.false; expect(g.isMultigraph()).to.be.false; }); - it("can be set to undirected", function() { + it('can be set to undirected', function () { var g = new Graph({ directed: false }); expect(g.isDirected()).to.be.false; expect(g.isCompound()).to.be.false; expect(g.isMultigraph()).to.be.false; }); - it("can be set to a compound graph", function() { + it('can be set to a compound graph', function () { var g = new Graph({ compound: true }); expect(g.isDirected()).to.be.true; expect(g.isCompound()).to.be.true; expect(g.isMultigraph()).to.be.false; }); - it("can be set to a mulitgraph", function() { + it('can be set to a mulitgraph', function () { var g = new Graph({ multigraph: true }); expect(g.isDirected()).to.be.true; expect(g.isCompound()).to.be.false; @@ -50,926 +50,992 @@ describe("Graph", function() { }); }); - describe("setGraph", function() { - it("can be used to get and set properties for the graph", function() { - g.setGraph("foo"); - expect(g.graph()).to.equal("foo"); + describe('setGraph', function () { + it('can be used to get and set properties for the graph', function () { + g.setGraph('foo'); + expect(g.graph()).to.equal('foo'); }); - it("is chainable", function() { - expect(g.setGraph("foo")).to.equal(g); + it('is chainable', function () { + expect(g.setGraph('foo')).to.equal(g); }); }); - describe("nodes", function() { - it("is empty if there are no nodes in the graph", function() { + describe('nodes', function () { + it('is empty if there are no nodes in the graph', function () { expect(g.nodes()).to.eql([]); }); - it("returns the ids of nodes in the graph", function() { - g.setNode("a"); - g.setNode("b"); - expect(_.sortBy(g.nodes())).to.eql(["a", "b"]); + it('returns the ids of nodes in the graph', function () { + g.setNode('a'); + g.setNode('b'); + expect(_.sortBy(g.nodes())).to.eql(['a', 'b']); }); }); - describe("sources", function() { - it("returns nodes in the graph that have no in-edges", function() { - g.setPath(["a", "b", "c"]); - g.setNode("d"); - expect(_.sortBy(g.sources())).to.eql(["a", "d"]); + describe('sources', function () { + it('returns nodes in the graph that have no in-edges', function () { + g.setPath(['a', 'b', 'c']); + g.setNode('d'); + expect(_.sortBy(g.sources())).to.eql(['a', 'd']); }); }); - describe("sinks", function() { - it("returns nodes in the graph that have no out-edges", function() { - g.setPath(["a", "b", "c"]); - g.setNode("d"); - expect(_.sortBy(g.sinks())).to.eql(["c", "d"]); + describe('sinks', function () { + it('returns nodes in the graph that have no out-edges', function () { + g.setPath(['a', 'b', 'c']); + g.setNode('d'); + expect(_.sortBy(g.sinks())).to.eql(['c', 'd']); }); }); - describe("filterNodes", function() { - it("returns an identical graph when the filter selects everything", function() { - g.setGraph("graph label"); - g.setNode("a", 123); - g.setPath(["a", "b", "c"]); - g.setEdge("a", "c", 456); - var g2 = g.filterNodes(function() { return true; }); - expect(_.sortBy(g2.nodes())).eqls(["a", "b", "c"]); - expect(_.sortBy(g2.successors("a"))).eqls(["b", "c"]); - expect(_.sortBy(g2.successors("b"))).eqls(["c"]); - expect(g2.node("a")).eqls(123); - expect(g2.edge("a", "c")).eqls(456); - expect(g2.graph()).eqls("graph label"); - }); - - it("returns an empty graph when the filter selects nothing", function() { - g.setPath(["a", "b", "c"]); - var g2 = g.filterNodes(function() { return false; }); + describe('filterNodes', function () { + it('returns an identical graph when the filter selects everything', function () { + g.setGraph('graph label'); + g.setNode('a', 123); + g.setPath(['a', 'b', 'c']); + g.setEdge('a', 'c', 456); + var g2 = g.filterNodes(function () { + return true; + }); + expect(_.sortBy(g2.nodes())).eqls(['a', 'b', 'c']); + expect(_.sortBy(g2.successors('a'))).eqls(['b', 'c']); + expect(_.sortBy(g2.successors('b'))).eqls(['c']); + expect(g2.node('a')).eqls(123); + expect(g2.edge('a', 'c')).eqls(456); + expect(g2.graph()).eqls('graph label'); + }); + + it('returns an empty graph when the filter selects nothing', function () { + g.setPath(['a', 'b', 'c']); + var g2 = g.filterNodes(function () { + return false; + }); expect(g2.nodes()).eqls([]); expect(g2.edges()).eqls([]); }); - it("only includes nodes for which the filter returns true", function() { - g.setNodes(["a", "b"]); - var g2 = g.filterNodes(function(v) { return v === "a"; }); - expect(g2.nodes()).eqls(["a"]); + it('only includes nodes for which the filter returns true', function () { + g.setNodes(['a', 'b']); + var g2 = g.filterNodes(function (v) { + return v === 'a'; + }); + expect(g2.nodes()).eqls(['a']); }); - it("removes edges that are connected to removed nodes", function() { - g.setEdge("a", "b"); - var g2 = g.filterNodes(function(v) { return v === "a"; }); - expect(_.sortBy(g2.nodes())).eqls(["a"]); + it('removes edges that are connected to removed nodes', function () { + g.setEdge('a', 'b'); + var g2 = g.filterNodes(function (v) { + return v === 'a'; + }); + expect(_.sortBy(g2.nodes())).eqls(['a']); expect(g2.edges()).eqls([]); }); - it("preserves the directed option", function() { + it('preserves the directed option', function () { g = new Graph({ directed: true }); - expect(g.filterNodes(function() { return true; }).isDirected()).to.be.true; + expect( + g + .filterNodes(function () { + return true; + }) + .isDirected(), + ).to.be.true; g = new Graph({ directed: false }); - expect(g.filterNodes(function() { return true; }).isDirected()).to.be.false; + expect( + g + .filterNodes(function () { + return true; + }) + .isDirected(), + ).to.be.false; }); - it("preserves the multigraph option", function() { + it('preserves the multigraph option', function () { g = new Graph({ multigraph: true }); - expect(g.filterNodes(function() { return true; }).isMultigraph()).to.be.true; + expect( + g + .filterNodes(function () { + return true; + }) + .isMultigraph(), + ).to.be.true; g = new Graph({ multigraph: false }); - expect(g.filterNodes(function() { return true; }).isMultigraph()).to.be.false; + expect( + g + .filterNodes(function () { + return true; + }) + .isMultigraph(), + ).to.be.false; }); - it("preserves the compound option", function() { + it('preserves the compound option', function () { g = new Graph({ compound: true }); - expect(g.filterNodes(function() { return true; }).isCompound()).to.be.true; + expect( + g + .filterNodes(function () { + return true; + }) + .isCompound(), + ).to.be.true; g = new Graph({ compound: false }); - expect(g.filterNodes(function() { return true; }).isCompound()).to.be.false; + expect( + g + .filterNodes(function () { + return true; + }) + .isCompound(), + ).to.be.false; }); - it("includes subgraphs", function() { + it('includes subgraphs', function () { g = new Graph({ compound: true }); - g.setParent("a", "parent"); + g.setParent('a', 'parent'); - var g2 = g.filterNodes(function() { return true; }); - expect(g2.parent("a")).eqls("parent"); + var g2 = g.filterNodes(function () { + return true; + }); + expect(g2.parent('a')).eqls('parent'); }); - it("includes multi-level subgraphs", function() { + it('includes multi-level subgraphs', function () { g = new Graph({ compound: true }); - g.setParent("a", "parent"); - g.setParent("parent", "root"); + g.setParent('a', 'parent'); + g.setParent('parent', 'root'); - var g2 = g.filterNodes(function() { return true; }); - expect(g2.parent("a")).eqls("parent"); - expect(g2.parent("parent")).eqls("root"); + var g2 = g.filterNodes(function () { + return true; + }); + expect(g2.parent('a')).eqls('parent'); + expect(g2.parent('parent')).eqls('root'); }); - it("promotes a node to a higher subgraph if its parent is not included", function() { + it('promotes a node to a higher subgraph if its parent is not included', function () { g = new Graph({ compound: true }); - g.setParent("a", "parent"); - g.setParent("parent", "root"); + g.setParent('a', 'parent'); + g.setParent('parent', 'root'); - var g2 = g.filterNodes(function(v) { return v !== "parent"; }); - expect(g2.parent("a")).eqls("root"); + var g2 = g.filterNodes(function (v) { + return v !== 'parent'; + }); + expect(g2.parent('a')).eqls('root'); }); }); - describe("setNodes", function() { - it("creates multiple nodes", function() { - g.setNodes(["a", "b", "c"]); - expect(g.hasNode("a")).to.be.true; - expect(g.hasNode("b")).to.be.true; - expect(g.hasNode("c")).to.be.true; + describe('setNodes', function () { + it('creates multiple nodes', function () { + g.setNodes(['a', 'b', 'c']); + expect(g.hasNode('a')).to.be.true; + expect(g.hasNode('b')).to.be.true; + expect(g.hasNode('c')).to.be.true; }); - it("can set a value for all of the nodes", function() { - g.setNodes(["a", "b", "c"], "foo"); - expect(g.node("a")).to.equal("foo"); - expect(g.node("b")).to.equal("foo"); - expect(g.node("c")).to.equal("foo"); + it('can set a value for all of the nodes', function () { + g.setNodes(['a', 'b', 'c'], 'foo'); + expect(g.node('a')).to.equal('foo'); + expect(g.node('b')).to.equal('foo'); + expect(g.node('c')).to.equal('foo'); }); - it("is chainable", function() { - expect(g.setNodes(["a", "b", "c"])).to.equal(g); + it('is chainable', function () { + expect(g.setNodes(['a', 'b', 'c'])).to.equal(g); }); }); - describe("setNode", function() { - it("creates the node if it isn't part of the graph", function() { - g.setNode("a"); - expect(g.hasNode("a")).to.be.true; - expect(g.node("a")).to.be.undefined; + describe('setNode', function () { + it("creates the node if it isn't part of the graph", function () { + g.setNode('a'); + expect(g.hasNode('a')).to.be.true; + expect(g.node('a')).to.be.undefined; expect(g.nodeCount()).to.equal(1); }); - it("can set a value for the node", function() { - g.setNode("a", "foo"); - expect(g.node("a")).to.equal("foo"); + it('can set a value for the node', function () { + g.setNode('a', 'foo'); + expect(g.node('a')).to.equal('foo'); }); - it("does not change the node's value with a 1-arg invocation", function() { - g.setNode("a", "foo"); - g.setNode("a"); - expect(g.node("a")).to.equal("foo"); + it("does not change the node's value with a 1-arg invocation", function () { + g.setNode('a', 'foo'); + g.setNode('a'); + expect(g.node('a')).to.equal('foo'); }); - it("can remove the node's value by passing undefined", function() { - g.setNode("a", undefined); - expect(g.node("a")).to.be.undefined; + it("can remove the node's value by passing undefined", function () { + g.setNode('a', undefined); + expect(g.node('a')).to.be.undefined; }); - it("is idempotent", function() { - g.setNode("a", "foo"); - g.setNode("a", "foo"); - expect(g.node("a")).to.equal("foo"); + it('is idempotent', function () { + g.setNode('a', 'foo'); + g.setNode('a', 'foo'); + expect(g.node('a')).to.equal('foo'); expect(g.nodeCount()).to.equal(1); }); - it("uses the stringified form of the id", function() { + it('uses the stringified form of the id', function () { g.setNode(1); expect(g.hasNode(1)).to.be.true; - expect(g.hasNode("1")).to.be.true; - expect(g.nodes()).eqls(["1"]); + expect(g.hasNode('1')).to.be.true; + expect(g.nodes()).eqls(['1']); }); - it("is chainable", function() { - expect(g.setNode("a")).to.equal(g); + it('is chainable', function () { + expect(g.setNode('a')).to.equal(g); }); }); - describe("setNodeDefaults", function() { - it("sets a default label for new nodes", function() { - g.setDefaultNodeLabel("foo"); - g.setNode("a"); - expect(g.node("a")).to.equal("foo"); + describe('setNodeDefaults', function () { + it('sets a default label for new nodes', function () { + g.setDefaultNodeLabel('foo'); + g.setNode('a'); + expect(g.node('a')).to.equal('foo'); }); - it("does not change existing nodes", function() { - g.setNode("a"); - g.setDefaultNodeLabel("foo"); - expect(g.node("a")).to.be.undefined; + it('does not change existing nodes', function () { + g.setNode('a'); + g.setDefaultNodeLabel('foo'); + expect(g.node('a')).to.be.undefined; }); - it("is not used if an explicit value is set", function() { - g.setDefaultNodeLabel("foo"); - g.setNode("a", "bar"); - expect(g.node("a")).to.equal("bar"); + it('is not used if an explicit value is set', function () { + g.setDefaultNodeLabel('foo'); + g.setNode('a', 'bar'); + expect(g.node('a')).to.equal('bar'); }); - it("can take a function", function() { - g.setDefaultNodeLabel(function() { return "foo"; }); - g.setNode("a"); - expect(g.node("a")).to.equal("foo"); + it('can take a function', function () { + g.setDefaultNodeLabel(function () { + return 'foo'; + }); + g.setNode('a'); + expect(g.node('a')).to.equal('foo'); }); - it("can take a function that takes the node's name", function() { - g.setDefaultNodeLabel(function(v) { return v + "-foo"; }); - g.setNode("a"); - expect(g.node("a")).to.equal("a-foo"); + it("can take a function that takes the node's name", function () { + g.setDefaultNodeLabel(function (v) { + return v + '-foo'; + }); + g.setNode('a'); + expect(g.node('a')).to.equal('a-foo'); }); - it("is chainable", function() { - expect(g.setDefaultNodeLabel("foo")).to.equal(g); + it('is chainable', function () { + expect(g.setDefaultNodeLabel('foo')).to.equal(g); }); }); - describe("node", function() { - it("returns undefined if the node isn't part of the graph", function() { - expect(g.node("a")).to.be.undefined; + describe('node', function () { + it("returns undefined if the node isn't part of the graph", function () { + expect(g.node('a')).to.be.undefined; }); - it("returns the value of the node if it is part of the graph", function() { - g.setNode("a", "foo"); - expect(g.node("a")).to.equal("foo"); + it('returns the value of the node if it is part of the graph', function () { + g.setNode('a', 'foo'); + expect(g.node('a')).to.equal('foo'); }); }); - describe("removeNode", function() { - it("does nothing if the node is not in the graph", function() { + describe('removeNode', function () { + it('does nothing if the node is not in the graph', function () { expect(g.nodeCount()).to.equal(0); - g.removeNode("a"); - expect(g.hasNode("a")).to.be.false; + g.removeNode('a'); + expect(g.hasNode('a')).to.be.false; expect(g.nodeCount()).to.equal(0); }); - it("removes the node if it is in the graph", function() { - g.setNode("a"); - g.removeNode("a"); - expect(g.hasNode("a")).to.be.false; + it('removes the node if it is in the graph', function () { + g.setNode('a'); + g.removeNode('a'); + expect(g.hasNode('a')).to.be.false; expect(g.nodeCount()).to.equal(0); }); - it("is idempotent", function() { - g.setNode("a"); - g.removeNode("a"); - g.removeNode("a"); - expect(g.hasNode("a")).to.be.false; + it('is idempotent', function () { + g.setNode('a'); + g.removeNode('a'); + g.removeNode('a'); + expect(g.hasNode('a')).to.be.false; expect(g.nodeCount()).to.equal(0); }); - it("removes edges incident on the node", function() { - g.setEdge("a", "b"); - g.setEdge("b", "c"); - g.removeNode("b"); + it('removes edges incident on the node', function () { + g.setEdge('a', 'b'); + g.setEdge('b', 'c'); + g.removeNode('b'); expect(g.edgeCount()).to.equal(0); }); - it("removes parent / child relationships for the node", function() { + it('removes parent / child relationships for the node', function () { var g = new Graph({ compound: true }); - g.setParent("c", "b"); - g.setParent("b", "a"); - g.removeNode("b"); - expect(g.parent("b")).to.be.undefined; - expect(g.children("b")).to.be.undefined; - expect(g.children("a")).to.not.include("b"); - expect(g.parent("c")).to.be.undefined; + g.setParent('c', 'b'); + g.setParent('b', 'a'); + g.removeNode('b'); + expect(g.parent('b')).to.be.undefined; + expect(g.children('b')).to.be.undefined; + expect(g.children('a')).to.not.include('b'); + expect(g.parent('c')).to.be.undefined; }); - it("is chainable", function() { - expect(g.removeNode("a")).to.equal(g); + it('is chainable', function () { + expect(g.removeNode('a')).to.equal(g); }); }); - describe("setParent", function() { - beforeEach(function() { + describe('setParent', function () { + beforeEach(function () { g = new Graph({ compound: true }); }); - it("throws if the graph is not compound", function() { - expect(function() { new Graph().setParent("a", "parent"); }).to.throw(); + it('throws if the graph is not compound', function () { + expect(function () { + new Graph().setParent('a', 'parent'); + }).to.throw(); }); - it("creates the parent if it does not exist", function() { - g.setNode("a"); - g.setParent("a", "parent"); - expect(g.hasNode("parent")).to.be.true; - expect(g.parent("a")).to.equal("parent"); + it('creates the parent if it does not exist', function () { + g.setNode('a'); + g.setParent('a', 'parent'); + expect(g.hasNode('parent')).to.be.true; + expect(g.parent('a')).to.equal('parent'); }); - it("creates the child if it does not exist", function() { - g.setNode("parent"); - g.setParent("a", "parent"); - expect(g.hasNode("a")).to.be.true; - expect(g.parent("a")).to.equal("parent"); + it('creates the child if it does not exist', function () { + g.setNode('parent'); + g.setParent('a', 'parent'); + expect(g.hasNode('a')).to.be.true; + expect(g.parent('a')).to.equal('parent'); }); - it("has the parent as undefined if it has never been invoked", function() { - g.setNode("a"); - expect(g.parent("a")).to.be.undefined; + it('has the parent as undefined if it has never been invoked', function () { + g.setNode('a'); + expect(g.parent('a')).to.be.undefined; }); - it("moves the node from the previous parent", function() { - g.setParent("a", "parent"); - g.setParent("a", "parent2"); - expect(g.parent("a")).to.equal("parent2"); - expect(g.children("parent")).to.eql([]); - expect(g.children("parent2")).to.eql(["a"]); + it('moves the node from the previous parent', function () { + g.setParent('a', 'parent'); + g.setParent('a', 'parent2'); + expect(g.parent('a')).to.equal('parent2'); + expect(g.children('parent')).to.eql([]); + expect(g.children('parent2')).to.eql(['a']); }); - it("removes the parent if the parent is undefined", function() { - g.setParent("a", "parent"); - g.setParent("a", undefined); - expect(g.parent("a")).to.be.undefined; - expect(_.sortBy(g.children())).to.eql(["a", "parent"]); + it('removes the parent if the parent is undefined', function () { + g.setParent('a', 'parent'); + g.setParent('a', undefined); + expect(g.parent('a')).to.be.undefined; + expect(_.sortBy(g.children())).to.eql(['a', 'parent']); }); - it("removes the parent if no parent was specified", function() { - g.setParent("a", "parent"); - g.setParent("a"); - expect(g.parent("a")).to.be.undefined; - expect(_.sortBy(g.children())).to.eql(["a", "parent"]); + it('removes the parent if no parent was specified', function () { + g.setParent('a', 'parent'); + g.setParent('a'); + expect(g.parent('a')).to.be.undefined; + expect(_.sortBy(g.children())).to.eql(['a', 'parent']); }); - it("is idempotent to remove a parent", function() { - g.setParent("a", "parent"); - g.setParent("a"); - g.setParent("a"); - expect(g.parent("a")).to.be.undefined; - expect(_.sortBy(g.children())).to.eql(["a", "parent"]); + it('is idempotent to remove a parent', function () { + g.setParent('a', 'parent'); + g.setParent('a'); + g.setParent('a'); + expect(g.parent('a')).to.be.undefined; + expect(_.sortBy(g.children())).to.eql(['a', 'parent']); }); - it("uses the stringified form of the id", function() { + it('uses the stringified form of the id', function () { g.setParent(2, 1); g.setParent(3, 2); - expect(g.parent(2)).equals("1"); - expect(g.parent("2")).equals("1"); - expect(g.parent(3)).equals("2"); + expect(g.parent(2)).equals('1'); + expect(g.parent('2')).equals('1'); + expect(g.parent(3)).equals('2'); }); - it("preserves the tree invariant", function() { - g.setParent("c", "b"); - g.setParent("b", "a"); - expect(function() { g.setParent("a", "c"); }).to.throw(); + it('preserves the tree invariant', function () { + g.setParent('c', 'b'); + g.setParent('b', 'a'); + expect(function () { + g.setParent('a', 'c'); + }).to.throw(); }); - it("is chainable", function() { - expect(g.setParent("a", "parent")).to.equal(g); + it('is chainable', function () { + expect(g.setParent('a', 'parent')).to.equal(g); }); }); - describe("parent", function() { - beforeEach(function() { + describe('parent', function () { + beforeEach(function () { g = new Graph({ compound: true }); }); - it("returns undefined if the graph is not compound", function() { - expect(new Graph({ compound: false }).parent("a")).to.be.undefined; + it('returns undefined if the graph is not compound', function () { + expect(new Graph({ compound: false }).parent('a')).to.be.undefined; }); - it("returns undefined if the node is not in the graph", function() { - expect(g.parent("a")).to.be.undefined; + it('returns undefined if the node is not in the graph', function () { + expect(g.parent('a')).to.be.undefined; }); - it("defaults to undefined for new nodes", function() { - g.setNode("a"); - expect(g.parent("a")).to.be.undefined; + it('defaults to undefined for new nodes', function () { + g.setNode('a'); + expect(g.parent('a')).to.be.undefined; }); - it("returns the current parent assignment", function() { - g.setNode("a"); - g.setNode("parent"); - g.setParent("a", "parent"); - expect(g.parent("a")).to.equal("parent"); + it('returns the current parent assignment', function () { + g.setNode('a'); + g.setNode('parent'); + g.setParent('a', 'parent'); + expect(g.parent('a')).to.equal('parent'); }); }); - describe("children", function() { - beforeEach(function() { + describe('children', function () { + beforeEach(function () { g = new Graph({ compound: true }); }); - it("returns undefined if the node is not in the graph", function() { - expect(g.children("a")).to.be.undefined; + it('returns undefined if the node is not in the graph', function () { + expect(g.children('a')).to.be.undefined; }); - it("defaults to en empty list for new nodes", function() { - g.setNode("a"); - expect(g.children("a")).to.eql([]); + it('defaults to en empty list for new nodes', function () { + g.setNode('a'); + expect(g.children('a')).to.eql([]); }); - it("returns undefined for a non-compound graph without the node", function() { + it('returns undefined for a non-compound graph without the node', function () { var g = new Graph(); - expect(g.children("a")).to.be.undefined; + expect(g.children('a')).to.be.undefined; }); - it("returns an empty list for a non-compound graph with the node", function() { + it('returns an empty list for a non-compound graph with the node', function () { var g = new Graph(); - g.setNode("a"); - expect(g.children("a")).eqls([]); + g.setNode('a'); + expect(g.children('a')).eqls([]); }); - it ("returns all nodes for the root of a non-compound graph", function() { + it('returns all nodes for the root of a non-compound graph', function () { var g = new Graph(); - g.setNode("a"); - g.setNode("b"); - expect(_.sortBy(g.children())).eqls(["a", "b"]); + g.setNode('a'); + g.setNode('b'); + expect(_.sortBy(g.children())).eqls(['a', 'b']); }); - it("returns children for the node", function() { - g.setParent("a", "parent"); - g.setParent("b", "parent"); - expect(_.sortBy(g.children("parent"))).to.eql(["a", "b"]); + it('returns children for the node', function () { + g.setParent('a', 'parent'); + g.setParent('b', 'parent'); + expect(_.sortBy(g.children('parent'))).to.eql(['a', 'b']); }); - it("returns all nodes without a parent when the parent is not set", function() { - g.setNode("a"); - g.setNode("b"); - g.setNode("c"); - g.setNode("parent"); - g.setParent("a", "parent"); - expect(_.sortBy(g.children())).to.eql(["b", "c", "parent"]); - expect(_.sortBy(g.children(undefined))).to.eql(["b", "c", "parent"]); + it('returns all nodes without a parent when the parent is not set', function () { + g.setNode('a'); + g.setNode('b'); + g.setNode('c'); + g.setNode('parent'); + g.setParent('a', 'parent'); + expect(_.sortBy(g.children())).to.eql(['b', 'c', 'parent']); + expect(_.sortBy(g.children(undefined))).to.eql(['b', 'c', 'parent']); }); }); - describe("predecessors", function() { - it("returns undefined for a node that is not in the graph", function() { - expect(g.predecessors("a")).to.be.undefined; + describe('predecessors', function () { + it('returns undefined for a node that is not in the graph', function () { + expect(g.predecessors('a')).to.be.undefined; }); - it("returns the predecessors of a node", function() { - g.setEdge("a", "b"); - g.setEdge("b", "c"); - g.setEdge("a", "a"); - expect(_.sortBy(g.predecessors("a"))).to.eql(["a"]); - expect(_.sortBy(g.predecessors("b"))).to.eql(["a"]); - expect(_.sortBy(g.predecessors("c"))).to.eql(["b"]); + it('returns the predecessors of a node', function () { + g.setEdge('a', 'b'); + g.setEdge('b', 'c'); + g.setEdge('a', 'a'); + expect(_.sortBy(g.predecessors('a'))).to.eql(['a']); + expect(_.sortBy(g.predecessors('b'))).to.eql(['a']); + expect(_.sortBy(g.predecessors('c'))).to.eql(['b']); }); }); - describe("successors", function() { - it("returns undefined for a node that is not in the graph", function() { - expect(g.successors("a")).to.be.undefined; + describe('successors', function () { + it('returns undefined for a node that is not in the graph', function () { + expect(g.successors('a')).to.be.undefined; }); - it("returns the successors of a node", function() { - g.setEdge("a", "b"); - g.setEdge("b", "c"); - g.setEdge("a", "a"); - expect(_.sortBy(g.successors("a"))).to.eql(["a", "b"]); - expect(_.sortBy(g.successors("b"))).to.eql(["c"]); - expect(_.sortBy(g.successors("c"))).to.eql([]); + it('returns the successors of a node', function () { + g.setEdge('a', 'b'); + g.setEdge('b', 'c'); + g.setEdge('a', 'a'); + expect(_.sortBy(g.successors('a'))).to.eql(['a', 'b']); + expect(_.sortBy(g.successors('b'))).to.eql(['c']); + expect(_.sortBy(g.successors('c'))).to.eql([]); }); }); - describe("neighbors", function() { - it("returns undefined for a node that is not in the graph", function() { - expect(g.neighbors("a")).to.be.undefined; + describe('neighbors', function () { + it('returns undefined for a node that is not in the graph', function () { + expect(g.neighbors('a')).to.be.undefined; }); - it("returns the neighbors of a node", function() { - g.setEdge("a", "b"); - g.setEdge("b", "c"); - g.setEdge("a", "a"); - expect(_.sortBy(g.neighbors("a"))).to.eql(["a", "b"]); - expect(_.sortBy(g.neighbors("b"))).to.eql(["a", "c"]); - expect(_.sortBy(g.neighbors("c"))).to.eql(["b"]); + it('returns the neighbors of a node', function () { + g.setEdge('a', 'b'); + g.setEdge('b', 'c'); + g.setEdge('a', 'a'); + expect(_.sortBy(g.neighbors('a'))).to.eql(['a', 'b']); + expect(_.sortBy(g.neighbors('b'))).to.eql(['a', 'c']); + expect(_.sortBy(g.neighbors('c'))).to.eql(['b']); }); }); - describe("isLeaf", function() { - it("returns false for connected node in undirected graph", function() { - g = new Graph({directed: false}); - g.setNode("a"); - g.setNode("b"); - g.setEdge("a", "b"); - expect(g.isLeaf("b")).to.be.false; - }); - it("returns true for an unconnected node in undirected graph", function() { - g = new Graph({directed: false}); - g.setNode("a"); - expect(g.isLeaf("a")).to.be.true; - }); - it("returns true for unconnected node in directed graph", function() { - g.setNode("a"); - expect(g.isLeaf("a")).to.be.true; - }); - it("returns false for predecessor node in directed graph", function() { - g.setNode("a"); - g.setNode("b"); - g.setEdge("a", "b"); - expect(g.isLeaf("a")).to.be.false; - }); - it("returns true for successor node in directed graph", function() { - g.setNode("a"); - g.setNode("b"); - g.setEdge("a", "b"); - expect(g.isLeaf("b")).to.be.true; + describe('isLeaf', function () { + it('returns false for connected node in undirected graph', function () { + g = new Graph({ directed: false }); + g.setNode('a'); + g.setNode('b'); + g.setEdge('a', 'b'); + expect(g.isLeaf('b')).to.be.false; + }); + it('returns true for an unconnected node in undirected graph', function () { + g = new Graph({ directed: false }); + g.setNode('a'); + expect(g.isLeaf('a')).to.be.true; + }); + it('returns true for unconnected node in directed graph', function () { + g.setNode('a'); + expect(g.isLeaf('a')).to.be.true; + }); + it('returns false for predecessor node in directed graph', function () { + g.setNode('a'); + g.setNode('b'); + g.setEdge('a', 'b'); + expect(g.isLeaf('a')).to.be.false; + }); + it('returns true for successor node in directed graph', function () { + g.setNode('a'); + g.setNode('b'); + g.setEdge('a', 'b'); + expect(g.isLeaf('b')).to.be.true; }); }); - describe("edges", function() { - it("is empty if there are no edges in the graph", function() { + describe('edges', function () { + it('is empty if there are no edges in the graph', function () { expect(g.edges()).to.eql([]); }); - it("returns the keys for edges in the graph", function() { - g.setEdge("a", "b"); - g.setEdge("b", "c"); - expect(_.sortBy(g.edges(), ["v", "w"])).to.eql([ - { v: "a", w: "b" }, - { v: "b", w: "c" } + it('returns the keys for edges in the graph', function () { + g.setEdge('a', 'b'); + g.setEdge('b', 'c'); + expect(_.sortBy(g.edges(), ['v', 'w'])).to.eql([ + { v: 'a', w: 'b' }, + { v: 'b', w: 'c' }, ]); }); }); - describe("setPath", function() { - it("creates a path of mutiple edges", function() { - g.setPath(["a", "b", "c"]); - expect(g.hasEdge("a", "b")).to.be.true; - expect(g.hasEdge("b", "c")).to.be.true; + describe('setPath', function () { + it('creates a path of mutiple edges', function () { + g.setPath(['a', 'b', 'c']); + expect(g.hasEdge('a', 'b')).to.be.true; + expect(g.hasEdge('b', 'c')).to.be.true; }); - it("can set a value for all of the edges", function() { - g.setPath(["a", "b", "c"], "foo"); - expect(g.edge("a", "b")).to.equal("foo"); - expect(g.edge("b", "c")).to.equal("foo"); + it('can set a value for all of the edges', function () { + g.setPath(['a', 'b', 'c'], 'foo'); + expect(g.edge('a', 'b')).to.equal('foo'); + expect(g.edge('b', 'c')).to.equal('foo'); }); - it("is chainable", function() { - expect(g.setPath(["a", "b", "c"])).to.equal(g); + it('is chainable', function () { + expect(g.setPath(['a', 'b', 'c'])).to.equal(g); }); }); - describe("setEdge", function() { - it("creates the edge if it isn't part of the graph", function() { - g.setNode("a"); - g.setNode("b"); - g.setEdge("a", "b"); - expect(g.edge("a", "b")).to.be.undefined; - expect(g.hasEdge("a", "b")).to.be.true; - expect(g.hasEdge({ v: "a", w: "b" })).to.be.true; + describe('setEdge', function () { + it("creates the edge if it isn't part of the graph", function () { + g.setNode('a'); + g.setNode('b'); + g.setEdge('a', 'b'); + expect(g.edge('a', 'b')).to.be.undefined; + expect(g.hasEdge('a', 'b')).to.be.true; + expect(g.hasEdge({ v: 'a', w: 'b' })).to.be.true; expect(g.edgeCount()).to.equal(1); }); - it("creates the nodes for the edge if they are not part of the graph", function() { - g.setEdge("a", "b"); - expect(g.hasNode("a")).to.be.true; - expect(g.hasNode("b")).to.be.true; + it('creates the nodes for the edge if they are not part of the graph', function () { + g.setEdge('a', 'b'); + expect(g.hasNode('a')).to.be.true; + expect(g.hasNode('b')).to.be.true; expect(g.nodeCount()).to.equal(2); }); - it("creates a multi-edge if if it isn't part of the graph", function() { + it("creates a multi-edge if if it isn't part of the graph", function () { var g = new Graph({ multigraph: true }); - g.setEdge("a", "b", undefined, "name"); - expect(g.hasEdge("a", "b")).to.be.false; - expect(g.hasEdge("a", "b", "name")).to.be.true; + g.setEdge('a', 'b', undefined, 'name'); + expect(g.hasEdge('a', 'b')).to.be.false; + expect(g.hasEdge('a', 'b', 'name')).to.be.true; }); - it("throws if a multi-edge is used with a non-multigraph", function() { - expect(function() { g.setEdge("a", "b", undefined, "name"); }).to.throw(); + it('throws if a multi-edge is used with a non-multigraph', function () { + expect(function () { + g.setEdge('a', 'b', undefined, 'name'); + }).to.throw(); }); - it("changes the value for an edge if it is already in the graph", function() { - g.setEdge("a", "b", "foo"); - g.setEdge("a", "b", "bar"); - expect(g.edge("a", "b")).to.equal("bar"); + it('changes the value for an edge if it is already in the graph', function () { + g.setEdge('a', 'b', 'foo'); + g.setEdge('a', 'b', 'bar'); + expect(g.edge('a', 'b')).to.equal('bar'); }); - it ("deletes the value for the edge if the value arg is undefined", function() { - g.setEdge("a", "b", "foo"); - g.setEdge("a", "b", undefined); - expect(g.edge("a", "b")).to.be.undefined; - expect(g.hasEdge("a", "b")).to.be.true; + it('deletes the value for the edge if the value arg is undefined', function () { + g.setEdge('a', 'b', 'foo'); + g.setEdge('a', 'b', undefined); + expect(g.edge('a', 'b')).to.be.undefined; + expect(g.hasEdge('a', 'b')).to.be.true; }); - it("changes the value for a multi-edge if it is already in the graph", function() { + it('changes the value for a multi-edge if it is already in the graph', function () { var g = new Graph({ multigraph: true }); - g.setEdge("a", "b", "value", "name"); - g.setEdge("a", "b", undefined, "name"); - expect(g.edge("a", "b", "name")).to.be.undefined; - expect(g.hasEdge("a", "b", "name")).to.be.true; + g.setEdge('a', 'b', 'value', 'name'); + g.setEdge('a', 'b', undefined, 'name'); + expect(g.edge('a', 'b', 'name')).to.be.undefined; + expect(g.hasEdge('a', 'b', 'name')).to.be.true; }); - it("can take an edge object as the first parameter", function() { - g.setEdge({ v: "a", w: "b" }, "value"); - expect(g.edge("a", "b")).to.equal("value"); + it('can take an edge object as the first parameter', function () { + g.setEdge({ v: 'a', w: 'b' }, 'value'); + expect(g.edge('a', 'b')).to.equal('value'); }); - it("can take an multi-edge object as the first parameter", function() { + it('can take an multi-edge object as the first parameter', function () { var g = new Graph({ multigraph: true }); - g.setEdge({ v: "a", w: "b", name: "name" }, "value"); - expect(g.edge("a", "b", "name")).to.equal("value"); + g.setEdge({ v: 'a', w: 'b', name: 'name' }, 'value'); + expect(g.edge('a', 'b', 'name')).to.equal('value'); }); - it("uses the stringified form of the id #1", function() { - g.setEdge(1, 2, "foo"); - expect(g.edges()).eqls([{ v: "1", w: "2" }]); - expect(g.edge("1", "2")).to.equal("foo"); - expect(g.edge(1, 2)).to.equal("foo"); + it('uses the stringified form of the id #1', function () { + g.setEdge(1, 2, 'foo'); + expect(g.edges()).eqls([{ v: '1', w: '2' }]); + expect(g.edge('1', '2')).to.equal('foo'); + expect(g.edge(1, 2)).to.equal('foo'); }); - it("uses the stringified form of the id #2", function() { + it('uses the stringified form of the id #2', function () { g = new Graph({ multigraph: true }); - g.setEdge(1, 2, "foo", undefined); - expect(g.edges()).eqls([{ v: "1", w: "2" }]); - expect(g.edge("1", "2")).to.equal("foo"); - expect(g.edge(1, 2)).to.equal("foo"); + g.setEdge(1, 2, 'foo', undefined); + expect(g.edges()).eqls([{ v: '1', w: '2' }]); + expect(g.edge('1', '2')).to.equal('foo'); + expect(g.edge(1, 2)).to.equal('foo'); }); - it("uses the stringified form of the id with a name", function() { + it('uses the stringified form of the id with a name', function () { g = new Graph({ multigraph: true }); - g.setEdge(1, 2, "foo", 3); - expect(g.edge("1", "2", "3")).to.equal("foo"); - expect(g.edge(1, 2, 3)).to.equal("foo"); - expect(g.edges()).eqls([{ v: "1", w: "2", name: "3" }]); + g.setEdge(1, 2, 'foo', 3); + expect(g.edge('1', '2', '3')).to.equal('foo'); + expect(g.edge(1, 2, 3)).to.equal('foo'); + expect(g.edges()).eqls([{ v: '1', w: '2', name: '3' }]); }); - it("treats edges in opposite directions as distinct in a digraph", function() { - g.setEdge("a", "b"); - expect(g.hasEdge("a", "b")).to.be.true; - expect(g.hasEdge("b", "a")).to.be.false; + it('treats edges in opposite directions as distinct in a digraph', function () { + g.setEdge('a', 'b'); + expect(g.hasEdge('a', 'b')).to.be.true; + expect(g.hasEdge('b', 'a')).to.be.false; }); - it("handles undirected graph edges", function() { + it('handles undirected graph edges', function () { var g = new Graph({ directed: false }); - g.setEdge("a", "b", "foo"); - expect(g.edge("a", "b")).to.equal("foo"); - expect(g.edge("b", "a")).to.equal("foo"); + g.setEdge('a', 'b', 'foo'); + expect(g.edge('a', 'b')).to.equal('foo'); + expect(g.edge('b', 'a')).to.equal('foo'); }); - it("handles undirected edges where id has different order than Stringified id", function() { + it('handles undirected edges where id has different order than Stringified id', function () { var g = new Graph({ directed: false }); - g.setEdge(9, 10, "foo"); - expect(g.hasEdge("9", "10")).to.be.true; + g.setEdge(9, 10, 'foo'); + expect(g.hasEdge('9', '10')).to.be.true; expect(g.hasEdge(9, 10)).to.be.true; - expect(g.hasEdge("10", "9")).to.be.true; + expect(g.hasEdge('10', '9')).to.be.true; expect(g.hasEdge(10, 9)).to.be.true; - expect(g.edge("9", "10")).eqls("foo"); - expect(g.edge(9, 10)).eqls("foo"); + expect(g.edge('9', '10')).eqls('foo'); + expect(g.edge(9, 10)).eqls('foo'); }); - it("is chainable", function() { - expect(g.setEdge("a", "b")).to.equal(g); + it('is chainable', function () { + expect(g.setEdge('a', 'b')).to.equal(g); }); }); - describe("setDefaultEdgeLabel", function() { - it("sets a default label for new edges", function() { - g.setDefaultEdgeLabel("foo"); - g.setEdge("a", "b"); - expect(g.edge("a", "b")).to.equal("foo"); + describe('setDefaultEdgeLabel', function () { + it('sets a default label for new edges', function () { + g.setDefaultEdgeLabel('foo'); + g.setEdge('a', 'b'); + expect(g.edge('a', 'b')).to.equal('foo'); }); - it("does not change existing edges", function() { - g.setEdge("a", "b"); - g.setDefaultEdgeLabel("foo"); - expect(g.edge("a", "b")).to.be.undefined; + it('does not change existing edges', function () { + g.setEdge('a', 'b'); + g.setDefaultEdgeLabel('foo'); + expect(g.edge('a', 'b')).to.be.undefined; }); - it("is not used if an explicit value is set", function() { - g.setDefaultEdgeLabel("foo"); - g.setEdge("a", "b", "bar"); - expect(g.edge("a", "b")).to.equal("bar"); + it('is not used if an explicit value is set', function () { + g.setDefaultEdgeLabel('foo'); + g.setEdge('a', 'b', 'bar'); + expect(g.edge('a', 'b')).to.equal('bar'); }); - it("can take a function", function() { - g.setDefaultEdgeLabel(function() { return "foo"; }); - g.setEdge("a", "b"); - expect(g.edge("a", "b")).to.equal("foo"); + it('can take a function', function () { + g.setDefaultEdgeLabel(function () { + return 'foo'; + }); + g.setEdge('a', 'b'); + expect(g.edge('a', 'b')).to.equal('foo'); }); - it("can take a function that takes the edge's endpoints and name", function() { + it("can take a function that takes the edge's endpoints and name", function () { var g = new Graph({ multigraph: true }); - g.setDefaultEdgeLabel(function(v, w, name) { - return v + "-" + w + "-" + name + "-foo"; + g.setDefaultEdgeLabel(function (v, w, name) { + return v + '-' + w + '-' + name + '-foo'; }); - g.setEdge({ v: "a", w: "b", name: "name"}); - expect(g.edge("a", "b", "name")).to.equal("a-b-name-foo"); + g.setEdge({ v: 'a', w: 'b', name: 'name' }); + expect(g.edge('a', 'b', 'name')).to.equal('a-b-name-foo'); }); - it("does not set a default value for a multi-edge that already exists", function() { + it('does not set a default value for a multi-edge that already exists', function () { var g = new Graph({ multigraph: true }); - g.setEdge("a", "b", "old", "name"); - g.setDefaultEdgeLabel(function() { return "should not set this"; }); - g.setEdge({ v: "a", w: "b", name: "name"}); - expect(g.edge("a", "b", "name")).to.equal("old"); + g.setEdge('a', 'b', 'old', 'name'); + g.setDefaultEdgeLabel(function () { + return 'should not set this'; + }); + g.setEdge({ v: 'a', w: 'b', name: 'name' }); + expect(g.edge('a', 'b', 'name')).to.equal('old'); }); - it("is chainable", function() { - expect(g.setDefaultEdgeLabel("foo")).to.equal(g); + it('is chainable', function () { + expect(g.setDefaultEdgeLabel('foo')).to.equal(g); }); }); - describe("edge", function() { - it("returns undefined if the edge isn't part of the graph", function() { - expect(g.edge("a", "b")).to.be.undefined; - expect(g.edge({ v: "a", w: "b" })).to.be.undefined; - expect(g.edge("a", "b", "foo")).to.be.undefined; + describe('edge', function () { + it("returns undefined if the edge isn't part of the graph", function () { + expect(g.edge('a', 'b')).to.be.undefined; + expect(g.edge({ v: 'a', w: 'b' })).to.be.undefined; + expect(g.edge('a', 'b', 'foo')).to.be.undefined; }); - it("returns the value of the edge if it is part of the graph", function() { - g.setEdge("a", "b", { foo: "bar" }); - expect(g.edge("a", "b")).to.eql({ foo: "bar" }); - expect(g.edge({ v: "a", w: "b" })).to.eql({ foo: "bar" }); - expect(g.edge("b", "a")).to.be.undefined; + it('returns the value of the edge if it is part of the graph', function () { + g.setEdge('a', 'b', { foo: 'bar' }); + expect(g.edge('a', 'b')).to.eql({ foo: 'bar' }); + expect(g.edge({ v: 'a', w: 'b' })).to.eql({ foo: 'bar' }); + expect(g.edge('b', 'a')).to.be.undefined; }); - it("returns the value of a multi-edge if it is part of the graph", function() { + it('returns the value of a multi-edge if it is part of the graph', function () { var g = new Graph({ multigraph: true }); - g.setEdge("a", "b", { bar: "baz" }, "foo"); - expect(g.edge("a", "b", "foo")).to.eql({ bar: "baz" }); - expect(g.edge("a", "b")).to.be.undefined; + g.setEdge('a', 'b', { bar: 'baz' }, 'foo'); + expect(g.edge('a', 'b', 'foo')).to.eql({ bar: 'baz' }); + expect(g.edge('a', 'b')).to.be.undefined; }); - it("returns an edge in either direction in an undirected graph", function() { + it('returns an edge in either direction in an undirected graph', function () { var g = new Graph({ directed: false }); - g.setEdge("a", "b", { foo: "bar" }); - expect(g.edge("a", "b")).to.eql({ foo: "bar" }); - expect(g.edge("b", "a")).to.eql({ foo: "bar" }); + g.setEdge('a', 'b', { foo: 'bar' }); + expect(g.edge('a', 'b')).to.eql({ foo: 'bar' }); + expect(g.edge('b', 'a')).to.eql({ foo: 'bar' }); }); }); - describe("removeEdge", function() { - it("has no effect if the edge is not in the graph", function() { - g.removeEdge("a", "b"); - expect(g.hasEdge("a", "b")).to.be.false; + describe('removeEdge', function () { + it('has no effect if the edge is not in the graph', function () { + g.removeEdge('a', 'b'); + expect(g.hasEdge('a', 'b')).to.be.false; expect(g.edgeCount()).to.equal(0); }); - it("can remove an edge by edgeObj", function() { + it('can remove an edge by edgeObj', function () { var g = new Graph({ multigraph: true }); - g.setEdge({ v: "a", w: "b", name: "foo" }); - g.removeEdge({ v: "a", w: "b", name: "foo" }); - expect(g.hasEdge("a", "b", "foo")).to.be.false; + g.setEdge({ v: 'a', w: 'b', name: 'foo' }); + g.removeEdge({ v: 'a', w: 'b', name: 'foo' }); + expect(g.hasEdge('a', 'b', 'foo')).to.be.false; expect(g.edgeCount()).to.equal(0); }); - it("can remove an edge by separate ids", function() { + it('can remove an edge by separate ids', function () { var g = new Graph({ multigraph: true }); - g.setEdge({ v: "a", w: "b", name: "foo" }); - g.removeEdge("a", "b", "foo"); - expect(g.hasEdge("a", "b", "foo")).to.be.false; + g.setEdge({ v: 'a', w: 'b', name: 'foo' }); + g.removeEdge('a', 'b', 'foo'); + expect(g.hasEdge('a', 'b', 'foo')).to.be.false; expect(g.edgeCount()).to.equal(0); }); - it("correctly removes neighbors", function() { - g.setEdge("a", "b"); - g.removeEdge("a", "b"); - expect(g.successors("a")).to.eql([]); - expect(g.neighbors("a")).to.eql([]); - expect(g.predecessors("b")).to.eql([]); - expect(g.neighbors("b")).to.eql([]); + it('correctly removes neighbors', function () { + g.setEdge('a', 'b'); + g.removeEdge('a', 'b'); + expect(g.successors('a')).to.eql([]); + expect(g.neighbors('a')).to.eql([]); + expect(g.predecessors('b')).to.eql([]); + expect(g.neighbors('b')).to.eql([]); }); - it("correctly decrements neighbor counts", function() { + it('correctly decrements neighbor counts', function () { var g = new Graph({ multigraph: true }); - g.setEdge("a", "b"); - g.setEdge({ v: "a", w: "b", name: "foo" }); - g.removeEdge("a", "b"); - expect(g.hasEdge("a", "b", "foo")); - expect(g.successors("a")).to.eql(["b"]); - expect(g.neighbors("a")).to.eql(["b"]); - expect(g.predecessors("b")).to.eql(["a"]); - expect(g.neighbors("b")).to.eql(["a"]); + g.setEdge('a', 'b'); + g.setEdge({ v: 'a', w: 'b', name: 'foo' }); + g.removeEdge('a', 'b'); + expect(g.hasEdge('a', 'b', 'foo')); + expect(g.successors('a')).to.eql(['b']); + expect(g.neighbors('a')).to.eql(['b']); + expect(g.predecessors('b')).to.eql(['a']); + expect(g.neighbors('b')).to.eql(['a']); }); - it("works with undirected graphs", function() { + it('works with undirected graphs', function () { var g = new Graph({ directed: false }); - g.setEdge("h", "g"); - g.removeEdge("g", "h"); - expect(g.neighbors("g")).to.eql([]); - expect(g.neighbors("h")).to.eql([]); + g.setEdge('h', 'g'); + g.removeEdge('g', 'h'); + expect(g.neighbors('g')).to.eql([]); + expect(g.neighbors('h')).to.eql([]); }); - it("is chainable", function() { - g.setEdge("a", "b"); - expect(g.removeEdge("a", "b")).to.equal(g); + it('is chainable', function () { + g.setEdge('a', 'b'); + expect(g.removeEdge('a', 'b')).to.equal(g); }); }); - describe("inEdges", function() { - it("returns undefined for a node that is not in the graph", function() { - expect(g.inEdges("a")).to.be.undefined; + describe('inEdges', function () { + it('returns undefined for a node that is not in the graph', function () { + expect(g.inEdges('a')).to.be.undefined; }); - it("returns the edges that point at the specified node", function() { - g.setEdge("a", "b"); - g.setEdge("b", "c"); - expect(g.inEdges("a")).to.eql([]); - expect(g.inEdges("b")).to.eql([{ v: "a", w: "b" }]); - expect(g.inEdges("c")).to.eql([{ v: "b", w: "c" }]); + it('returns the edges that point at the specified node', function () { + g.setEdge('a', 'b'); + g.setEdge('b', 'c'); + expect(g.inEdges('a')).to.eql([]); + expect(g.inEdges('b')).to.eql([{ v: 'a', w: 'b' }]); + expect(g.inEdges('c')).to.eql([{ v: 'b', w: 'c' }]); }); - it("works for multigraphs", function() { + it('works for multigraphs', function () { var g = new Graph({ multigraph: true }); - g.setEdge("a", "b"); - g.setEdge("a", "b", undefined, "bar"); - g.setEdge("a", "b", undefined, "foo"); - expect(g.inEdges("a")).to.eql([]); - expect(_.sortBy(g.inEdges("b"), "name")).to.eql([ - { v: "a", w: "b", name: "bar" }, - { v: "a", w: "b", name: "foo" }, - { v: "a", w: "b" } + g.setEdge('a', 'b'); + g.setEdge('a', 'b', undefined, 'bar'); + g.setEdge('a', 'b', undefined, 'foo'); + expect(g.inEdges('a')).to.eql([]); + expect(_.sortBy(g.inEdges('b'), 'name')).to.eql([ + { v: 'a', w: 'b', name: 'bar' }, + { v: 'a', w: 'b', name: 'foo' }, + { v: 'a', w: 'b' }, ]); }); - it("can return only edges from a specified node", function() { + it('can return only edges from a specified node', function () { var g = new Graph({ multigraph: true }); - g.setEdge("a", "b"); - g.setEdge("a", "b", undefined, "foo"); - g.setEdge("a", "c"); - g.setEdge("b", "c"); - g.setEdge("z", "a"); - g.setEdge("z", "b"); - expect(g.inEdges("a", "b")).to.eql([]); - expect(_.sortBy(g.inEdges("b", "a"), "name")).to.eql([ - { v: "a", w: "b", name: "foo" }, - { v: "a", w: "b" } + g.setEdge('a', 'b'); + g.setEdge('a', 'b', undefined, 'foo'); + g.setEdge('a', 'c'); + g.setEdge('b', 'c'); + g.setEdge('z', 'a'); + g.setEdge('z', 'b'); + expect(g.inEdges('a', 'b')).to.eql([]); + expect(_.sortBy(g.inEdges('b', 'a'), 'name')).to.eql([ + { v: 'a', w: 'b', name: 'foo' }, + { v: 'a', w: 'b' }, ]); }); }); - describe("outEdges", function() { - it("returns undefined for a node that is not in the graph", function() { - expect(g.outEdges("a")).to.be.undefined; + describe('outEdges', function () { + it('returns undefined for a node that is not in the graph', function () { + expect(g.outEdges('a')).to.be.undefined; }); - it("returns all edges that this node points at", function() { - g.setEdge("a", "b"); - g.setEdge("b", "c"); - expect(g.outEdges("a")).to.eql([{ v: "a", w: "b" }]); - expect(g.outEdges("b")).to.eql([{ v: "b", w: "c" }]); - expect(g.outEdges("c")).to.eql([]); + it('returns all edges that this node points at', function () { + g.setEdge('a', 'b'); + g.setEdge('b', 'c'); + expect(g.outEdges('a')).to.eql([{ v: 'a', w: 'b' }]); + expect(g.outEdges('b')).to.eql([{ v: 'b', w: 'c' }]); + expect(g.outEdges('c')).to.eql([]); }); - it("works for multigraphs", function() { + it('works for multigraphs', function () { var g = new Graph({ multigraph: true }); - g.setEdge("a", "b"); - g.setEdge("a", "b", undefined, "bar"); - g.setEdge("a", "b", undefined, "foo"); - expect(_.sortBy(g.outEdges("a"), "name")).to.eql([ - { v: "a", w: "b", name: "bar" }, - { v: "a", w: "b", name: "foo" }, - { v: "a", w: "b" } + g.setEdge('a', 'b'); + g.setEdge('a', 'b', undefined, 'bar'); + g.setEdge('a', 'b', undefined, 'foo'); + expect(_.sortBy(g.outEdges('a'), 'name')).to.eql([ + { v: 'a', w: 'b', name: 'bar' }, + { v: 'a', w: 'b', name: 'foo' }, + { v: 'a', w: 'b' }, ]); - expect(g.outEdges("b")).to.eql([]); + expect(g.outEdges('b')).to.eql([]); }); - it("can return only edges to a specified node", function() { + it('can return only edges to a specified node', function () { var g = new Graph({ multigraph: true }); - g.setEdge("a", "b"); - g.setEdge("a", "b", undefined, "foo"); - g.setEdge("a", "c"); - g.setEdge("b", "c"); - g.setEdge("z", "a"); - g.setEdge("z", "b"); - expect(_.sortBy(g.outEdges("a", "b"), "name")).to.eql([ - { v: "a", w: "b", name: "foo" }, - { v: "a", w: "b" } + g.setEdge('a', 'b'); + g.setEdge('a', 'b', undefined, 'foo'); + g.setEdge('a', 'c'); + g.setEdge('b', 'c'); + g.setEdge('z', 'a'); + g.setEdge('z', 'b'); + expect(_.sortBy(g.outEdges('a', 'b'), 'name')).to.eql([ + { v: 'a', w: 'b', name: 'foo' }, + { v: 'a', w: 'b' }, ]); - expect(g.outEdges("b", "a")).to.eql([]); + expect(g.outEdges('b', 'a')).to.eql([]); }); }); - describe("nodeEdges", function() { - it("returns undefined for a node that is not in the graph", function() { - expect(g.nodeEdges("a")).to.be.undefined; + describe('nodeEdges', function () { + it('returns undefined for a node that is not in the graph', function () { + expect(g.nodeEdges('a')).to.be.undefined; }); - it("returns all edges that this node points at", function() { - g.setEdge("a", "b"); - g.setEdge("b", "c"); - expect(g.nodeEdges("a")).to.eql([{ v: "a", w: "b" }]); - expect(_.sortBy(g.nodeEdges("b"), ["v", "w"])) - .to.eql([{ v: "a", w: "b" }, { v: "b", w: "c" }]); - expect(g.nodeEdges("c")).to.eql([{ v: "b", w: "c" }]); + it('returns all edges that this node points at', function () { + g.setEdge('a', 'b'); + g.setEdge('b', 'c'); + expect(g.nodeEdges('a')).to.eql([{ v: 'a', w: 'b' }]); + expect(_.sortBy(g.nodeEdges('b'), ['v', 'w'])).to.eql([ + { v: 'a', w: 'b' }, + { v: 'b', w: 'c' }, + ]); + expect(g.nodeEdges('c')).to.eql([{ v: 'b', w: 'c' }]); }); - it("works for multigraphs", function() { + it('works for multigraphs', function () { var g = new Graph({ multigraph: true }); - g.setEdge("a", "b"); - g.setEdge({ v: "a", w: "b", name: "bar" }); - g.setEdge({ v: "a", w: "b", name: "foo" }); - expect(_.sortBy(g.nodeEdges("a"), "name")).to.eql([ - { v: "a", w: "b", name: "bar" }, - { v: "a", w: "b", name: "foo" }, - { v: "a", w: "b" } + g.setEdge('a', 'b'); + g.setEdge({ v: 'a', w: 'b', name: 'bar' }); + g.setEdge({ v: 'a', w: 'b', name: 'foo' }); + expect(_.sortBy(g.nodeEdges('a'), 'name')).to.eql([ + { v: 'a', w: 'b', name: 'bar' }, + { v: 'a', w: 'b', name: 'foo' }, + { v: 'a', w: 'b' }, ]); - expect(_.sortBy(g.nodeEdges("b"), "name")).to.eql([ - { v: "a", w: "b", name: "bar" }, - { v: "a", w: "b", name: "foo" }, - { v: "a", w: "b" } + expect(_.sortBy(g.nodeEdges('b'), 'name')).to.eql([ + { v: 'a', w: 'b', name: 'bar' }, + { v: 'a', w: 'b', name: 'foo' }, + { v: 'a', w: 'b' }, ]); }); - it("can return only edges between specific nodes", function() { + it('can return only edges between specific nodes', function () { var g = new Graph({ multigraph: true }); - g.setEdge("a", "b"); - g.setEdge({ v: "a", w: "b", name: "foo" }); - g.setEdge("a", "c"); - g.setEdge("b", "c"); - g.setEdge("z", "a"); - g.setEdge("z", "b"); - expect(_.sortBy(g.nodeEdges("a", "b"), "name")).to.eql([ - { v: "a", w: "b", name: "foo" }, - { v: "a", w: "b" } + g.setEdge('a', 'b'); + g.setEdge({ v: 'a', w: 'b', name: 'foo' }); + g.setEdge('a', 'c'); + g.setEdge('b', 'c'); + g.setEdge('z', 'a'); + g.setEdge('z', 'b'); + expect(_.sortBy(g.nodeEdges('a', 'b'), 'name')).to.eql([ + { v: 'a', w: 'b', name: 'foo' }, + { v: 'a', w: 'b' }, ]); - expect(_.sortBy(g.nodeEdges("b", "a"), "name")).to.eql([ - { v: "a", w: "b", name: "foo" }, - { v: "a", w: "b" } + expect(_.sortBy(g.nodeEdges('b', 'a'), 'name')).to.eql([ + { v: 'a', w: 'b', name: 'foo' }, + { v: 'a', w: 'b' }, ]); }); }); diff --git a/test/json-test.js b/test/json-test.js index c1fc71d1..762f1d04 100644 --- a/test/json-test.js +++ b/test/json-test.js @@ -1,10 +1,10 @@ -var expect = require("./chai").expect; -var Graph = require("..").Graph; -var read = require("..").json.read; -var write = require("..").json.write; +var expect = require('./chai').expect; +var Graph = require('..').Graph; +var read = require('..').json.read; +var write = require('..').json.write; -describe("json", function() { - it("preserves the graph options", function() { +describe('json', function () { + it('preserves the graph options', function () { expect(rw(new Graph({ directed: true })).isDirected()).to.be.true; expect(rw(new Graph({ directed: false })).isDirected()).to.be.false; expect(rw(new Graph({ multigraph: true })).isMultigraph()).to.be.true; @@ -13,49 +13,54 @@ describe("json", function() { expect(rw(new Graph({ compound: false })).isCompound()).to.be.false; }); - it("preserves the graph value, if any", function() { + it('preserves the graph value, if any', function () { expect(rw(new Graph().setGraph(1)).graph()).equals(1); - expect(rw(new Graph().setGraph({ foo: "bar" })).graph()).eqls({ foo: "bar" }); + expect(rw(new Graph().setGraph({ foo: 'bar' })).graph()).eqls({ + foo: 'bar', + }); expect(rw(new Graph()).graph()).to.be.undefined; }); - it("preserves nodes", function() { - expect(rw(new Graph().setNode("a")).hasNode("a")).to.be.true; - expect(rw(new Graph().setNode("a")).node("a")).to.be.undefined; - expect(rw(new Graph().setNode("a", 1)).node("a")).equals(1); - expect(rw(new Graph().setNode("a", { foo: "bar" })).node("a")) - .eqls({ foo: "bar" }); + it('preserves nodes', function () { + expect(rw(new Graph().setNode('a')).hasNode('a')).to.be.true; + expect(rw(new Graph().setNode('a')).node('a')).to.be.undefined; + expect(rw(new Graph().setNode('a', 1)).node('a')).equals(1); + expect(rw(new Graph().setNode('a', { foo: 'bar' })).node('a')).eqls({ + foo: 'bar', + }); }); - it("preserves simple edges", function() { - expect(rw(new Graph().setEdge("a", "b")).hasEdge("a", "b")).to.be.true; - expect(rw(new Graph().setEdge("a", "b")).edge("a", "b")).to.be.undefined; - expect(rw(new Graph().setEdge("a", "b", 1)).edge("a", "b")).equals(1); - expect(rw(new Graph().setEdge("a", "b", { foo: "bar" })).edge("a", "b")) - .eqls({ foo: "bar" }); + it('preserves simple edges', function () { + expect(rw(new Graph().setEdge('a', 'b')).hasEdge('a', 'b')).to.be.true; + expect(rw(new Graph().setEdge('a', 'b')).edge('a', 'b')).to.be.undefined; + expect(rw(new Graph().setEdge('a', 'b', 1)).edge('a', 'b')).equals(1); + expect( + rw(new Graph().setEdge('a', 'b', { foo: 'bar' })).edge('a', 'b'), + ).eqls({ foo: 'bar' }); }); - it("preserves multi-edges", function() { + it('preserves multi-edges', function () { var g = new Graph({ multigraph: true }); - g.setEdge({ v: "a", w: "b", name: "foo" }); - expect(rw(g).hasEdge("a", "b", "foo")).to.be.true; + g.setEdge({ v: 'a', w: 'b', name: 'foo' }); + expect(rw(g).hasEdge('a', 'b', 'foo')).to.be.true; - g.setEdge({ v: "a", w: "b", name: "foo" }); - expect(rw(g).edge("a", "b", "foo")).to.be.undefined; + g.setEdge({ v: 'a', w: 'b', name: 'foo' }); + expect(rw(g).edge('a', 'b', 'foo')).to.be.undefined; - g.setEdge({ v: "a", w: "b", name: "foo" }, 1); - expect(rw(g).edge("a", "b", "foo")).equals(1); + g.setEdge({ v: 'a', w: 'b', name: 'foo' }, 1); + expect(rw(g).edge('a', 'b', 'foo')).equals(1); - g.setEdge({ v: "a", w: "b", name: "foo" }, { foo: "bar" }); - expect(rw(g).edge("a", "b", "foo")).eqls({ foo: "bar" }); + g.setEdge({ v: 'a', w: 'b', name: 'foo' }, { foo: 'bar' }); + expect(rw(g).edge('a', 'b', 'foo')).eqls({ foo: 'bar' }); }); - it("preserves parent / child relationships", function() { - expect(rw(new Graph({ compound: true }).setNode("a")).parent("a")) - .to.be.undefined; - expect(rw(new Graph({ compound: true }).setParent("a", "parent")).parent("a")) - .to.equal("parent"); + it('preserves parent / child relationships', function () { + expect(rw(new Graph({ compound: true }).setNode('a')).parent('a')).to.be + .undefined; + expect( + rw(new Graph({ compound: true }).setParent('a', 'parent')).parent('a'), + ).to.equal('parent'); }); }); diff --git a/test/test-main.js b/test/test-main.js index dbec2c69..894a7b11 100644 --- a/test/test-main.js +++ b/test/test-main.js @@ -4,7 +4,7 @@ var allTestFiles = []; var TEST_REGEXP = /(spec|test)\.js$/i; // Get a list of all the test files to include -Object.keys(this.__karma__.files).forEach(function(file) { +Object.keys(this.__karma__.files).forEach(function (file) { if (TEST_REGEXP.test(file)) { // Normalize paths to RequireJS module names. // If you require sub-dependencies of test files to be loaded as-is (requiring file extension) @@ -18,23 +18,23 @@ require.config({ // Karma serves files under /base, which is the basePath from your config file baseUrl: '/base', - paths:{ + paths: { chai: 'node_modules/chai/chai', '@snyk/lodash': 'node_modules/@snyk/lodash/lodash', graphlib: 'build/graphlib', - 'graphlib.core': 'build/graphlib.core' + 'graphlib.core': 'build/graphlib.core', }, shim: { 'graphlib.core': { deps: ['@snyk/lodash'], - exports: 'graphlib.core' //any even not existing var could be defined here. - } + exports: 'graphlib.core', //any even not existing var could be defined here. + }, }, // dynamically load all test files deps: allTestFiles, // we have to kickoff jasmine, as it is asynchronous - callback: this.__karma__.start + callback: this.__karma__.start, }); diff --git a/test/version-test.js b/test/version-test.js index e8b2d205..9c7868d0 100644 --- a/test/version-test.js +++ b/test/version-test.js @@ -1,7 +1,7 @@ var expect = require('./chai').expect; -describe('version', function() { - it('should match the version from package.json', function() { +describe('version', function () { + it('should match the version from package.json', function () { var packageVersion = require('../package').version; expect(require('../lib/version')).to.equal(packageVersion); }); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..03840212 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "outDir": "./dist", + "target": "es2017", + "lib": ["es2017"], + "module": "commonjs", + "allowSyntheticDefaultImports": true, + "allowJs": false, + "esModuleInterop": true, + "declaration": true, + "sourceMap": true, + "pretty": true, + "strict": true, + "noImplicitAny": true, + "noUnusedLocals": true, + "noImplicitReturns": true + }, + "include": ["./lib/**/*"] +}