node-uglifier-es
Version:
Fully auto merging and uglifying a whole NodeJs project into one file with external files option. Recompiled from Zsolt Istvan Szabo's work with uglify-es instead of uglify-js-harmony.
1,353 lines (1,084 loc) • 44.4 kB
JavaScript
;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
define([".", "matchers"], function (Graph) {////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var graph;
beforeEach(function () {
graph = new Graph();
});
describe("method", function () {////////////////////////////////////////////////////////////////////////////////
var methodUnderTest = "";
function describeMethod(method, fn) {
describe("'" + method + "'", function () {
beforeEach(function () {
methodUnderTest = method;
});
it("is present", function () {
expect(typeof graph[methodUnderTest]).toBe('function');
});
fn();
});
}
function callItWith() {
return graph[methodUnderTest].apply(undefined, arguments);
}
function expectItWhenBoundWith() {
var args = arguments;
return expect(function () {
graph[methodUnderTest].apply(undefined, args);
});
}
function expectItWhenCalledWith() {
var args = Array.prototype.slice.call(arguments, 0);
return expect(graph[methodUnderTest].apply(undefined, args));
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
var originalVertices, originalEdges, originalVertexCount, originalEdgeCount;
function expectTheGraphNotToHaveChanged() {
var vertices = {};
graph.eachVertex(function (key, value) {
vertices[key] = value;
});
expect(vertices).toEqual(originalVertices);
var edges = {};
graph.eachEdge(function (from, to, value) {
edges[from + ", " + to] = value;
});
expect(edges).toEqual(originalEdges);
}
beforeEach(function () {
//// the original graph:
//
graph.addNewVertex('k1', 'oldValue1');
graph.addNewVertex('k2');
graph.addNewVertex('k3');
graph.addNewVertex('k4');
graph.addNewVertex('k5', 'oldValue5');
graph.addNewEdge('k2', 'k3', 'oldValue23');
graph.addNewEdge('k3', 'k4');
graph.addNewEdge('k2', 'k5');
graph.addNewEdge('k5', 'k3');
// k1 k2 --> k3 --> k4
// | ^
// | ;
// V /
// k5 __/
//// some preliminary work to more easily 'expect' things about the original graph:
//
originalVertices = {
'k1': 'oldValue1',
'k2': undefined,
'k3': undefined,
'k4': undefined,
'k5': 'oldValue5'
};
originalEdges = {
'k2, k3': 'oldValue23',
'k3, k4': undefined,
'k2, k5': undefined,
'k5, k3': undefined
};
originalVertexCount = Object.keys(originalVertices).length;
originalEdgeCount = Object.keys(originalEdges).length;
//// and we now 'expect' that those variables are set correctly
//
expectTheGraphNotToHaveChanged();
});
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
describeMethod('vertexCount', function () {
it("throws nothing", function () {
expectItWhenBoundWith().not.toThrow();
});
it("returns the number of vertices in the graph", function () {
expectItWhenCalledWith().toBe(originalVertexCount);
});
});
describeMethod('edgeCount', function () {
it("throws nothing", function () {
expectItWhenBoundWith().not.toThrow();
});
it("returns the number of edges in the graph", function () {
expectItWhenCalledWith().toBe(originalEdgeCount);
});
});
describeMethod('hasVertex', function () {
it("throws nothing when passed a key argument", function () {
expectItWhenBoundWith('k1').not.toThrow();
expectItWhenBoundWith('newKey').not.toThrow();
});
it("returns a truthy value for an existing vertex", function () {
expectItWhenCalledWith('k1').toBeTruthy();
expectItWhenCalledWith('k2').toBeTruthy();
});
it("returns a falsy value for an absent vertex", function () {
expectItWhenCalledWith('newKey').toBeFalsy();
});
});
describeMethod('hasEdge', function () {
it("throws nothing when passed two key arguments", function () {
expectItWhenBoundWith('k1', 'k2').not.toThrow();
expectItWhenBoundWith('k2', 'k3').not.toThrow();
expectItWhenBoundWith('newKey', 'k2').not.toThrow();
expectItWhenBoundWith('newKey1', 'newKey2').not.toThrow();
});
it("returns a truthy value for an existing edge", function () {
expectItWhenCalledWith('k2', 'k3').toBeTruthy();
expectItWhenCalledWith('k3', 'k4').toBeTruthy();
});
it("returns a falsy value for an absent edge", function () {
expectItWhenCalledWith('k1', 'k2').toBeFalsy();
expectItWhenCalledWith('k3', 'k2').toBeFalsy();
expectItWhenCalledWith('newKey', 'k2').toBeFalsy();
expectItWhenCalledWith('newKey1', 'newKey2').toBeFalsy();
});
});
describeMethod('vertexValue', function () {
it("throws nothing when passed a key argument", function () {
expectItWhenBoundWith('k1').not.toThrow();
expectItWhenBoundWith('k2').not.toThrow();
expectItWhenBoundWith('newKey').not.toThrow();
});
it("returns the proper value belonging to a vertex", function () {
expectItWhenCalledWith('k1').toBe('oldValue1');
});
it("returns the 'undefined' value for vertices with no value", function () {
expectItWhenCalledWith('k2').toBeUndefined();
});
it("returns the 'undefined' value for absent vertices", function () {
expectItWhenCalledWith('newKey').toBeUndefined();
});
});
describeMethod('edgeValue', function () {
it("throws nothing when passed two key arguments", function () {
expectItWhenBoundWith('k1', 'k2').not.toThrow();
expectItWhenBoundWith('k2', 'k3').not.toThrow();
expectItWhenBoundWith('newKey', 'k2').not.toThrow();
expectItWhenBoundWith('newKey1', 'newKey2').not.toThrow();
});
it("returns the proper value belonging to an edge", function () {
expectItWhenCalledWith('k2', 'k3').toBe('oldValue23');
});
it("returns the 'undefined' value for edges with no value", function () {
expectItWhenCalledWith('k3', 'k4').toBeUndefined();
});
it("returns the 'undefined' value for absent edges", function () {
expectItWhenCalledWith('k1', 'k2').toBeUndefined();
expectItWhenCalledWith('k3', 'k2').toBeUndefined();
expectItWhenCalledWith('newKey', 'k2').toBeUndefined();
expectItWhenCalledWith('newKey1', 'newKey2').toBeUndefined();
});
});
describeMethod('eachVertex', function () {
it("throws nothing when passed a non-throwing function", function () {
expectItWhenBoundWith(function () {/*not throwing things*/}).not.toThrow();
});
it("does not change the graph if the specified handler doesn't", function () {
callItWith(function () {
// not changing the graph from here
});
expectTheGraphNotToHaveChanged();
});
it("calls the specified handler exactly once for each vertex in the graph", function () {
var verticesFound = {};
callItWith(function (key, value) {
expect(verticesFound[key]).toBeUndefined();
verticesFound[key] = value;
});
expect(verticesFound).toEqual(originalVertices);
});
});
describeMethod('eachVertexFrom', function () {
it("throws an error if the given vertex does not exist", function () {
expectItWhenBoundWith('newKey', function () {}).toThrow();
expectItWhenBoundWith('newKey', function () {}).toThrowSpecific(Graph.VertexNotExistsError, {'newKey': undefined});
});
it("throws nothing if the given vertex exists", function () {
expectItWhenBoundWith('k1', function () {}).not.toThrow();
});
it("does not change the graph if the specified handler doesn't", function () {
callItWith('k2', function () {
// not changing the graph from here
});
expectTheGraphNotToHaveChanged();
});
it("calls the specified handler exactly once for each outgoing edge, providing the connected vertex key/value and edge value", function () {
var valuesFound = {};
callItWith('k2', function (key, value, edgeValue) {
expect(valuesFound[key]).toBeUndefined();
valuesFound[key] = [value, edgeValue];
});
expect(valuesFound).toEqual({
'k3': [undefined, 'oldValue23'],
'k5': ['oldValue5', undefined]
});
});
});
describeMethod('eachVertexTo', function () {
it("throws an error if the given vertex does not exist", function () {
expectItWhenBoundWith('newKey', function () {}).toThrow();
expectItWhenBoundWith('newKey', function () {}).toThrowSpecific(Graph.VertexNotExistsError, {'newKey': undefined});
});
it("throws nothing if the given vertex exists", function () {
expectItWhenBoundWith('k1', function () {}).not.toThrow();
});
it("does not change the graph if the specified handler doesn't", function () {
callItWith('k3', function () {
// not changing the graph from here
});
expectTheGraphNotToHaveChanged();
});
it("calls the specified handler exactly once for each incoming edge, providing the connected vertex key/value and edge value", function () {
var valuesFound = {};
callItWith('k3', function (key, value, edgeValue) {
expect(valuesFound[key]).toBeUndefined();
valuesFound[key] = [value, edgeValue];
});
expect(valuesFound).toEqual({
'k2': [undefined, 'oldValue23'],
'k5': ['oldValue5', undefined]
});
});
});
describeMethod('eachEdge', function () {
it("throws nothing when passed a non-throwing function", function () {
expectItWhenBoundWith(function () {/*not throwing things*/}).not.toThrow();
});
it("does not change the graph if the specified handler doesn't", function () {
callItWith(function () {
// not changing the graph from here
});
expectTheGraphNotToHaveChanged();
});
it("calls the specified handler exactly once for each edge in the graph", function () {
var edgesFound = {};
callItWith(function (from, to, value) {
var key = from + ", " + to;
expect(edgesFound[key]).toBeUndefined();
edgesFound[key] = value;
});
expect(edgesFound).toEqual(originalEdges);
});
});
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
function it_throwsErrorIfVertexExists() {
it("throws an error if a vertex with the given key already exists", function () {
expectItWhenBoundWith('k1').toThrow();
expectItWhenBoundWith('k2').toThrow();
expectItWhenBoundWith('k1').toThrowSpecific(Graph.VertexExistsError, { vertices: {'k1': 'oldValue1'} });
expectItWhenBoundWith('k2').toThrowSpecific(Graph.VertexExistsError, { vertices: {'k2': undefined} });
});
}
function it_throwsErrorIfVertexDoesNotExist() {
it("throws an error if a vertex with the given key does not exist", function () {
expectItWhenBoundWith('newKey').toThrow();
expectItWhenBoundWith('newKey').toThrowSpecific(Graph.VertexNotExistsError, { vertices: {'newKey': undefined} });
});
}
function it_throwsErrorIfEdgesAreConnected() {
it("throws an error if there are edges connected to that vertex", function () {
expectItWhenBoundWith('k2').toThrow();
expectItWhenBoundWith('k3').toThrow();
expectItWhenBoundWith('k4').toThrow();
expectItWhenBoundWith('k2').toThrowSpecific(Graph.HasConnectedEdgesError, { key: 'k2' });
expectItWhenBoundWith('k3').toThrowSpecific(Graph.HasConnectedEdgesError, { key: 'k3' });
expectItWhenBoundWith('k4').toThrowSpecific(Graph.HasConnectedEdgesError, { key: 'k4' });
});
}
function it_throwsNothingIfVertexDoesNotExist() {
it("throws no exceptions if a vertex with that key does not exist", function () {
expectItWhenBoundWith('newKey').not.toThrow();
});
}
function it_throwsNothingIfVertexExists() {
it("throws no exceptions if a vertex with that key exists", function () {
expectItWhenBoundWith('k3').not.toThrow();
});
}
function it_throwsNothingIfUnconnectedVertexExists() {
it("throws no exceptions if a vertex with that key exists, not connected to any edges", function () {
expectItWhenBoundWith('k1').not.toThrow();
});
}
function it_throwsNothingWhenPassedAKey() {
it("throws no exceptions when it is passed a single key argument", function () {
expectItWhenBoundWith('k1').not.toThrow();
expectItWhenBoundWith('newKey').not.toThrow();
});
}
function it_throwsNothingWhenPassedAKeyAndValue() {
it("throws no exceptions when it is passed a key and a value argument", function () {
expectItWhenBoundWith('k1', 'newValue').not.toThrow();
expectItWhenBoundWith('newKey', 'newValue').not.toThrow();
});
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
function it_leavesNewVertexWithNewValue() {
it("leaves a new vertex in the graph with a new value", function () {
callItWith('newKey', 'newValue');
expect(graph.hasVertex('newKey')).toBeTruthy();
expect(graph.vertexValue('newKey')).toBe('newValue');
expect(graph.vertexCount()).toBe(originalVertexCount + 1);
});
}
function it_leavesNewVertexWithNewUndefinedValue() {
it("leaves a new vertex in the graph with a new 'undefined' value", function () {
callItWith('newKey');
expect(graph.hasVertex('newKey')).toBeTruthy();
expect(graph.vertexValue('newKey')).toBeUndefined();
expect(graph.vertexCount()).toBe(originalVertexCount + 1);
});
}
function it_leavesExistingVertexWithNewValue() {
it("leaves an existing vertex in the graph with a new value", function () {
callItWith('k1', 'newValue');
expect(graph.hasVertex('k1')).toBeTruthy();
expect(graph.vertexValue('k1')).toBe('newValue');
expect(graph.vertexCount()).toBe(originalVertexCount);
});
}
function it_leavesExistingVertexWithNewUndefinedValue() {
it("leaves an existing vertex in the graph with a new 'undefined' value", function () {
callItWith('k1');
expect(graph.hasVertex('k1')).toBeTruthy();
expect(graph.vertexValue('k1')).toBeUndefined();
expect(graph.vertexCount()).toBe(originalVertexCount);
});
}
function it_leavesExistingVertexWithOldValue() {
it("leaves an existing vertex in the graph with its old value", function () {
callItWith('k1', 'newValue');
expect(graph.hasVertex('k1')).toBeTruthy();
expect(graph.vertexValue('k1')).toBe('oldValue1');
expect(graph.vertexCount()).toBe(originalVertexCount);
callItWith('k1', undefined);
expect(graph.hasVertex('k1')).toBeTruthy();
expect(graph.vertexValue('k1')).toBe('oldValue1');
expect(graph.vertexCount()).toBe(originalVertexCount);
});
}
function it_leavesExistingVertexWithOldUndefinedValue() {
it("leaves an existing vertex in the graph with its old 'undefined' value", function () {
callItWith('k2', 'newValue');
expect(graph.hasVertex('k2')).toBeTruthy();
expect(graph.vertexValue('k2')).toBeUndefined();
expect(graph.vertexCount()).toBe(originalVertexCount);
});
}
function it_leavesExistingVertexAbsent() {
it("leaves an existing vertex absent from the graph", function () {
callItWith('k1');
expect(graph.hasVertex('k1')).toBeFalsy();
expect(graph.vertexCount()).toBe(originalVertexCount - 1);
});
}
function it_leavesConnectedEdgesAbsent() {
it("leaves existing connected edges absent from the graph", function () {
callItWith('k3');
expect(graph.hasEdge('k2', 'k3')).toBeFalsy();
expect(graph.hasEdge('k3', 'k4')).toBeFalsy();
expect(graph.hasEdge('k4', 'k3')).toBeFalsy();
expect(graph.edgeCount()).toBe(originalEdgeCount - 3);
});
}
function it_leavesAbsentVertexAbsent() {
it("leaves an absent vertex absent from the graph", function () {
callItWith('newKey');
expect(graph.hasVertex('newKey')).toBeFalsy();
expect(graph.vertexCount()).toBe(originalVertexCount);
});
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
describeMethod('addNewVertex', function () {
it_throwsErrorIfVertexExists();
it_throwsNothingIfVertexDoesNotExist();
it_leavesNewVertexWithNewValue();
it_leavesNewVertexWithNewUndefinedValue();
});
describeMethod('setVertex', function () {
it_throwsErrorIfVertexDoesNotExist();
it_throwsNothingIfVertexExists();
it_leavesExistingVertexWithNewValue();
it_leavesExistingVertexWithNewUndefinedValue();
});
describeMethod('ensureVertex', function () {
it_throwsNothingWhenPassedAKey();
it_throwsNothingWhenPassedAKeyAndValue();
it_leavesNewVertexWithNewValue();
it_leavesNewVertexWithNewUndefinedValue();
it_leavesExistingVertexWithOldValue();
it_leavesExistingVertexWithOldUndefinedValue();
});
describeMethod('addVertex', function () {
it_throwsNothingWhenPassedAKey();
it_throwsNothingWhenPassedAKeyAndValue();
it_leavesNewVertexWithNewValue();
it_leavesNewVertexWithNewUndefinedValue();
it_leavesExistingVertexWithNewValue();
it_leavesExistingVertexWithNewUndefinedValue();
});
describeMethod('removeExistingVertex', function () {
it_throwsErrorIfVertexDoesNotExist();
it_throwsErrorIfEdgesAreConnected();
it_throwsNothingIfUnconnectedVertexExists();
it_leavesExistingVertexAbsent();
});
describeMethod('destroyExistingVertex', function () {
it_throwsErrorIfVertexDoesNotExist();
it_throwsNothingIfVertexExists();
it_leavesExistingVertexAbsent();
it_leavesConnectedEdgesAbsent();
});
describeMethod('removeVertex', function () {
it_throwsErrorIfEdgesAreConnected();
it_throwsNothingIfUnconnectedVertexExists();
it_leavesExistingVertexAbsent();
it_leavesAbsentVertexAbsent();
});
describeMethod('destroyVertex', function () {
it_throwsNothingWhenPassedAKey();
it_leavesExistingVertexAbsent();
it_leavesAbsentVertexAbsent();
it_leavesConnectedEdgesAbsent();
});
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
function it_throwsErrorIfEdgeExists() {
it("throws an error if an edge with the given keys already exists", function () {
expectItWhenBoundWith('k2', 'k3').toThrow();
expectItWhenBoundWith('k3', 'k4').toThrow();
expectItWhenBoundWith('k2', 'k3').toThrowSpecific(Graph.EdgeExistsError, { edges: {'k2': {'k3': 'oldValue23'}} });
expectItWhenBoundWith('k3', 'k4').toThrowSpecific(Graph.EdgeExistsError, { edges: {'k3': {'k4': undefined}} });
});
}
function it_throwsErrorIfEdgeDoesNotExist() {
it("throws an error if an edge with the given keys does not exist", function () {
expectItWhenBoundWith('k1', 'k2').toThrow();
expectItWhenBoundWith('k1', 'k2').toThrowSpecific(Graph.EdgeNotExistsError, { edges: {'k1': {'k2': undefined}} });
});
}
function it_throwsErrorIfVerticesDoNotExist() {
it("throws an error if the required vertices do not exist", function () {
expectItWhenBoundWith('newKey1', 'newKey2').toThrow();
expectItWhenBoundWith('k1', 'newKey3').toThrow();
expectItWhenBoundWith('newKey4', 'k2').toThrow();
expectItWhenBoundWith('newKey1', 'newKey2').toThrowSpecific(Graph.VertexNotExistsError, { vertices: {'newKey1': undefined, 'newKey2': undefined} });
expectItWhenBoundWith('k1', 'newKey3').toThrowSpecific(Graph.VertexNotExistsError, { vertices: {'newKey3': undefined} });
expectItWhenBoundWith('newKey4', 'k2').toThrowSpecific(Graph.VertexNotExistsError, { vertices: {'newKey4': undefined} });
});
}
function it_throwsNothingIfEdgeDoesNotExist() {
it("throws nothing if the edge does not exist", function () {
expectItWhenBoundWith('k1', 'k2').not.toThrow();
expectItWhenBoundWith('newKey1', 'newKey2').not.toThrow();
});
}
function it_throwsNothingIfEdgeExists() {
it("throws nothing if the edge exists", function () {
expectItWhenBoundWith('k2', 'k3').not.toThrow();
expectItWhenBoundWith('k3', 'k4').not.toThrow();
});
}
function it_throwsNothingIfVerticesExistAndEdgeDoesNot() {
it("throws nothing if the required vertices exist but the edge does not", function () {
expectItWhenBoundWith('k1', 'k2').not.toThrow();
});
}
function it_throwsNothingIfVerticesExist() {
it("throws nothing if the required vertices exist", function () {
expectItWhenBoundWith('k1', 'k2').not.toThrow();
expectItWhenBoundWith('k2', 'k3').not.toThrow();
expectItWhenBoundWith('k3', 'k4').not.toThrow();
});
}
function it_throwsNothingWhenPassedTwoKeys() {
it("throws no exceptions when it is passed two key arguments", function () {
expectItWhenBoundWith('k1', 'k2').not.toThrow();
expectItWhenBoundWith('k2', 'k3').not.toThrow();
expectItWhenBoundWith('k3', 'k4').not.toThrow();
expectItWhenBoundWith('newKey1', 'newKey2').not.toThrow();
});
}
function it_throwsNothingWhenPassedTwoKeysAndValue() {
it("throws no exceptions when it is passed two keys and a value argument", function () {
expectItWhenBoundWith('k1', 'k2', 'newValue').not.toThrow();
expectItWhenBoundWith('k2', 'k3', 'newValue').not.toThrow();
expectItWhenBoundWith('k3', 'k4', 'newValue').not.toThrow();
expectItWhenBoundWith('newKey1', 'newKey2', 'newValue').not.toThrow();
});
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
function it_leavesNewEdgeWithNewValue() {
it("leaves a new edge in the graph with a new value", function () {
callItWith('k1', 'k2', 'newValue');
expect(graph.hasEdge('k1', 'k2')).toBeTruthy();
expect(graph.edgeValue('k1', 'k2')).toBe('newValue');
expect(graph.edgeCount()).toBe(originalEdgeCount + 1);
});
}
function it_leavesNewEdgeWithNewUndefinedValue() {
it("leaves a new edge in the graph with a new 'undefined' value", function () {
callItWith('k1', 'k2');
expect(graph.hasEdge('k1', 'k2')).toBeTruthy();
expect(graph.edgeValue('k1', 'k2')).toBeUndefined();
expect(graph.edgeCount()).toBe(originalEdgeCount + 1);
});
}
function it_leavesExistingEdgeWithNewValue() {
it("leaves an existing edge in the graph with a new value", function () {
callItWith('k2', 'k3', 'newValue');
expect(graph.hasEdge('k2', 'k3')).toBeTruthy();
expect(graph.edgeValue('k2', 'k3')).toBe('newValue');
expect(graph.edgeCount()).toBe(originalEdgeCount);
});
}
function it_leavesExistingEdgeWithNewUndefinedValue() {
it("leaves an existing edge in the graph with a new 'undefined' value", function () {
callItWith('k2', 'k3');
expect(graph.hasEdge('k2', 'k3')).toBeTruthy();
expect(graph.edgeValue('k2', 'k3')).toBeUndefined();
expect(graph.edgeCount()).toBe(originalEdgeCount);
});
}
function it_leavesExistingEdgeWithOldValue() {
it("leaves an existing edge in the graph with its old value", function () {
callItWith('k2', 'k3', 'newValue');
expect(graph.hasEdge('k2', 'k3')).toBeTruthy();
expect(graph.edgeValue('k2', 'k3')).toBe('oldValue23');
expect(graph.edgeCount()).toBe(originalEdgeCount);
callItWith('k2', 'k3', undefined);
expect(graph.hasEdge('k2', 'k3')).toBeTruthy();
expect(graph.edgeValue('k2', 'k3')).toBe('oldValue23');
expect(graph.edgeCount()).toBe(originalEdgeCount);
});
}
function it_leavesExistingEdgeWithOldUndefinedValue() {
it("leaves an existing edge in the graph with its old 'undefined' value", function () {
callItWith('k3', 'k4', 'newValue');
expect(graph.hasEdge('k3', 'k4')).toBeTruthy();
expect(graph.edgeValue('k3', 'k4')).toBeUndefined();
expect(graph.edgeCount()).toBe(originalEdgeCount);
});
}
function it_leavesExistingEdgeAbsent() {
it("leaves an existing edge absent from the graph", function () {
callItWith('k2', 'k3');
expect(graph.hasEdge('k2', 'k3')).toBeFalsy();
expect(graph.edgeCount()).toBe(originalEdgeCount - 1);
callItWith('k3', 'k4');
expect(graph.hasEdge('k3', 'k4')).toBeFalsy();
expect(graph.edgeCount()).toBe(originalEdgeCount - 2);
});
}
function it_leavesAbsentEdgeAbsent() {
it("leaves an absent edge absent from the graph", function () {
callItWith('k1', 'k2');
expect(graph.hasEdge('k1', 'k2')).toBeFalsy();
expect(graph.edgeCount()).toBe(originalEdgeCount);
});
}
function it_leavesAbsentVerticesPresent() {
it("leaves absent vertices present in the graph", function () {
callItWith('newKey1', 'k1');
expect(graph.hasVertex('newKey1')).toBeTruthy();
expect(graph.vertexCount()).toBe(originalVertexCount + 1);
callItWith('k1', 'newKey2');
expect(graph.hasVertex('newKey2')).toBeTruthy();
expect(graph.vertexCount()).toBe(originalVertexCount + 2);
callItWith('newKey3', 'newKey4');
expect(graph.hasVertex('newKey3')).toBeTruthy();
expect(graph.hasVertex('newKey4')).toBeTruthy();
expect(graph.vertexCount()).toBe(originalVertexCount + 4);
});
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
describeMethod('addNewEdge', function () {
it_throwsErrorIfEdgeExists();
it_throwsErrorIfVerticesDoNotExist();
it_throwsNothingIfVerticesExistAndEdgeDoesNot();
it_leavesNewEdgeWithNewValue();
it_leavesNewEdgeWithNewUndefinedValue();
});
describeMethod('createNewEdge', function () {
it_throwsErrorIfEdgeExists();
it_throwsNothingIfEdgeDoesNotExist();
it_leavesNewEdgeWithNewValue();
it_leavesNewEdgeWithNewUndefinedValue();
it_leavesAbsentVerticesPresent();
});
describeMethod('setEdge', function () {
it_throwsErrorIfEdgeDoesNotExist();
it_throwsNothingIfEdgeExists();
it_leavesExistingEdgeWithNewValue();
it_leavesExistingEdgeWithNewUndefinedValue();
});
describeMethod('spanEdge', function () {
it_throwsErrorIfVerticesDoNotExist();
it_throwsNothingIfVerticesExist();
it_leavesNewEdgeWithNewValue();
it_leavesNewEdgeWithNewUndefinedValue();
it_leavesExistingEdgeWithOldValue();
it_leavesExistingEdgeWithOldUndefinedValue();
});
describeMethod('addEdge', function () {
it_throwsErrorIfVerticesDoNotExist();
it_throwsNothingIfVerticesExist();
it_leavesNewEdgeWithNewValue();
it_leavesNewEdgeWithNewUndefinedValue();
it_leavesExistingEdgeWithNewValue();
it_leavesExistingEdgeWithNewUndefinedValue();
});
describeMethod('ensureEdge', function () {
it_throwsNothingWhenPassedTwoKeys();
it_throwsNothingWhenPassedTwoKeysAndValue();
it_leavesNewEdgeWithNewValue();
it_leavesNewEdgeWithNewUndefinedValue();
it_leavesExistingEdgeWithOldValue();
it_leavesExistingEdgeWithOldUndefinedValue();
it_leavesAbsentVerticesPresent();
});
describeMethod('createEdge', function () {
it_throwsNothingWhenPassedTwoKeys();
it_throwsNothingWhenPassedTwoKeysAndValue();
it_leavesNewEdgeWithNewValue();
it_leavesNewEdgeWithNewUndefinedValue();
it_leavesExistingEdgeWithNewValue();
it_leavesExistingEdgeWithNewUndefinedValue();
it_leavesAbsentVerticesPresent();
});
describeMethod('removeExistingEdge', function () {
it_throwsErrorIfEdgeDoesNotExist();
it_leavesExistingEdgeAbsent();
});
describeMethod('removeEdge', function () {
it_throwsNothingWhenPassedTwoKeys();
it_leavesExistingEdgeAbsent();
it_leavesAbsentEdgeAbsent();
});
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
describeMethod('clearEdges', function () {
it("throws nothing", function () {
expectItWhenBoundWith().not.toThrow();
});
it("leaves the graph without edges", function () {
callItWith();
expect(graph.edgeCount()).toBe(0);
});
it("leaves existing vertices in the graph", function () {
callItWith();
expect(graph.vertexCount()).toBe(originalVertexCount);
});
});
describeMethod('clear', function () {
it("throws nothing", function () {
expectItWhenBoundWith().not.toThrow();
});
it("leaves the graph without edges", function () {
callItWith();
expect(graph.edgeCount()).toBe(0);
});
it("leaves the graph without vertices", function () {
callItWith();
expect(graph.vertexCount()).toBe(0);
});
});
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
describeMethod('onAddVertex', function () {
it("throws no exceptions when passed a function", function () {
expectItWhenBoundWith(function () { throw new Error("should not be thrown"); }).not.toThrow();
});
it("does not modify the graph", function () {
callItWith(function () {
graph = null;
});
expectTheGraphNotToHaveChanged();
});
it("causes the handler to be called after a new vertex is added", function () {
var addedVertices = {};
callItWith(function (key, value) {
expect(graph.hasVertex(key)).toBeTruthy();
addedVertices[key] = value;
});
graph.addNewVertex('newKey', 'newValue');
expect(addedVertices).toEqual({ 'newKey': 'newValue' });
});
it("does not cause the handler to be called when an existing vertex is modified", function () {
callItWith(function () {
expect().not.toBeReachable();
});
graph.setVertex('k1', 'newValue');
graph.setVertex('k2', 'newValue');
});
it("does not cause the handler to be called when an existing vertex is removed", function () {
callItWith(function () {
expect().not.toBeReachable();
});
graph.removeExistingVertex('k1');
});
it("causes the handler to be called after a previously removed vertex is added again", function () {
var vertices = {};
callItWith(function (key, value) {
expect(graph.hasVertex(key)).toBeTruthy();
vertices[key] = value;
});
graph.removeExistingVertex('k1');
expect(vertices).toEqual({});
graph.addNewVertex('k1', 'oldValue1');
expect(vertices).toEqual({ 'k1': 'oldValue1' });
});
it("does not cause the handler to be called after the handler is removed", function () {
var registeredAddedVertices = {};
var removeCallback = callItWith(function (key, value) {
registeredAddedVertices[key] = value;
});
graph.addNewVertex('newKey', 'newValue');
expect(registeredAddedVertices).toEqual({ 'newKey': 'newValue' });
removeCallback();
graph.addNewVertex('newKey2', 'newValue2');
expect(registeredAddedVertices).toEqual({ 'newKey': 'newValue' });
});
});
describeMethod('onAddEdge', function () {
it("throws no exceptions when passed a function", function () {
expectItWhenBoundWith(function () { throw new Error("should not be thrown"); }).not.toThrow();
});
it("does not modify the graph", function () {
callItWith(function () {
graph = null;
});
expectTheGraphNotToHaveChanged();
});
it("causes the handler to be called after a new edge is added", function () {
var addedEdges = {};
callItWith(function (from, to, value) {
expect(graph.hasEdge(from, to)).toBeTruthy();
addedEdges[from + ", " + to] = value;
});
graph.addNewEdge('k1', 'k2', 'newValue');
expect(addedEdges).toEqual({ 'k1, k2': 'newValue' });
});
it("does not cause the handler to be called when an existing edge is modified", function () {
callItWith(function () {
expect().not.toBeReachable();
});
graph.setEdge('k2', 'k3', 'newValue');
graph.setEdge('k3', 'k4', 'newValue');
});
it("does not cause the handler to be called when an existing edge is removed", function () {
callItWith(function () {
expect().not.toBeReachable();
});
graph.removeExistingEdge('k2', 'k3');
});
it("causes the handler to be called after a previously removed edge is added again", function () {
var edges = {};
callItWith(function (from, to, value) {
expect(graph.hasEdge(from, to)).toBeTruthy();
edges[from + ", " + to] = value;
});
graph.removeExistingEdge('k2', 'k3');
expect(edges).toEqual({});
graph.addNewEdge('k2', 'k3', 'oldValue23');
expect(edges).toEqual({ 'k2, k3': 'oldValue23' });
});
it("does not cause the handler to be called after the handler is removed", function () {
var registeredAddedEdges = {};
var removeCallback = callItWith(function (from, to, value) {
registeredAddedEdges[from + ", " + to] = value;
});
graph.addNewEdge('k1', 'k2', 'newValue');
expect(registeredAddedEdges).toEqual({ 'k1, k2': 'newValue' });
removeCallback();
graph.addNewEdge('k2', 'k1', 'newValue2');
expect(registeredAddedEdges).toEqual({ 'k1, k2': 'newValue' });
});
});
describeMethod('onRemoveVertex', function () {
it("throws no exceptions when passed a function", function () {
expectItWhenBoundWith(function () { throw new Error("should not be thrown"); }).not.toThrow();
});
it("does not modify the graph", function () {
callItWith(function () {
graph = null;
});
expectTheGraphNotToHaveChanged();
});
it("causes the handler to be called after an existing vertex is removed", function () {
var removedVertices = {};
callItWith(function (key, value) {
expect(graph.hasVertex(key)).toBeFalsy();
removedVertices[key] = value;
});
graph.removeExistingVertex('k1');
expect(removedVertices).toEqual({ 'k1': 'oldValue1' });
});
it("does not cause the handler to be called when an existing vertex is modified", function () {
callItWith(function () {
expect().not.toBeReachable();
});
graph.setVertex('k1', 'newValue');
graph.setVertex('k2', 'newValue');
});
it("does not cause the handler to be called when an absent vertex is left absent", function () {
callItWith(function () {
expect().not.toBeReachable();
});
graph.removeVertex('newKey');
});
it("does not cause the handler to be called when an absent vertex is added", function () {
callItWith(function () {
expect().not.toBeReachable();
});
graph.addNewVertex('newKey');
});
it("does not cause the handler to be called after the handler is removed", function () {
var registeredRemovedVertices = {};
var removeCallback = callItWith(function (key, value) {
registeredRemovedVertices[key] = value;
});
graph.addNewVertex('k99', 'newValue');
graph.removeExistingVertex('k99');
expect(registeredRemovedVertices).toEqual({ 'k99': 'newValue' });
removeCallback();
graph.removeExistingVertex('k1');
expect(registeredRemovedVertices).toEqual({ 'k99': 'newValue' });
});
});
describeMethod('onRemoveEdge', function () {
it("throws no exceptions when passed a function", function () {
expectItWhenBoundWith(function () { throw new Error("should not be thrown"); }).not.toThrow();
});
it("does not modify the graph", function () {
callItWith(function () {
graph = null;
});
expectTheGraphNotToHaveChanged();
});
it("causes the handler to be called after an existing edge is removed", function () {
var removedEdges = {};
callItWith(function (from, to, value) {
expect(graph.hasEdge(from, to)).toBeFalsy();
removedEdges[from + ", " + to] = value;
});
graph.removeExistingEdge('k2', 'k3');
expect(removedEdges).toEqual({ 'k2, k3': 'oldValue23' });
});
it("does not cause the handler to be called when an existing edge is modified", function () {
callItWith(function () {
expect().not.toBeReachable();
});
graph.setEdge('k2', 'k3', 'newValue');
graph.setEdge('k3', 'k4', 'newValue');
});
it("does not cause the handler to be called when an absent edge is left absent", function () {
callItWith(function () {
expect().not.toBeReachable();
});
graph.removeEdge('k1', 'k2');
});
it("does not cause the handler to be called when an absent edge is added", function () {
callItWith(function () {
expect().not.toBeReachable();
});
graph.addNewEdge('k1', 'k2');
});
it("does not cause the handler to be called after the handler is removed", function () {
var registeredRemovedEdges = {};
var removeCallback = callItWith(function (from, to, value) {
registeredRemovedEdges[from + ", " + to] = value;
});
graph.removeExistingEdge('k2', 'k3');
expect(registeredRemovedEdges).toEqual({ 'k2, k3': 'oldValue23' });
removeCallback();
graph.removeExistingEdge('k3', 'k4');
expect(registeredRemovedEdges).toEqual({ 'k2, k3': 'oldValue23' });
});
});
describe("event subscription methods", function () {
it("register each handler only once", function () {
var counter = 0;
var handler = function () {
++counter;
};
graph.onAddVertex(handler);
graph.onAddVertex(handler);
graph.addNewVertex('newKey', 'newValue');
expect(counter).toBe(1);
});
it("quietly ignore multiple removals of the same handler", function () {
var counter = 0;
graph.onAddVertex(function () { // adding a handler before the main handler
++counter;
});
var removeCallback = graph.onAddVertex(function () {
counter += 10;
});
graph.onAddVertex(function () { // adding a handler after the main handler
++counter;
});
graph.addNewVertex('newKey', 'newValue');
expect(counter).toBe(12);
removeCallback();
removeCallback();
graph.addNewVertex('newKey2', 'newValue2');
expect(counter).toBe(14); // meaning: the other two handlers are not accidentally removed
});
});
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
describeMethod('hasPath', function () {
it("throws nothing when passed two key arguments", function () {
expectItWhenBoundWith('k1', 'k2').not.toThrow();
expectItWhenBoundWith('k2', 'k3').not.toThrow();
expectItWhenBoundWith('newKey', 'k2').not.toThrow();
expectItWhenBoundWith('newKey1', 'newKey2').not.toThrow();
});
// k1 k2 --> k3 --> k4
// | ^
// | ;
// V /
// k5 __/
it("returns a falsy value if the path doesn't exist (1)", function () {
expectItWhenCalledWith('k1', 'k2').toBeFalsy();
expectItWhenCalledWith('k1', 'k3').toBeFalsy();
expectItWhenCalledWith('k2', 'k1').toBeFalsy();
});
it("returns a falsy value if the path doesn't exist (2: self-loop)", function () {
expectItWhenCalledWith('k2', 'k2').toBeFalsy();
});
it("returns a falsy value if the path doesn't exist (3: edge backwards)", function () {
expectItWhenCalledWith('k3', 'k2').toBeFalsy();
expectItWhenCalledWith('k4', 'k2').toBeFalsy();
});
it("returns a truthy value if the path exists (1: single edge)", function () {
expectItWhenCalledWith('k2', 'k3').toBeTruthy();
expectItWhenCalledWith('k3', 'k4').toBeTruthy();
expectItWhenCalledWith('k2', 'k5').toBeTruthy();
expectItWhenCalledWith('k5', 'k3').toBeTruthy();
});
it("returns a truthy value if the path exists (2: transitive)", function () {
expectItWhenCalledWith('k2', 'k4').toBeTruthy();
expectItWhenCalledWith('k5', 'k4').toBeTruthy();
graph.addEdge('k4', 'k1');
expectItWhenCalledWith('k2', 'k1').toBeTruthy();
});
it("returns a truthy value if the path exists (3: reflexive cycle)", function () {
graph.addEdge('k1', 'k1');
expectItWhenCalledWith('k1', 'k1').toBeTruthy();
});
it("returns a truthy value if the path exists (4: symmetric cycle)", function () {
graph.addEdge('k4', 'k3');
expectItWhenCalledWith('k3', 'k3').toBeTruthy();
});
it("returns a truthy value if the path exists (5: larger cycle)", function () {
graph.addEdge('k4', 'k1');
graph.addEdge('k1', 'k2');
expectItWhenCalledWith('k3', 'k3').toBeTruthy();
});
it("returns a truthy value if the path exists (6: including part of a cycle, part 1)", function () {
graph.clear();
graph.createEdge('n1', 'n2');
graph.createEdge('n2', 'n3');
graph.createEdge('n3', 'n4');
graph.createEdge('n4', 'n5');
graph.createEdge('n3', 'n23');
graph.createEdge('n23', 'n2');
// n1 --> n2 --> n3 --> n4 --> n5
// ^ |
// | ;
// | /
// n23 <-"
expectItWhenCalledWith('n1', 'n5').toBeTruthy();
});
it("returns a truthy value if the path exists (7: including part of a cycle, part 2)", function () {
graph.clear();
graph.createEdge('n3', 'n23'); // same graph as above, but creating the loopy bit
graph.createEdge('n23', 'n2'); // first; insertion order matters for some engines
graph.createEdge('n1', 'n2');
graph.createEdge('n2', 'n3');
graph.createEdge('n3', 'n4');
graph.createEdge('n4', 'n5');
// n1 --> n2 --> n3 --> n4 --> n5
// ^ |
// | ;
// | /
// n23 <-"
expectItWhenCalledWith('n1', 'n5').toBeTruthy();
});
});
describeMethod('topologically', function () {
it("throws an error if the graph contains a cycle (1)", function () {
graph.clear();
graph.createEdge('n1', 'n2');
graph.createEdge('n2', 'n3');
graph.createEdge('n3', 'n4');
graph.createEdge('n4', 'n5');
graph.createEdge('n3', 'n23');
graph.createEdge('n23', 'n2');
// n1 --> n2 --> n3 --> n4 --> n5
// ^ |
// | ;
// | /
// n23 <-"
expectItWhenBoundWith(function () {}).toThrow();
expectItWhenBoundWith(function () {}).toThrowSpecific(Graph.CycleError, {});
try {
callItWith(function () {});
} catch (err) {
expect(err.cycle).toEqualOneOf(
['n23', 'n2', 'n3'],
['n3', 'n23', 'n2'],
['n2', 'n3', 'n23']
);
}
});
it("throws an error if the graph contains a cycle (2)", function () {
graph.clear();
graph.createEdge('n1', 'n1');
expectItWhenBoundWith(function () {}).toThrow();
expectItWhenBoundWith(function () {}).toThrowSpecific(Graph.CycleError, {});
try {
callItWith(function () {});
} catch (err) {
expect(err.cycle).toEqual(['n1']);
}
});
it("throws nothing if the graph has no cycle and the passed function throws nothing", function () {
expectItWhenBoundWith(function () {/*not throwing stuff*/}).not.toThrow();
});
it("calls the specified handler exactly once for each vertex in the graph", function () {
var verticesFound = {};
callItWith(function (key, value) {
expect(verticesFound[key]).toBeUndefined();
verticesFound[key] = value;
});
expect(verticesFound).toEqual(originalVertices);
});
it("visits vertices only when their predecessors have already been visited", function () {
graph.clear();
graph.createEdge('n3', 'n23');
graph.createEdge('n2', 'n23');
graph.createEdge('n1', 'n2');
graph.createEdge('n2', 'n3');
graph.createEdge('n3', 'n4');
graph.createEdge('n4', 'n5');
// n1 --> n2 --> n3 --> n4 --> n5
// | |
// | ;
// V /
// n23 <-"
var visited = {};
callItWith(function (key) {
if (key === 'n2') { expect(visited['n1']).toBeDefined(); }
if (key === 'n3') { expect(visited['n2']).toBeDefined(); }
if (key === 'n4') { expect(visited['n3']).toBeDefined(); }
if (key === 'n5') { expect(visited['n4']).toBeDefined(); }
if (key === 'n23') {
expect(visited['n2']).toBeDefined();
expect(visited['n3']).toBeDefined();
}
visited[key] = true;
});
});
});
});/////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
});/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////