react 0.0.1 → 0.2.0

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 (69) hide show
  1. package/.npmignore +6 -0
  2. package/Jakefile.js +8 -0
  3. package/README.md +233 -83
  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/default1.js +40 -0
  8. package/examples/fstr-events1.js +51 -0
  9. package/examples/fstr1.js +36 -0
  10. package/examples/pcode1.js +22 -0
  11. package/jake-tasks/jake-test.js +64 -0
  12. package/lib/base-task.js +115 -0
  13. package/lib/cb-task.js +67 -0
  14. package/lib/chain.js +148 -0
  15. package/lib/core.js +96 -0
  16. package/lib/dsl.js +122 -0
  17. package/lib/error.js +37 -0
  18. package/lib/event-manager.js +57 -0
  19. package/lib/finalcb-first-task.js +59 -0
  20. package/lib/finalcb-task.js +54 -0
  21. package/lib/fstr.js +110 -0
  22. package/lib/id.js +10 -0
  23. package/lib/input-parser.js +44 -0
  24. package/lib/parse.js +29 -0
  25. package/lib/pcode.js +164 -0
  26. package/lib/ret-task.js +67 -0
  27. package/lib/status.js +5 -0
  28. package/lib/task.js +234 -0
  29. package/lib/validate.js +102 -0
  30. package/lib/vcon.js +76 -0
  31. package/oldExamples/analyze.js +29 -0
  32. package/oldExamples/analyze2.js +29 -0
  33. package/oldExamples/example10-dsl.js +63 -0
  34. package/oldExamples/example11.js +62 -0
  35. package/oldExamples/example12.js +63 -0
  36. package/oldExamples/example13.js +63 -0
  37. package/oldExamples/example14.js +63 -0
  38. package/oldExamples/example15.js +75 -0
  39. package/{test → oldExamples}/example6-ast.js +4 -4
  40. package/{test → oldExamples}/example6-dsl.js +3 -2
  41. package/{test → oldExamples}/example8-ast.js +3 -2
  42. package/{test → oldExamples}/example8-dsl.js +3 -2
  43. package/oldExamples/example9-ast.js +58 -0
  44. package/oldExamples/example9-dsl.js +57 -0
  45. package/oldExamples/function-str-ex1.js +33 -0
  46. package/oldExamples/function-str-ex2.js +67 -0
  47. package/oldExamples/trait1.js +41 -0
  48. package/oldExamples/trait2.js +44 -0
  49. package/package.json +16 -6
  50. package/react.js +11 -1
  51. package/test/ast.test.js +69 -0
  52. package/test/cb-task.test.js +197 -0
  53. package/test/chain.test.js +239 -0
  54. package/test/core.test.js +519 -0
  55. package/test/dsl.test.js +237 -0
  56. package/test/event-manager.test.js +102 -0
  57. package/test/exec-options.test.js +32 -0
  58. package/test/finalcb-task.test.js +37 -0
  59. package/test/fstr.test.js +288 -0
  60. package/test/input-parser.test.js +62 -0
  61. package/test/module-use.test.js +317 -0
  62. package/test/pcode.test.js +321 -0
  63. package/test/ret-task.test.js +199 -0
  64. package/test/task.test.js +21 -0
  65. package/test/validate-cb-task.test.js +74 -0
  66. package/test/validate-ret-task.test.js +83 -0
  67. package/test/validate.test.js +218 -0
  68. package/test/vcon.test.js +160 -0
  69. package/lib/react.js +0 -228
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+
3
+ var test = require('tap').test;
4
+
5
+ var inputParser = require('../lib/input-parser.js');
6
+
7
+ test('parser parses input args', function (t) {
8
+ var ast = { inParams: ['a', 'b'] };
9
+ var parsedInput = inputParser([10, 20], ast);
10
+ t.deepEqual(parsedInput.args, [10, 20]);
11
+ t.deepEqual(parsedInput.options, inputParser.defaultExecOptions);
12
+ t.end();
13
+ });
14
+
15
+ test('parser parses input args with cb', function (t) {
16
+ function foo() { }
17
+ var ast = { inParams: ['a', 'b'] };
18
+ var parsedInput = inputParser([10, 20, foo], ast);
19
+ t.deepEqual(parsedInput.args, [10, 20]);
20
+ t.deepEqual(parsedInput.cb, foo);
21
+ t.deepEqual(parsedInput.options, inputParser.defaultExecOptions);
22
+ t.end();
23
+ });
24
+
25
+ test('parser parses input args with cb and extra args', function (t) {
26
+ function foo() { }
27
+ var ast = { inParams: ['a', 'b'] };
28
+ var parsedInput = inputParser([10, 20, foo, 30, 40], ast);
29
+ t.deepEqual(parsedInput.args, [10, 20]);
30
+ t.deepEqual(parsedInput.cb, foo);
31
+ t.deepEqual(parsedInput.extraArgs, [30, 40]);
32
+ t.deepEqual(parsedInput.options, inputParser.defaultExecOptions);
33
+ t.end();
34
+ });
35
+
36
+ test('parser parses input args with extra args', function (t) {
37
+ var ast = { inParams: [] };
38
+ var execOptions = { reactExecOptions: true, outputStyle: 'none' };
39
+ var parsedInput = inputParser([execOptions, 10, 20], ast);
40
+ t.deepEqual(parsedInput.args, []);
41
+ t.deepEqual(parsedInput.extraArgs, [10, 20]);
42
+ t.end();
43
+ });
44
+
45
+ test('parser pulls react exec option off arg list', function (t) {
46
+ var ast = { inParams: ['a', 'b'] };
47
+ var execOptions = { reactExecOptions: true, foo: 10 };
48
+ var parsedInput = inputParser([execOptions, 10, 20], ast);
49
+ t.deepEqual(parsedInput.args, [10, 20]);
50
+ t.deepEqual(parsedInput.options, { reactExecOptions: true, outputStyle: 'callback', foo: 10 });
51
+ t.end();
52
+ });
53
+
54
+ test('parser pulls react exec options off arg list and merges from left to right', function (t) {
55
+ var ast = { inParams: ['a', 'b'] };
56
+ var execOptions = { reactExecOptions: true, foo: 12, bar: 24 };
57
+ var execOptions2 = { reactExecOptions: true, bar: 36, baz: 'hello' };
58
+ var parsedInput = inputParser([execOptions, execOptions2, 10, 20], ast);
59
+ t.deepEqual(parsedInput.args, [10, 20]);
60
+ t.deepEqual(parsedInput.options, { reactExecOptions: true, outputStyle: 'callback', foo: 12, bar: 36, baz: 'hello' });
61
+ t.end();
62
+ });
@@ -0,0 +1,317 @@
1
+ 'use strict';
2
+
3
+ var test = require('tap').test;
4
+ var BaseTask = require('../lib/base-task.js');
5
+
6
+ var react = require('../react');
7
+
8
+ /**
9
+ @example
10
+ var react = require('react');
11
+ react.options.an_option = 'something';
12
+
13
+ // define function
14
+ var loadAndSave = react('myName', 'one, two, cb -> err, result1, result2',
15
+ foo, 'one, cb -> err, cat',
16
+ bar, 'two, cat, cb -> err, dog',
17
+ baz, 'dog, cb -> err, result1',
18
+ bum, 'dog, cb -> err, result2');
19
+
20
+ // OR using AST
21
+
22
+ var loadAndSave = react();
23
+ loadAndSave.setAndValidateAST({
24
+ inParams: ['one', 'two'],
25
+ tasks: { },
26
+ outTask: { a: ['three'] }
27
+ });
28
+
29
+ //if you want to listen to task completion events
30
+ loadAndSave.events.on('task.complete', function (taskObj) { });
31
+
32
+ loadAndSave(1,2,cb); // execute like any other function
33
+ */
34
+
35
+ test('module exports an function object with properties', function (t) {
36
+ t.type(react, 'function', 'is a core constructor and default dsl function');
37
+ t.type(react.options, 'object', 'has property for global react options');
38
+ t.type(react.fstrDefine, 'function', 'has fn property for using fstr dsl');
39
+ t.type(react.pcodeDefine, 'function', 'has fn property for using pcode dsl');
40
+ t.type(react.chainDefine, 'function', 'has fn property for chain define');
41
+ t.end();
42
+ });
43
+
44
+ function foo() { }
45
+ function bar() { }
46
+
47
+ test('calling react constructor function creates new function with ast', function (t) {
48
+ var r = react();
49
+ t.type(r, 'function', 'is a function ready to execute flow');
50
+ t.type(r.ast, 'object', 'is object for inspecting AST');
51
+ t.deepEqual(r.ast.inParams, [], 'ast.inParams should return empty array');
52
+ t.deepEqual(r.ast.tasks, [], 'ast.tasks() should return empty array');
53
+ t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
54
+ t.end();
55
+ });
56
+
57
+ test('setAndValidateAST sets the ast and validates returning errors', function (t) {
58
+ var r = react();
59
+ var errors = r.setAndValidateAST({
60
+ inParams: ['a', 'b'],
61
+ tasks: [
62
+ { f: foo, a: ['a'], out: ['c'] },
63
+ { f: bar, a: ['b'], out: ['d'] }
64
+ ],
65
+ outTask: { a: ['c', 'd'] }
66
+ });
67
+ t.deepEqual(r.ast.inParams, ['a', 'b'], 'ast.inParams() should match array just set');
68
+ t.deepEqual(r.ast.tasks, [
69
+ { f: foo, a: ['a'], out: ['c'], type: 'cb', name: 'foo' },
70
+ { f: bar, a: ['b'], out: ['d'], type: 'cb', name: 'bar' }
71
+ ]);
72
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' }, 'should return obj just set');
73
+ t.end();
74
+ });
75
+
76
+ test('use react() default DSL from module', function (t) {
77
+ t.plan(3);
78
+ function multiply(a, b, cb) { cb(null, a * b); }
79
+ function add(a, b, cb) { cb(null, a + b); }
80
+ var fn = react('multiplyAdd', 'a, b, cb -> err, m, s',
81
+ multiply, 'a, b, cb -> err, m',
82
+ add, 'm, a, cb -> err, s'
83
+ );
84
+
85
+ fn(2, 3, function (err, m, s) {
86
+ t.deepEqual(err, null, 'should not be any error');
87
+ t.equal(m, 6);
88
+ t.equal(s, 8);
89
+ t.end();
90
+ });
91
+ });
92
+
93
+ test('use react.selectFirst() default DSL with events', function (t) {
94
+ t.plan(7);
95
+ function noSuccess(a, b, cb) {
96
+ setTimeout(function () { cb(null); }, 100); // returns undefined result
97
+ }
98
+ function noSuccessNull(a, b, cb) { cb(null, null); } // returns null result
99
+ function add(a, b, cb) { cb(null, a + b); }
100
+
101
+ var events = [];
102
+ function accumEvents(task) {
103
+ events.push(task);
104
+ }
105
+
106
+ var fn = react.selectFirst('mySelectFirst', 'a, b, cb -> err, c',
107
+ noSuccess, 'a, b, cb -> err, c',
108
+ noSuccessNull, 'a, b, cb -> err, c',
109
+ add, 'a, b, cb -> err, c',
110
+ noSuccess, 'a, b, cb -> err, c'
111
+ );
112
+
113
+ fn.events.on('task.complete', accumEvents);
114
+
115
+ fn(2, 3, function (err, c) {
116
+ t.deepEqual(err, null, 'should not be any error');
117
+ t.equal(c, 5);
118
+ t.equal(events.length, 3, 'should have seen two task compl events');
119
+ t.equal(events[0].name, 'noSuccess', 'name matches');
120
+ t.equal(events[1].name, 'noSuccessNull', 'name matches');
121
+ t.equal(events[2].name, 'add', 'name matches');
122
+ t.deepEqual(events[2].results, [5], 'results match');
123
+ t.end();
124
+ });
125
+ });
126
+
127
+
128
+ test('use pcodeDefine from module', function (t) {
129
+ t.plan(3);
130
+ function multiply(a, b, cb) { cb(null, a * b); }
131
+ function add(a, b, cb) { cb(null, a + b); }
132
+ var locals = { multiply: multiply, add: add };
133
+ var fn = react.pcodeDefine('a, b, cb', [
134
+ 'm := multiply(a, b)',
135
+ 's := add(m, a)',
136
+ 'cb(err, m, s)'
137
+ ], locals);
138
+
139
+ fn(2, 3, function (err, m, s) {
140
+ t.deepEqual(err, null, 'should not be any error');
141
+ t.equal(m, 6);
142
+ t.equal(s, 8);
143
+ t.end();
144
+ });
145
+ });
146
+
147
+ test('use pcodeDefine with events', function (t) {
148
+ t.plan(8);
149
+ function multiply(a, b, cb) { cb(null, a * b); }
150
+ function add(a, b, cb) { cb(null, a + b); }
151
+
152
+ var events = [];
153
+ function accumEvents(task) {
154
+ events.push(task);
155
+ }
156
+
157
+ var locals = { multiply: multiply, add: add };
158
+ var fn = react.pcodeDefine('a, b, cb', [
159
+ 'm := multiply(a, b)',
160
+ 's := add(m, a)',
161
+ 'cb(err, m, s)'
162
+ ], locals);
163
+
164
+ fn.events.on('task.complete', accumEvents);
165
+
166
+ fn(2, 3, function (err, m, s) {
167
+ t.deepEqual(err, null, 'should not be any error');
168
+ t.equal(m, 6);
169
+ t.equal(s, 8);
170
+ t.equal(events.length, 2, 'should have seen two task compl events');
171
+ t.equal(events[0].name, 'multiply', 'name matches');
172
+ t.deepEqual(events[0].results, [6], 'results match');
173
+ t.equal(events[1].name, 'add', 'name matches');
174
+ t.deepEqual(events[1].results, [8], 'results match');
175
+ t.end();
176
+ });
177
+ });
178
+
179
+ test('use pcodeDefine.selectFirst with events', function (t) {
180
+ t.plan(7);
181
+ function noSuccess(a, b, cb) {
182
+ setTimeout(function () { cb(null); }, 100); // returns undefined result
183
+ }
184
+ function noSuccessNull(a, b, cb) { cb(null, null); } // returns null result
185
+ function add(a, b, cb) { cb(null, a + b); }
186
+
187
+ var events = [];
188
+ function accumEvents(task) {
189
+ events.push(task);
190
+ }
191
+
192
+ var locals = { noSuccess: noSuccess, noSuccessNull: noSuccessNull, add: add };
193
+ var fn = react.pcodeDefine.selectFirst('a, b, cb', [
194
+ 'c := noSuccess(a, b)',
195
+ 'c := noSuccessNull(a, b)',
196
+ 'c := add(a, b)',
197
+ 'c := noSuccess(a, b)',
198
+ 'cb(err, c)'
199
+ ], locals);
200
+
201
+ fn.events.on('task.complete', accumEvents);
202
+
203
+ fn(2, 3, function (err, c) {
204
+ t.deepEqual(err, null, 'should not be any error');
205
+ t.equal(c, 5);
206
+ t.equal(events.length, 3, 'should have seen two task compl events');
207
+ t.equal(events[0].name, 'noSuccess', 'name matches');
208
+ t.equal(events[1].name, 'noSuccessNull', 'name matches');
209
+ t.equal(events[2].name, 'add', 'name matches');
210
+ t.deepEqual(events[2].results, [5], 'results match');
211
+ t.end();
212
+ });
213
+ });
214
+
215
+ test('use pcodeDefine events emit to global emitter', function (t) {
216
+ t.plan(8);
217
+ function multiply(a, b, cb) { cb(null, a * b); }
218
+ function add(a, b, cb) { cb(null, a + b); }
219
+
220
+ var events = [];
221
+ function accumEvents(task) {
222
+ events.push(task);
223
+ }
224
+
225
+ var locals = { multiply: multiply, add: add };
226
+ var fn = react.pcodeDefine('a, b, cb', [
227
+ 'm := multiply(a, b)',
228
+ 's := add(m, a)',
229
+ 'cb(err, m, s)'
230
+ ], locals);
231
+
232
+ react.events.on('task.complete', accumEvents); // the global react emitter
233
+
234
+ fn(2, 3, function (err, m, s) {
235
+ t.deepEqual(err, null, 'should not be any error');
236
+ t.equal(m, 6);
237
+ t.equal(s, 8);
238
+ t.equal(events.length, 2, 'should have seen two task compl events');
239
+ t.equal(events[0].name, 'multiply', 'name matches');
240
+ t.deepEqual(events[0].results, [6], 'results match');
241
+ t.equal(events[1].name, 'add', 'name matches');
242
+ t.deepEqual(events[1].results, [8], 'results match');
243
+ t.end();
244
+ });
245
+ });
246
+
247
+
248
+
249
+ test('chainDefine use', function (t) {
250
+ t.plan(8);
251
+ function multiply(a, b, cb) { cb(null, a * b); }
252
+ function add(a, b, cb) { cb(null, a + b); }
253
+
254
+ var events = [];
255
+ function accumEvents(task) {
256
+ events.push(task);
257
+ }
258
+
259
+ var fn = react.chainDefine()
260
+ .in('a', 'b', 'cb')
261
+ .out('err', 'm', 's')
262
+ .async(multiply).in('a', 'b', 'cb').out('err', 'm')
263
+ .async(add).in('m', 'a', 'cb').out('err', 's')
264
+ .end();
265
+
266
+ fn.events.on('task.complete', accumEvents);
267
+
268
+ fn(2, 3, function (err, m, s) {
269
+ t.deepEqual(err, null, 'should not be any error');
270
+ t.equal(m, 6);
271
+ t.equal(s, 8);
272
+ t.equal(events.length, 2, 'should have seen two task compl events');
273
+ t.equal(events[0].name, 'multiply', 'name matches');
274
+ t.deepEqual(events[0].results, [6], 'results match');
275
+ t.equal(events[1].name, 'add', 'name matches');
276
+ t.deepEqual(events[1].results, [8], 'results match');
277
+ t.end();
278
+ });
279
+ });
280
+
281
+ test('use chainDefine selectFirst with events', function (t) {
282
+ t.plan(7);
283
+ function noSuccess(a, b, cb) {
284
+ setTimeout(function () { cb(null); }, 100); // returns undefined result
285
+ }
286
+ function noSuccessNull(a, b, cb) { cb(null, null); } // returns null result
287
+ function add(a, b, cb) { cb(null, a + b); }
288
+
289
+ var events = [];
290
+ function accumEvents(task) {
291
+ events.push(task);
292
+ }
293
+
294
+ var fn = react.chainDefine()
295
+ .selectFirst()
296
+ .in('a', 'b', 'cb')
297
+ .out('err', 'c')
298
+ .async(noSuccess).in('a', 'b', 'cb').out('err', 'c')
299
+ .async(noSuccessNull).in('a', 'b', 'cb').out('err', 'c')
300
+ .async(add).in('a', 'b', 'cb').out('err', 'c')
301
+ .async(noSuccess).in('a', 'b', 'cb').out('err', 'c')
302
+ .end();
303
+
304
+ fn.events.on('task.complete', accumEvents);
305
+
306
+ fn(2, 3, function (err, c) {
307
+ t.deepEqual(err, null, 'should not be any error');
308
+ t.equal(c, 5);
309
+ t.equal(events.length, 3, 'should have seen two task compl events');
310
+ t.equal(events[0].name, 'noSuccess', 'name matches');
311
+ t.equal(events[1].name, 'noSuccessNull', 'name matches');
312
+ t.equal(events[2].name, 'add', 'name matches');
313
+ t.deepEqual(events[2].results, [5], 'results match');
314
+ t.end();
315
+ });
316
+ });
317
+
@@ -0,0 +1,321 @@
1
+ 'use strict';
2
+
3
+ var test = require('tap').test;
4
+ var sprintf = require('sprintf').sprintf;
5
+
6
+ var pcode = require('../lib/pcode.js');
7
+
8
+ function falpha() { }
9
+ function fbeta() { }
10
+ function fcharlie() { }
11
+
12
+ test('module exports an object', function (t) {
13
+ t.type(pcode, 'function', 'has define by DSL method');
14
+ t.end();
15
+ });
16
+
17
+ test('no arguments -> empty inParams, tasks, outTask', function (t) {
18
+ var r = pcode();
19
+ t.deepEqual(r.ast.inParams, []);
20
+ t.deepEqual(r.ast.tasks, []);
21
+ t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
22
+ t.end();
23
+ });
24
+
25
+ test('empty first string -> empty inParams, tasks, outTask', function (t) {
26
+ var r = pcode('');
27
+ t.deepEqual(r.ast.inParams, []);
28
+ t.deepEqual(r.ast.tasks, []);
29
+ t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
30
+ t.end();
31
+ });
32
+
33
+
34
+ test('single first string -> inParams["foo"], empty tasks, outTask', function (t) {
35
+ var r = pcode('foo');
36
+ t.deepEqual(r.ast.inParams, ['foo']);
37
+ t.deepEqual(r.ast.tasks, []);
38
+ t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
39
+ t.end();
40
+ });
41
+
42
+ test('triple first string -> inParams["foo", "bar", "baz"], empty tasks, outTask',
43
+ function (t) {
44
+ var r = pcode(' foo, bar,baz ');
45
+ t.deepEqual(r.ast.inParams, ['foo', 'bar', 'baz']);
46
+ t.deepEqual(r.ast.tasks, []);
47
+ t.deepEqual(r.ast.outTask, { a: [], type: 'finalcb' });
48
+ t.end();
49
+ });
50
+
51
+ test('single task, single out params', function (t) {
52
+ var locals = { falpha: falpha };
53
+ var r = pcode('', [
54
+ 'c := falpha(a, b)',
55
+ 'cb(err, c)'
56
+ ], locals);
57
+ t.deepEqual(r.ast.inParams, []);
58
+ t.deepEqual(r.ast.tasks, [
59
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
60
+ ]);
61
+ t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
62
+ t.end();
63
+ });
64
+
65
+ test('single task, err and out params', function (t) {
66
+ var locals = { falpha: falpha };
67
+ var r = pcode('', [
68
+ 'c := falpha(a, b)',
69
+ 'cb(err, c)'
70
+ ], locals);
71
+ t.deepEqual(r.ast.inParams, []);
72
+ t.deepEqual(r.ast.tasks, [
73
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'}
74
+ ]);
75
+ t.deepEqual(r.ast.outTask, { a: ['c'], type: 'finalcb' });
76
+ t.end();
77
+ });
78
+
79
+ test('two inputs, two tasks, two out params', function (t) {
80
+ var locals = { falpha: falpha, fbeta: fbeta };
81
+ var r = pcode('a, b', [
82
+ 'c := falpha(a, b)',
83
+ 'd, e := fbeta(a, b)',
84
+ 'cb(err, c, d)'
85
+ ], locals);
86
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
87
+ t.deepEqual(r.ast.tasks, [
88
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
89
+ { f: 'fbeta', a: ['a', 'b'], out: ['d', 'e'], type: 'cb', name: 'fbeta'}
90
+ ]);
91
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
92
+ t.end();
93
+ });
94
+
95
+ test('two inputs, two tasks, two out params, options', function (t) {
96
+ var locals = { falpha: falpha, fbeta: fbeta };
97
+ var r = pcode('a, b', [
98
+ 'c := falpha(a, b)',
99
+ 'd, e := fbeta(a, b)',
100
+ 'cb(err, c, d)'
101
+ ], locals, { name: 'myflow', otherOptFoo: 'foo'});
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
+ { f: 'fbeta', a: ['a', 'b'], out: ['d', 'e'], type: 'cb', name: 'fbeta'}
106
+ ]);
107
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
108
+ t.equal(r.ast.name, 'myflow', 'name should match if supplied');
109
+ t.equal(r.ast.otherOptFoo, 'foo', 'other options should pass through');
110
+ t.end();
111
+ });
112
+
113
+
114
+
115
+ test('two inputs, two mixed tasks, two out params', function (t) {
116
+ var locals = { falpha: falpha, fbeta: fbeta };
117
+ var r = pcode('a, b', [
118
+ 'c := falpha(a, b)',
119
+ 'd = fbeta(a, b)',
120
+ 'cb(err, c, d)'
121
+ ], locals);
122
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
123
+ t.deepEqual(r.ast.tasks, [
124
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
125
+ { f: 'fbeta', a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
126
+ ]);
127
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
128
+ t.end();
129
+ });
130
+
131
+ test('allow cb in the definitions', function (t) {
132
+ var locals = { falpha: falpha, fbeta: fbeta };
133
+ var r = pcode('a, b, cb', [
134
+ 'c := falpha(a, b, cb)',
135
+ 'd = fbeta(a, b)',
136
+ 'cb(err, c, d)'
137
+ ], locals);
138
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
139
+ t.deepEqual(r.ast.tasks, [
140
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
141
+ { f: 'fbeta', a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
142
+ ]);
143
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
144
+ t.end();
145
+ });
146
+
147
+ test('allow Cb in the definitions', function (t) {
148
+ var locals = { falpha: falpha, fbeta: fbeta };
149
+ var r = pcode('a, b, Cb', [
150
+ 'c := falpha(a, b, Cb)',
151
+ 'd = fbeta(a, b)',
152
+ 'cb(err, c, d)'
153
+ ], locals);
154
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
155
+ t.deepEqual(r.ast.tasks, [
156
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
157
+ { f: 'fbeta', a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
158
+ ]);
159
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
160
+ t.end();
161
+ });
162
+
163
+ test('allow callback in the definitions', function (t) {
164
+ var locals = { falpha: falpha, fbeta: fbeta };
165
+ var r = pcode('a, b, callback', [
166
+ 'c := falpha(a, b, callback)',
167
+ 'd = fbeta(a, b)',
168
+ 'callback(err, c, d)'
169
+ ], locals);
170
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
171
+ t.deepEqual(r.ast.tasks, [
172
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
173
+ { f: 'fbeta', a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
174
+ ]);
175
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
176
+ t.end();
177
+ });
178
+
179
+ test('allow Callback in the definitions', function (t) {
180
+ var locals = { falpha: falpha, fbeta: fbeta };
181
+ var r = pcode('a, b, Callback', [
182
+ 'c := falpha(a, b, Callback)',
183
+ 'd = fbeta(a, b)',
184
+ 'Callback(err, c, d)'
185
+ ], locals);
186
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
187
+ t.deepEqual(r.ast.tasks, [
188
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
189
+ { f: 'fbeta', a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
190
+ ]);
191
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
192
+ t.end();
193
+ });
194
+
195
+
196
+
197
+
198
+
199
+ test('var prefix two inputs, two mixed tasks, two out params', function (t) {
200
+ var locals = { falpha: falpha, fbeta: fbeta };
201
+ var r = pcode('a, b', [
202
+ 'var c := falpha(a, b);',
203
+ 'var d = fbeta(a, b);',
204
+ 'cb(err, c, d);'
205
+ ], locals);
206
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
207
+ t.deepEqual(r.ast.tasks, [
208
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
209
+ { f: 'fbeta', a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
210
+ ]);
211
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
212
+ t.end();
213
+ });
214
+
215
+ test('when single ret fn:done', function (t) {
216
+ var locals = { falpha: falpha, fbeta: fbeta };
217
+ var r = pcode('a, b', [
218
+ 'c := falpha(a, b)',
219
+ 'd = fbeta(a, b) when falpha:done',
220
+ 'cb(err, c, d);'
221
+ ], locals);
222
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
223
+ t.deepEqual(r.ast.tasks, [
224
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
225
+ { f: 'fbeta', a: ['a', 'b'], out: ['d'], type: 'ret', after: ['falpha'], name: 'fbeta'}
226
+ ]);
227
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
228
+ t.end();
229
+ });
230
+
231
+ test('when single cb fn:done', function (t) {
232
+ var locals = { falpha: falpha, fbeta: fbeta };
233
+ var r = pcode('a, b', [
234
+ 'c := falpha(a, b) when fbeta:done',
235
+ 'd = fbeta(a, b)',
236
+ 'cb(err, c, d);'
237
+ ], locals);
238
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
239
+ t.deepEqual(r.ast.tasks, [
240
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', after: ['fbeta'], name: 'falpha'},
241
+ { f: 'fbeta', a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'}
242
+ ]);
243
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
244
+ t.end();
245
+ });
246
+
247
+ test('when multiple fn:done cb', function (t) {
248
+ var locals = { falpha: falpha, fbeta: fbeta, fcharlie: fcharlie };
249
+ var r = pcode('a, b', [
250
+ 'd = fbeta(a, b)',
251
+ 'e = fcharlie(a, b)',
252
+ 'c := falpha(a, b) when fbeta:done and fcharlie:done',
253
+ 'cb(err, c, d);'
254
+ ], locals);
255
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
256
+ t.deepEqual(r.ast.tasks, [
257
+ { f: 'fbeta', a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'},
258
+ { f: 'fcharlie', a: ['a', 'b'], out: ['e'], type: 'ret', name: 'fcharlie'},
259
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', after: ['fbeta', 'fcharlie'], name: 'falpha'}
260
+ ]);
261
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
262
+ t.end();
263
+ });
264
+
265
+ test('when multiple fn:done ret', function (t) {
266
+ var locals = { falpha: falpha, fbeta: fbeta, fcharlie: fcharlie };
267
+ var r = pcode('a, b', [
268
+ 'd = fbeta(a, b)',
269
+ 'e = fcharlie(a, b)',
270
+ 'c = falpha(a, b) when fbeta:done and fcharlie:done',
271
+ 'cb(err, c, d);'
272
+ ], locals);
273
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
274
+ t.deepEqual(r.ast.tasks, [
275
+ { f: 'fbeta', a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'},
276
+ { f: 'fcharlie', a: ['a', 'b'], out: ['e'], type: 'ret', name: 'fcharlie'},
277
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'ret', after: ['fbeta', 'fcharlie'], name: 'falpha'}
278
+ ]);
279
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
280
+ t.end();
281
+ });
282
+
283
+ test('when mixed multiple fn:done', function (t) {
284
+ var locals = { falpha: falpha, fbeta: fbeta, fcharlie: fcharlie };
285
+ var r = pcode('a, b', [
286
+ 'd = fbeta(a, b)',
287
+ 'e = fcharlie(a, b) when fbeta;',
288
+ 'c = falpha(a, b) when fbeta and fcharlie;',
289
+ 'cb(err, c, d);'
290
+ ], locals);
291
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
292
+ t.deepEqual(r.ast.tasks, [
293
+ { f: 'fbeta', a: ['a', 'b'], out: ['d'], type: 'ret', name: 'fbeta'},
294
+ { f: 'fcharlie', a: ['a', 'b'], out: ['e'], type: 'ret', after: ['fbeta'], name: 'fcharlie'},
295
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'ret', after: ['fbeta', 'fcharlie'], name: 'falpha'}
296
+ ]);
297
+ t.deepEqual(r.ast.outTask, { a: ['c', 'd'], type: 'finalcb' });
298
+ t.end();
299
+ });
300
+
301
+
302
+ /* selectFirst */
303
+
304
+ test('selectFirst', function (t) {
305
+ var locals = { falpha: falpha, fbeta: fbeta, fcharlie: fcharlie };
306
+ var r = pcode.selectFirst('a, b', [
307
+ 'c := falpha(a, b)',
308
+ 'c = fbeta(a, b)',
309
+ 'cb(err, c)'
310
+ ], locals, { name: 'myflow', otherOptFoo: 'foo'});
311
+ t.deepEqual(r.ast.inParams, ['a', 'b']);
312
+ t.deepEqual(r.ast.tasks, [
313
+ { f: 'falpha', a: ['a', 'b'], out: ['c'], type: 'cb', name: 'falpha'},
314
+ { f: 'fbeta', a: ['a', 'b'], out: ['c'], type: 'ret', name: 'fbeta', after: ['falpha']}
315
+ ]);
316
+ t.deepEqual(r.ast.outTask, { type: 'finalcbFirst', a: ['c'] });
317
+ t.equal(r.ast.name, 'myflow', 'name should match if supplied');
318
+ t.equal(r.ast.otherOptFoo, 'foo', 'other options should pass through');
319
+ t.end();
320
+ });
321
+