react 0.0.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/.npmignore +6 -0
  2. package/Jakefile.js +8 -0
  3. package/README.md +226 -86
  4. package/examples/ast1.js +26 -0
  5. package/examples/chain-events1.js +34 -0
  6. package/examples/chain1.js +19 -0
  7. package/examples/default-events1.js +52 -0
  8. package/examples/default1.js +40 -0
  9. package/examples/fstr-events1.js +51 -0
  10. package/examples/fstr1.js +36 -0
  11. package/examples/pcode1.js +22 -0
  12. package/jake-tasks/jake-test.js +64 -0
  13. package/lib/base-task.js +115 -0
  14. package/lib/cb-task.js +67 -0
  15. package/lib/chain.js +148 -0
  16. package/lib/core.js +96 -0
  17. package/lib/dsl.js +122 -0
  18. package/lib/error.js +37 -0
  19. package/lib/event-manager.js +57 -0
  20. package/lib/finalcb-first-task.js +59 -0
  21. package/lib/finalcb-task.js +54 -0
  22. package/lib/fstr.js +110 -0
  23. package/lib/id.js +10 -0
  24. package/lib/input-parser.js +44 -0
  25. package/lib/parse.js +29 -0
  26. package/lib/pcode.js +164 -0
  27. package/lib/ret-task.js +67 -0
  28. package/lib/status.js +5 -0
  29. package/lib/task.js +234 -0
  30. package/lib/validate.js +102 -0
  31. package/lib/vcon.js +76 -0
  32. package/oldExamples/analyze.js +29 -0
  33. package/oldExamples/analyze2.js +29 -0
  34. package/oldExamples/example10-dsl.js +63 -0
  35. package/oldExamples/example11.js +62 -0
  36. package/oldExamples/example12.js +63 -0
  37. package/oldExamples/example13.js +63 -0
  38. package/oldExamples/example14.js +63 -0
  39. package/oldExamples/example15.js +75 -0
  40. package/{test → oldExamples}/example6-ast.js +4 -4
  41. package/{test → oldExamples}/example6-dsl.js +3 -2
  42. package/{test → oldExamples}/example8-ast.js +3 -2
  43. package/{test → oldExamples}/example8-dsl.js +3 -2
  44. package/{test → oldExamples}/example9-ast.js +3 -2
  45. package/{test → oldExamples}/example9-dsl.js +3 -2
  46. package/oldExamples/function-str-ex1.js +33 -0
  47. package/oldExamples/function-str-ex2.js +67 -0
  48. package/oldExamples/trait1.js +41 -0
  49. package/oldExamples/trait2.js +44 -0
  50. package/package.json +16 -6
  51. package/react.js +11 -1
  52. package/test/ast.test.js +69 -0
  53. package/test/cb-task.test.js +197 -0
  54. package/test/chain.test.js +239 -0
  55. package/test/core.test.js +519 -0
  56. package/test/dsl.test.js +237 -0
  57. package/test/event-manager.test.js +102 -0
  58. package/test/exec-options.test.js +32 -0
  59. package/test/finalcb-task.test.js +37 -0
  60. package/test/fstr.test.js +288 -0
  61. package/test/input-parser.test.js +62 -0
  62. package/test/module-use.test.js +317 -0
  63. package/test/pcode.test.js +321 -0
  64. package/test/ret-task.test.js +199 -0
  65. package/test/task.test.js +21 -0
  66. package/test/validate-cb-task.test.js +74 -0
  67. package/test/validate-ret-task.test.js +83 -0
  68. package/test/validate.test.js +218 -0
  69. package/test/vcon.test.js +160 -0
  70. package/lib/react.js +0 -239
@@ -0,0 +1,237 @@
1
+ 'use strict';
2
+
3
+ var test = require('tap').test;
4
+ var sprintf = require('sprintf').sprintf;
5
+
6
+ var react = require('../'); // require('react');
7
+
8
+ function falpha() { }
9
+ function fbeta() { }
10
+
11
+ test('module exports is a fn with properties', function (t) {
12
+ t.type(react, 'function', 'has define by DSL method'); //
13
+ t.type(react.selectFirst, 'function', 'has selectFirst define method');
14
+ t.end();
15
+ });
16
+
17
+ test('no arguments -> empty name, inParams, tasks, outTask', function (t) {
18
+ var r = react();
19
+ t.equal(r.ast.name, undefined);
20
+ t.deepEqual(r.ast.inParams, []);
21
+ t.deepEqual(r.ast.tasks, []);
22
+ t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
23
+ t.end();
24
+ });
25
+
26
+
27
+ test('empty first string -> empty name, inParams, tasks, outTask', function (t) {
28
+ var r = react('');
29
+ t.equal(r.ast.name, '');
30
+ t.deepEqual(r.ast.inParams, []);
31
+ t.deepEqual(r.ast.tasks, []);
32
+ t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
33
+ t.end();
34
+ });
35
+
36
+
37
+ test('single first string -> name, inParams["foo"], empty tasks, outTask', function (t) {
38
+ var r = react('foo');
39
+ t.equal(r.ast.name, 'foo');
40
+ t.deepEqual(r.ast.inParams, []);
41
+ t.deepEqual(r.ast.tasks, []);
42
+ t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
43
+ t.end();
44
+ });
45
+
46
+ test('triple first string -> inParams["foo", "bar", "baz"], empty tasks, outTask',
47
+ function (t) {
48
+ var r = react('myName', ' foo, bar,baz ');
49
+ t.equal(r.ast.name, 'myName');
50
+ t.deepEqual(r.ast.inParams, ['foo', 'bar', 'baz']);
51
+ t.deepEqual(r.ast.tasks, []);
52
+ t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
53
+ t.end();
54
+ });
55
+
56
+ test('single task, single out params', function (t) {
57
+ var r = react('myName', 'cb -> err, c',
58
+ falpha, 'a, b, cb -> err, c'
59
+ );
60
+ t.deepEqual(r.ast.inParams, []);
61
+ t.deepEqual(r.ast.tasks, [
62
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
63
+ ]);
64
+ t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
65
+ t.end();
66
+ });
67
+
68
+ test('single task, err and out params', function (t) {
69
+ var r = react('myName', 'cb -> err, c',
70
+ falpha, 'a, b, cb -> err, c'
71
+ );
72
+ t.deepEqual(r.ast.inParams, []);
73
+ t.deepEqual(r.ast.tasks, [
74
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
75
+ ]);
76
+ t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
77
+ t.end();
78
+ });
79
+
80
+ test('single task, ERR and out params', function (t) {
81
+ var r = react('myName', 'cb -> ERR, c',
82
+ falpha, 'a, b, cb -> ERR, c'
83
+ );
84
+ t.deepEqual(r.ast.inParams, []);
85
+ t.deepEqual(r.ast.tasks, [
86
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
87
+ ]);
88
+ t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
89
+ t.end();
90
+ });
91
+
92
+ test('cb used in defs is simply ignored', function (t) {
93
+ var r = react('myName', 'a, b, cb -> err, c',
94
+ falpha, 'a, b, cb -> err, c'
95
+ );
96
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
97
+ t.deepEqual(r.ast.tasks, [
98
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
99
+ ]);
100
+ t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
101
+ t.end();
102
+ });
103
+
104
+ test('callback used in defs is simply ignored', function (t) {
105
+ var r = react('myName', 'a, b, callback -> err, c',
106
+ falpha, 'a, b, callback -> err, c'
107
+ );
108
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
109
+ t.deepEqual(r.ast.tasks, [
110
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
111
+ ]);
112
+ t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
113
+ t.end();
114
+ });
115
+
116
+ test('two inputs, two tasks, two out params', function (t) {
117
+ var r = react('myName', 'a, b, cb -> err, c, d',
118
+ falpha, 'a, b, cb -> err, c',
119
+ fbeta, 'a, b, cb -> err, d, e'
120
+ );
121
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
122
+ t.deepEqual(r.ast.tasks, [
123
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
124
+ { f: fbeta, a: ['a', 'b'], out: ['d', 'e'], type: 'cb', name: 'fbeta'}
125
+ ]);
126
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
127
+ t.end();
128
+ });
129
+
130
+ test('two inputs, two tasks, two out params, options', function (t) {
131
+ var r = react('myName', 'a, b, cb -> err, c, d',
132
+ { otherOptFoo: 'foo'}, // main flow options
133
+ falpha, 'a, b, cb -> err, c',
134
+ fbeta, 'a, b, cb -> err, d, e'
135
+ );
136
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
137
+ t.deepEqual(r.ast.tasks, [
138
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
139
+ { f: fbeta, a: ['a', 'b'], out: ['d', 'e'], type: 'cb', name: 'fbeta'}
140
+ ]);
141
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
142
+ t.equal(r.ast.name, 'myName', 'name should match');
143
+ t.equal(r.ast.otherOptFoo, 'foo', 'other options should pass through');
144
+ t.end();
145
+ });
146
+
147
+ test('two inputs, two mixed tasks, two out params', function (t) {
148
+ var r = react('myName', 'a, b, cb -> err, c, d',
149
+ falpha, 'a, b, cb -> err, c',
150
+ fbeta, 'a, b -> d'
151
+ );
152
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
153
+ t.deepEqual(r.ast.tasks, [
154
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
155
+ { f: fbeta, a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
156
+ ]);
157
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
158
+ t.end();
159
+ });
160
+
161
+
162
+ test('two inputs, two mixed tasks, two out params, opts', function (t) {
163
+ var r = react('myName', 'a, b, cb -> err, c, d',
164
+ falpha, 'a, cb -> err, c', { after: fbeta },
165
+ fbeta, 'a, b -> d'
166
+ );
167
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
168
+ t.deepEqual(r.ast.tasks, [
169
+ { after: ['fbeta'], f: falpha, a: ['a'], out: ['c'], type: 'cb', name: 'falpha'},
170
+ { f: fbeta, a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
171
+ ]);
172
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
173
+ t.end();
174
+ });
175
+
176
+
177
+ // Object use
178
+ test('object prop task params', function (t) {
179
+ var r = react('myName', 'a, b, cb -> err, c, e',
180
+ falpha, 'a, b.cat, cb -> err, c',
181
+ fbeta, 'c.dog, b -> d',
182
+ 'd.egg', 'c, cb -> err, e'
183
+ );
184
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
185
+ t.deepEqual(r.ast.tasks, [
186
+ { f: falpha, a: ['a', 'b.cat'], out: ['c'], type: 'cb', name: 'falpha'},
187
+ { f: fbeta, a: ['c.dog', 'b'], out: ['d'], type: 'ret', name: 'fbeta'},
188
+ { f: 'd.egg', a: ['c'], out: ['e'], type: 'cb', name: 'd.egg'}
189
+ ]);
190
+ t.deepEqual(r.ast.outTask, { a: ['c', 'e'], type: 'finalcb' });
191
+ t.end();
192
+ });
193
+
194
+ test('extra arg throws error', function (t) {
195
+ var fn = function () {
196
+ var r = react('myName', 'a, b, cb -> err, c, d',
197
+ falpha, 'a -> err, c', { after: fbeta },
198
+ fbeta, 'a, b -> returns d',
199
+ 'extraBadArg'
200
+ );
201
+ };
202
+ t.throws(fn, new Error('extra unmatched task arg: extraBadArg'));
203
+ t.end();
204
+ });
205
+
206
+ test('not enough args throws error', function (t) {
207
+ var fn = function () {
208
+ var r = react('myName', 'a, b, cb -> c, d',
209
+ falpha, 'a -> err, c', { after: fbeta },
210
+ fbeta
211
+ );
212
+ };
213
+ t.throws(fn, new Error(sprintf('extra unmatched task arg: %s', fbeta)));
214
+ t.end();
215
+ });
216
+
217
+
218
+
219
+ // selectFirst
220
+
221
+ test('selectFirst', function (t) {
222
+ var r = react.selectFirst('myName', 'a, b, cb -> c',
223
+ { otherOptFoo: 'foo'}, // main options
224
+ falpha, 'a, b, cb -> err, c',
225
+ fbeta, 'a, b -> c'
226
+ );
227
+ t.equal(r.ast.name, 'myName');
228
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
229
+ t.deepEqual(r.ast.tasks, [
230
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
231
+ { f: fbeta, a: ['a', 'b'], out: ['c'], type: 'ret', name: 'fbeta', after: ['falpha']}
232
+ ]);
233
+ t.deepEqual(r.ast.outTask, { type: 'finalcbFirst', a: ['c'] });
234
+ t.equal(r.ast.name, 'myName', 'name should match if supplied');
235
+ t.equal(r.ast.otherOptFoo, 'foo', 'other options should pass through');
236
+ t.end();
237
+ });
@@ -0,0 +1,102 @@
1
+ 'use strict';
2
+
3
+ var test = require('tap').test;
4
+
5
+ var EventManager = require('../lib/event-manager.js');
6
+
7
+ test('Event Manager is disabled by default', function (t) {
8
+ var em = EventManager.create();
9
+ t.notOk(em.isEnabled(), 'should be falsey by default');
10
+ t.end();
11
+ });
12
+
13
+ test('Event Manager enabled when a listener if registered', function (t) {
14
+ var em = EventManager.create();
15
+ em.on('foo', function () { });
16
+ t.ok(em.isEnabled(), 'should be truthy');
17
+ t.end();
18
+ });
19
+
20
+ test('Event Manager emits events', function (t) {
21
+ t.plan(1);
22
+ var em = EventManager.create();
23
+ em.on('foo', function (data) {
24
+ t.equal(data, 'hello');
25
+ t.end();
26
+ });
27
+ em.emit('foo', 'hello');
28
+ });
29
+
30
+ test('Event Manager emits events, wildcarded listener', function (t) {
31
+ t.plan(1);
32
+ var em = EventManager.create();
33
+ em.on('foo.*', function (data) {
34
+ t.equal(data, 'hello-world');
35
+ t.end();
36
+ });
37
+ em.emit('foo.bar', 'hello-world');
38
+ });
39
+
40
+ test('Event Manager emits events, all wildcarded listener', function (t) {
41
+ t.plan(1);
42
+ var em = EventManager.create();
43
+ em.on('*', function (data) {
44
+ t.equal(data, 'hello-world');
45
+ t.end();
46
+ });
47
+ em.emit('foo.bar', 'hello-world');
48
+ });
49
+
50
+ test('Event Manager emits event with three args', function (t) {
51
+ t.plan(3);
52
+ var em = EventManager.create();
53
+ em.on('foo', function (data, data2, data3) {
54
+ t.equal(data, 'hello');
55
+ t.equal(data2, 'world');
56
+ t.equal(data3, 100);
57
+ t.end();
58
+ });
59
+ em.emit('foo', 'hello', 'world', 100);
60
+ });
61
+
62
+ test('Event Manager with a parentListener will receive events', function (t) {
63
+ t.plan(1);
64
+ var parentEm = EventManager.create();
65
+ var em = EventManager.create();
66
+ em.parent = parentEm;
67
+ parentEm.on('foo', function (data) {
68
+ t.equal(data, 'world');
69
+ t.end();
70
+ });
71
+ em.emit('foo', 'world');
72
+ });
73
+
74
+ test('Event Manager w/listening grandparent will receive events', function (t) {
75
+ t.plan(1);
76
+ var grandEm = EventManager.create();
77
+ var parentEm = EventManager.create();
78
+ parentEm.parent = grandEm;
79
+ var em = EventManager.create();
80
+ em.parent = parentEm;
81
+ grandEm.on('foo', function (data) {
82
+ t.equal(data, 'world');
83
+ t.end();
84
+ });
85
+ em.emit('foo', 'world');
86
+ });
87
+
88
+ test('Event Manager all parents w/listeners will receive events', function (t) {
89
+ t.plan(3);
90
+ var grandEm = EventManager.create();
91
+ var parentEm = EventManager.create();
92
+ parentEm.parent = grandEm;
93
+ var em = EventManager.create();
94
+ em.parent = parentEm;
95
+ function recData(data) {
96
+ t.equal(data, 'hello');
97
+ }
98
+ grandEm.on('bar', recData);
99
+ parentEm.on('bar', recData);
100
+ em.on('bar', recData);
101
+ em.emit('bar', 'hello');
102
+ });
@@ -0,0 +1,32 @@
1
+ 'use strict';
2
+
3
+ var test = require('tap').test;
4
+
5
+ var react = require('../react');
6
+
7
+ function multiply(x, y, cb) { cb(null, x * y); }
8
+
9
+ test('execOptions as first param', function (t) {
10
+ t.plan(3);
11
+ var fn = react();
12
+ var errors = fn.setAndValidateAST({
13
+ inParams: ['a', 'b'],
14
+ tasks: [
15
+ { f: multiply, a: ['a', 'b'], out: ['c'] }
16
+ ],
17
+ outTask: { a: ['c'] }
18
+ });
19
+ t.deepEqual(errors, [], 'no validation errors');
20
+
21
+ var execOptions = {
22
+ reactExecOptions: true,
23
+ outputStyle: 'callback'
24
+ };
25
+
26
+ fn(execOptions, 2, 3, function (err, c) {
27
+ t.equal(err, null);
28
+ t.equal(c, 6);
29
+ t.end();
30
+ });
31
+ });
32
+
@@ -0,0 +1,37 @@
1
+ 'use strict';
2
+
3
+ var test = require('tap').test;
4
+
5
+ var FinalCbTask = require('../lib/finalcb-task.js');
6
+
7
+ test('undefined cb throws exception', function (t) {
8
+ var fn = function () {
9
+ var finalTask = FinalCbTask.create({}, undefined);
10
+ };
11
+ t.throws(fn, new Error('callback is not a function'));
12
+ t.end();
13
+ });
14
+
15
+ test('null cb throws exception', function (t) {
16
+ var fn = function () {
17
+ var finalTask = FinalCbTask.create({}, null);
18
+ };
19
+ t.throws(fn, new Error('callback is not a function'));
20
+ t.end();
21
+ });
22
+
23
+ test('cb needs to be a function or throws exception', function (t) {
24
+ var fn = function () {
25
+ var finalTask = FinalCbTask.create({}, 'foo');
26
+ };
27
+ t.throws(fn, new Error('callback is not a function'));
28
+ t.end();
29
+ });
30
+
31
+ test('valid fn creates outTask', function (t) {
32
+ function foo() { }
33
+ var finalTask = FinalCbTask.create({ a: ['bar', 'baz']}, foo);
34
+ t.equal(finalTask.f, foo);
35
+ t.deepEqual(finalTask.a, ['bar', 'baz']);
36
+ t.end();
37
+ });
@@ -0,0 +1,288 @@
1
+ 'use strict';
2
+
3
+ var test = require('tap').test;
4
+ var sprintf = require('sprintf').sprintf;
5
+
6
+ var fstrDefine = require('../lib/fstr.js');
7
+
8
+ function falpha() { }
9
+ function fbeta() { }
10
+
11
+ test('module exports an object', function (t) {
12
+ t.type(fstrDefine, 'function', 'has define by DSL method');
13
+ t.end();
14
+ });
15
+
16
+ test('no arguments -> empty inParams, tasks, outTask', function (t) {
17
+ var r = fstrDefine();
18
+ t.deepEqual(r.ast.inParams, []);
19
+ t.deepEqual(r.ast.tasks, []);
20
+ t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
21
+ t.end();
22
+ });
23
+
24
+ test('empty first string -> empty inParams, tasks, outTask', function (t) {
25
+ var r = fstrDefine('');
26
+ t.deepEqual(r.ast.inParams, []);
27
+ t.deepEqual(r.ast.tasks, []);
28
+ t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
29
+ t.end();
30
+ });
31
+
32
+
33
+ test('single first string -> inParams["foo"], empty tasks, outTask', function (t) {
34
+ var r = fstrDefine('foo');
35
+ t.deepEqual(r.ast.inParams, ['foo']);
36
+ t.deepEqual(r.ast.tasks, []);
37
+ t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
38
+ t.end();
39
+ });
40
+
41
+ test('triple first string -> inParams["foo", "bar", "baz"], empty tasks, outTask',
42
+ function (t) {
43
+ var r = fstrDefine(' foo, bar,baz ');
44
+ t.deepEqual(r.ast.inParams, ['foo', 'bar', 'baz']);
45
+ t.deepEqual(r.ast.tasks, []);
46
+ t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
47
+ t.end();
48
+ });
49
+
50
+ test('single task, single out params', function (t) {
51
+ var r = fstrDefine('', [
52
+ falpha, 'a, b -> err, c'
53
+ ], 'c');
54
+ t.deepEqual(r.ast.inParams, []);
55
+ t.deepEqual(r.ast.tasks, [
56
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
57
+ ]);
58
+ t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
59
+ t.end();
60
+ });
61
+
62
+ test('single task, err and out params', function (t) {
63
+ var r = fstrDefine('', [
64
+ falpha, 'a, b -> err, c'
65
+ ], 'err, c');
66
+ t.deepEqual(r.ast.inParams, []);
67
+ t.deepEqual(r.ast.tasks, [
68
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
69
+ ]);
70
+ t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
71
+ t.end();
72
+ });
73
+
74
+ test('single task, ERR and out params', function (t) {
75
+ var r = fstrDefine('', [
76
+ falpha, 'a, b -> ERR, c'
77
+ ], 'ERR, c');
78
+ t.deepEqual(r.ast.inParams, []);
79
+ t.deepEqual(r.ast.tasks, [
80
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
81
+ ]);
82
+ t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
83
+ t.end();
84
+ });
85
+
86
+ test('cb used in defs is simply ignored', function (t) {
87
+ var r = fstrDefine('a, b, cb', [
88
+ falpha, 'a, b, cb -> err, c'
89
+ ], 'err, c');
90
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
91
+ t.deepEqual(r.ast.tasks, [
92
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
93
+ ]);
94
+ t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
95
+ t.end();
96
+ });
97
+
98
+ test('callback used in defs is simply ignored', function (t) {
99
+ var r = fstrDefine('a, b, callback', [
100
+ falpha, 'a, b, callback -> err, c'
101
+ ], 'err, c');
102
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
103
+ t.deepEqual(r.ast.tasks, [
104
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
105
+ ]);
106
+ t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
107
+ t.end();
108
+ });
109
+
110
+ test('two inputs, two tasks, two out params', function (t) {
111
+ var r = fstrDefine('a, b', [
112
+ falpha, 'a, b -> err, c',
113
+ fbeta, 'a, b -> err, d, e'
114
+ ], 'c, d');
115
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
116
+ t.deepEqual(r.ast.tasks, [
117
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
118
+ { f: fbeta, a: ['a', 'b'], out: ['d', 'e'], type: 'cb', name: 'fbeta'}
119
+ ]);
120
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
121
+ t.end();
122
+ });
123
+
124
+ test('two inputs, two tasks, two out params, options', function (t) {
125
+ var r = fstrDefine('a, b', [
126
+ falpha, 'a, b -> err, c',
127
+ fbeta, 'a, b -> err, d, e'
128
+ ], 'c, d', { name: 'myflow', otherOptFoo: 'foo'});
129
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
130
+ t.deepEqual(r.ast.tasks, [
131
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
132
+ { f: fbeta, a: ['a', 'b'], out: ['d', 'e'], type: 'cb', name: 'fbeta'}
133
+ ]);
134
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
135
+ t.equal(r.ast.name, 'myflow', 'name should match if supplied');
136
+ t.equal(r.ast.otherOptFoo, 'foo', 'other options should pass through');
137
+ t.end();
138
+ });
139
+
140
+ test('two inputs, two mixed tasks, two out params', function (t) {
141
+ var r = fstrDefine('a, b', [
142
+ falpha, 'a, b -> err, c',
143
+ fbeta, 'a, b -> returns d'
144
+ ], 'c, d');
145
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
146
+ t.deepEqual(r.ast.tasks, [
147
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
148
+ { f: fbeta, a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
149
+ ]);
150
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
151
+ t.end();
152
+ });
153
+
154
+ test('uses return', function (t) {
155
+ var r = fstrDefine('a, b', [
156
+ falpha, 'a, b -> err, c',
157
+ fbeta, 'a, b -> return d'
158
+ ], 'c, d');
159
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
160
+ t.deepEqual(r.ast.tasks, [
161
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
162
+ { f: fbeta, a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
163
+ ]);
164
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
165
+ t.end();
166
+ });
167
+
168
+ test('uses Return', function (t) {
169
+ var r = fstrDefine('a, b', [
170
+ falpha, 'a, b -> err, c',
171
+ fbeta, 'a, b -> Return d'
172
+ ], 'c, d');
173
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
174
+ t.deepEqual(r.ast.tasks, [
175
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
176
+ { f: fbeta, a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
177
+ ]);
178
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
179
+ t.end();
180
+ });
181
+
182
+ test('uses RETURN', function (t) {
183
+ var r = fstrDefine('a, b', [
184
+ falpha, 'a, b -> err, c',
185
+ fbeta, 'a, b -> RETURN d'
186
+ ], 'c, d');
187
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
188
+ t.deepEqual(r.ast.tasks, [
189
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
190
+ { f: fbeta, a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
191
+ ]);
192
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
193
+ t.end();
194
+ });
195
+
196
+ test('uses RETURNS', function (t) {
197
+ var r = fstrDefine('a, b', [
198
+ falpha, 'a, b -> err, c',
199
+ fbeta, 'a, b -> RETURNS d'
200
+ ], 'c, d');
201
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
202
+ t.deepEqual(r.ast.tasks, [
203
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
204
+ { f: fbeta, a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
205
+ ]);
206
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
207
+ t.end();
208
+ });
209
+
210
+ test('two inputs, two mixed tasks, two out params, opts', function (t) {
211
+ var r = fstrDefine('a, b', [
212
+ falpha, 'a -> err, c', { after: fbeta },
213
+ fbeta, 'a, b -> returns d'
214
+ ], 'c, d');
215
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
216
+ t.deepEqual(r.ast.tasks, [
217
+ { after: ['fbeta'], f: falpha, a: ['a'], out: ['c'], type: 'cb', name: 'falpha'},
218
+ { f: fbeta, a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
219
+ ]);
220
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
221
+ t.end();
222
+ });
223
+
224
+
225
+ // Object use
226
+ test('object prop task params', function (t) {
227
+ var r = fstrDefine('a, b', [
228
+ falpha, 'a, b.cat -> err, c',
229
+ fbeta, 'c.dog, b -> returns d',
230
+ 'd.egg', 'c -> e'
231
+ ], 'c, e');
232
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
233
+ t.deepEqual(r.ast.tasks, [
234
+ { f: falpha, a: ['a', 'b.cat'], out: ['c'], type: 'cb', name: 'falpha'},
235
+ { f: fbeta, a: ['c.dog', 'b'], out: ['d'], type: 'ret', name: 'fbeta'},
236
+ { f: 'd.egg', a: ['c'], out: ['e'], type: 'cb', name: 'd.egg'}
237
+ ]);
238
+ t.deepEqual(r.ast.outTask, { a: ['c', 'e'], type: 'finalcb' });
239
+ t.end();
240
+ });
241
+
242
+
243
+
244
+
245
+
246
+ test('extra arg throws error', function (t) {
247
+ var fn = function () {
248
+ var r = fstrDefine('a, b', [
249
+ falpha, 'a -> err, c', { after: fbeta },
250
+ fbeta, 'a, b -> returns d',
251
+ 'extraBadArg'
252
+ ], 'c, d');
253
+ };
254
+ t.throws(fn, new Error('extra unmatched task arg: extraBadArg'));
255
+ t.end();
256
+ });
257
+
258
+ test('not enough args throws error', function (t) {
259
+ var fn = function () {
260
+ var r = fstrDefine('a, b', [
261
+ falpha, 'a -> err, c', { after: fbeta },
262
+ fbeta
263
+ ], 'c, d');
264
+ };
265
+ t.throws(fn, new Error(sprintf('extra unmatched task arg: %s', fbeta)));
266
+ t.end();
267
+ });
268
+
269
+
270
+
271
+ /* selectFirst */
272
+
273
+ test('selectFirst', function (t) {
274
+ var r = fstrDefine.selectFirst('a, b', [
275
+ falpha, 'a, b -> err, c',
276
+ fbeta, 'a, b -> returns c'
277
+ ], 'c', { name: 'myflow', otherOptFoo: 'foo'});
278
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
279
+ t.deepEqual(r.ast.tasks, [
280
+ { f: falpha, a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
281
+ { f: fbeta, a: ['a', 'b'], out: ['c'], type: 'ret', name: 'fbeta', after: ['falpha']}
282
+ ]);
283
+ t.deepEqual(r.ast.outTask, { type: 'finalcbFirst', a: ['c'] });
284
+ t.equal(r.ast.name, 'myflow', 'name should match if supplied');
285
+ t.equal(r.ast.otherOptFoo, 'foo', 'other options should pass through');
286
+ t.end();
287
+ });
288
+