aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorRuben Beltran del Rio <ruben@unlimited.pizza>2020-09-20 16:55:36 +0200
committerRuben Beltran del Rio <ruben@unlimited.pizza>2020-09-20 16:55:36 +0200
commite4c7bafd276049c805039b240e0a83346c31f41b (patch)
tree4c8788909ed67710a1628b9e4ae51c1a45b3b3ce /test
Initial release
Diffstat (limited to 'test')
-rw-r--r--test/grafn.js225
1 files changed, 225 insertions, 0 deletions
diff --git a/test/grafn.js b/test/grafn.js
new file mode 100644
index 0000000..1618eb2
--- /dev/null
+++ b/test/grafn.js
@@ -0,0 +1,225 @@
+'use strict';
+
+const Grafn = require('..');
+const Tap = require('tap');
+
+Tap.beforeEach((done, t) => {
+
+ t.graph = new Grafn();
+ t.verticesRan = 0;
+ done();
+});
+
+Tap.test(async (t) => {
+
+ await t.rejects(t.graph.run('nonExisting'), 'It throws an error if you try to run a non-existing vertex');
+});
+
+Tap.test(async (t) => {
+
+ t.graph.vertex({
+ name: 'root',
+ action() {
+
+ t.verticesRan++;
+ }
+ });
+
+ await t.graph.run('root');
+ t.equal(t.verticesRan, 1, 'It runs a vertex if no dependencies are defined');
+});
+
+Tap.test(async (t) => {
+
+ t.graph.vertex({
+ name: 'unfulfilled',
+ dependencies: ['nonExisting'],
+ action() {
+
+ t.verticesRan++;
+ }
+ });
+
+ await t.graph.run('unfulfilled');
+ t.equal(t.verticesRan, 0, 'It does not run a vertex if it has unfulfilled dependencies');
+});
+
+Tap.test(async (t) => {
+
+ t.graph.vertex({
+ name: 'root',
+ action() { }
+ });
+
+ t.graph.vertex({
+ name: 'firstDependent',
+ dependencies: ['root'],
+ action() {
+
+ t.verticesRan++;
+ }
+ });
+
+ t.graph.vertex({
+ name: 'secondDependent',
+ dependencies: ['root'],
+ action() {
+
+ t.verticesRan += 2;
+ }
+ });
+
+ await t.graph.run('root');
+ t.equal(t.verticesRan, 3, 'It runs dependent vertices on completion of a vertex\'s action');
+});
+
+Tap.test(async (t) => {
+
+ t.graph.vertex({
+ name: 'root',
+ action() { }
+ });
+
+ t.graph.vertex({
+ name: 'firstDependent',
+ dependencies: ['root'],
+ action() {
+
+ return 1;
+ }
+ });
+
+ t.graph.vertex({
+ name: 'secondDependent',
+ dependencies: ['root'],
+ action() {
+
+ return 2;
+ }
+ });
+
+ t.graph.vertex({
+ name: 'final',
+ dependencies: ['firstDependent', 'secondDependent'],
+ action(state) {
+
+ t.verticesRan = state.firstDependent + state.secondDependent;
+ }
+ });
+
+ await t.graph.run('root');
+ t.equal(t.verticesRan, 3, 'It ensures dependencies state is available before running dependents');
+});
+
+Tap.test(async (t) => {
+
+ t.graph.vertex({
+ name: 'root',
+ action() {
+
+ return 101;
+ }
+ });
+
+ t.graph.vertex({
+ name: 'stateDependent',
+ dependencies: ['root'],
+ action(state) {
+
+ t.verticesRan = state.root;
+ }
+ });
+
+ await t.graph.run('root');
+ t.equal(t.verticesRan, 101, 'It gives dependent vertices a state including their dependencies\' results');
+});
+
+Tap.test(async (t) => {
+
+ t.graph.vertex({
+ name: 'root',
+ action() {
+
+ throw new Error('Unexpected root problem');
+ }
+ });
+
+ await t.rejects(t.graph.run('root'), 'It throws an error if a vertex throws an error');
+});
+
+Tap.test(async (t) => {
+
+ t.graph.vertex({
+ name: 'root',
+ action() {
+
+ t.verticesRan++;
+ return 1;
+ }
+ });
+
+ await t.graph.run('root');
+ await t.graph.run('root');
+ t.equal(t.verticesRan, 1, 'It runs a vertex only once');
+});
+
+Tap.test( (t) => {
+
+ t.graph.vertex({
+ name: 'root',
+ action() {}
+ });
+
+ t.graph.vertex({
+ name: 'firstDependent',
+ dependencies: ['root'],
+ action() {}
+ });
+
+ t.graph.vertex({
+ name: 'secondDependent',
+ dependencies: ['root'],
+ action() {}
+ });
+
+ t.graph.vertex({
+ name: 'final',
+ dependencies: ['firstDependent', 'secondDependent'],
+ action() {}
+ });
+
+ t.matchSnapshot(t.graph.toString(), 'It can convert to a string representing the graph in graphviz format');
+ t.end();
+});
+
+Tap.test('It colorizes the graph based on execution results', async (t) => {
+
+ t.graph.vertex({
+ name: 'root',
+ action() {}
+ });
+
+ t.graph.vertex({
+ name: 'firstDependent',
+ dependencies: ['root'],
+ action() {}
+ });
+
+ t.graph.vertex({
+ name: 'secondDependent',
+ dependencies: ['root'],
+ action() {
+
+ throw new Error('Second dependent has failed');
+ }
+ });
+
+ t.graph.vertex({
+ name: 'final',
+ dependencies: ['firstDependent', 'secondDependent'],
+ action() {}
+ });
+
+ await t.rejects(t.graph.run('root'), 'It throws an error if a sub-step fails');
+ t.matchSnapshot(t.graph.toString(), 'It adds the right colors according to execution');
+});