UNPKG

dependency-foo

Version:

Serializable General Purpose Dependency Graph

252 lines (250 loc) 8.43 kB
var vows = require('vows'); var assert = require('assert'); var DependencyGraph = require('../'); vows.describe('dg.js').addBatch({ "the module export shuld be a function": function() { assert.isFunction(DependencyGraph); assert.strictEqual(DependencyGraph.name, 'Graph'); }, "When I add 'drug' as a dependency of 'human'": { topic: function() { var graph = new DependencyGraph(); graph.subject('human').dependOn('drug'); return graph; }, "Then the node 'human'": { topic: function(graph) { return graph.subject('human'); }, "should be a dependent of 'drug'": function(node) { // This guy is a drug addict xD assert.isTrue(node.hasDependencyTo('drug')); }, "should report 'drug' as the only dependency": function(node) { assert.deepEqual(node.dependencies, ['drug']); } }, "And the node 'drug'": { topic: function(graph) { return graph.subject('drug'); }, "should be a dependency of 'human'": function(drug) { // this drug just got a new human :) assert.isTrue(drug.isDependencyOf('human')); }, "should report 'human' as the only reference": function(node) { assert.deepEqual(node.references, ['human']); } } }, "When I have a dependency already established": { topic: function() { var graph = new DependencyGraph(); graph.subject('human').dependOn('drug'); return graph; }, "And I repeat the call that adds the dependency": { topic: function(graph) { return graph.subject('human').dependOn('drug'); }, "Then the dependency should not be repeated": function(human) { assert.deepEqual(human.dependencies, ['drug']); } } }, "When I add 'drug', 'air' and 'food' dependencies of 'human'": { topic: function() { var graph = new DependencyGraph(); return graph.subject('human').dependOn('drug').dependOn('air').dependOn('food'); }, "Then all the dependencies should be listed as dependencies": function(human) { assert.deepEqual(human.dependencies, ['drug', 'air', 'food']); }, "And a references to the 'human'": { "must exist in 'drug'": function(human) { assert.deepEqual(human.graph.subject('drug').references, ['human']); }, "also in 'air'": function(human) { assert.deepEqual(human.graph.subject('air').references, ['human']); }, "and 'food' as well": function(human) { assert.deepEqual(human.graph.subject('food').references, ['human']); } } }, "Having 'drug', 'air' and 'food' as dependencies of 'human'": { topic: function() { var graph = new DependencyGraph(); // we add another dependencies to 'air' so we check that 'drop' only removes 'human' references of 'air' graph.subject('plant').dependOn('air'); graph.subject('animal').dependOn('air'); return graph.subject('human').dependOn('drug').dependOn('air').dependOn('food'); }, "If then I remove 'air' and 'drug'": { topic: function(human) { return human.drop('air').drop('drug'); }, "Then the only dependency left should be 'food'": function(human) { assert.deepEqual(human.dependencies, ['food']); }, "And 'air'": { topic: function(human) { var graph = human.graph; return graph.subject('air'); }, "Should not have a reference to 'human'": function(air) { assert.deepEqual(air.references, ['plant','animal']); } }, "And 'drug'": { topic: function(human) { return human.graph.subject('drug'); }, "Should not have a reference to 'human'": function(drug) { assert.deepEqual(drug.references, []); } } } }, "When I serialize a graph with nodes": { topic: function() { var graph = new DependencyGraph(); graph.subject('air').dependOn("oxigen"); graph.subject('air').dependOn("hidrogen"); graph.subject('human').dependOn("air"); graph.subject('fire').dependOn("oxigen"); graph.subject('animal').dependOn("air"); return graph.serialize(); }, "The serialized graph state should be an object with properties per each node with sub properties dps and refs only": function(data) { assert.deepEqual(JSON.parse(data), { animal: { refs: [], dps: [ 'air' ] }, oxigen: { refs: [ 'air', 'fire' ], dps: [] }, human: { refs: [], dps: [ 'air' ] }, air: { refs: [ 'human', 'animal' ], dps: [ 'oxigen', 'hidrogen' ] }, hidrogen: { refs: [ 'air' ], dps: [] }, fire: { refs: [], dps: [ 'oxigen' ] } }); } }, "When I initialize a graph with a serialized state": { topic: function() { var graph = new DependencyGraph({ animal: { refs: [], dps: [ 'air' ] }, air: { refs: [ 'animal' ], dps: [] }, }); return graph; }, "I should be able to perform operations normally": function(graph){ assert.isTrue(graph.subject('air').isDependencyOf('animal')); } }, "Having a graph with multiple nested references": { topic: function() { var graph = new DependencyGraph(); graph.subject('B.first').dependOn('A'); graph.subject('B.middle').dependOn('A'); graph.subject('B.last').dependOn('A'); graph.subject('C').dependOn('B.first'); graph.subject('C').dependOn('B.middle'); graph.subject('C').dependOn('B.last'); graph.subject('D').dependOn('B'); graph.subject('D').dependOn('C'); return graph; }, "allReferences should return all the references in the right order and with unique elements": function(graph){ assert.deepEqual(graph.subject('A').allReferences, ['B.first','B.middle', 'B.last', 'C', 'D']); } }, "Having a graph with multiple nested dependencies": { topic: function() { var graph = new DependencyGraph(); graph.subject('B.first').dependOn('A'); graph.subject('B.middle').dependOn('A'); graph.subject('B.last').dependOn('A'); graph.subject('C').dependOn('B.first'); graph.subject('C').dependOn('B.middle'); graph.subject('C').dependOn('B.last'); graph.subject('D').dependOn('B'); graph.subject('D').dependOn('C'); return graph; }, "allReferences should return all the references in the right order and with unique elements": function(graph){ assert.deepEqual(graph.subject('D').allDependencies, ['B', 'C', 'B.first','B.middle', 'B.last', 'A']); } }, "If I try to add a dependency to the same node": { topic: function() { var graph = new DependencyGraph(); return graph; }, "Then I should receive an error with message 'Cyclic Dependency Detected'": function(graph) { assert.throws(function() { graph.subject('B').dependOn('B'); }); try { graph.subject('B').dependOn('B'); } catch(e) { assert.equal(e.message, 'Cyclic Dependency Detected'); } } }, "If I try to add a dependency to the same node in a sub-dependency": { topic: function() { var graph = new DependencyGraph(); graph.subject('B').dependOn('A'); return graph; }, "Then I should receive an error with message 'Cyclic Dependency Detected'": function(graph) { assert.throws(function() { graph.subject('A').dependOn('B'); }); try { graph.subject('A').dependOn('B'); } catch(e) { assert.equal(e.message, 'Cyclic Dependency Detected'); } graph.subject('C').dependOn('B'); assert.throws(function() { graph.subject('A').dependOn('C'); }); } }, "Having a graph with 4 nodes": { topic: function() { var graph = new DependencyGraph(); graph.subject('A','B'); graph.subject('B','C'); graph.subject('C','D'); graph.subject('D','F'); return graph; }, "all should return all the nodes in the graph": function(graph) { assert.equal(graph.all.length, 4); } } }).run();