concurrently 3.4.0 → 3.6.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.
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+
3
+ const assert = require('assert');
4
+
5
+ const findChild = require('../src/findChild');
6
+
7
+ describe('findChild', () => {
8
+
9
+ const aChild = { pid: '111' };
10
+ const bChild = { pid: '222' };
11
+
12
+ const children = [ aChild, bChild ];
13
+
14
+ const childrenInfo = {
15
+ 111: {
16
+ index: 0,
17
+ name: 'a child'
18
+ },
19
+ 222: {
20
+ index: 1,
21
+ name: 'b child'
22
+ }
23
+ };
24
+
25
+ it('finds child by index', () => {
26
+ const child = findChild('1', children, childrenInfo);
27
+ assert.strictEqual(child, bChild);
28
+ });
29
+
30
+ it('finds child by name', () => {
31
+ const child = findChild('a child', children, childrenInfo);
32
+ assert.strictEqual(child, aChild);
33
+ });
34
+
35
+ it('returns undefined when no matching child found', () => {
36
+ const child = findChild('no child', children, childrenInfo);
37
+ assert.strictEqual(child, undefined);
38
+ });
39
+ });
@@ -1,23 +1,24 @@
1
+ 'use strict';
1
2
  // Test basic usage of cli
2
3
 
3
- var path = require('path');
4
- var assert = require('assert');
5
- var run = require('./utils').run;
6
- var IS_WINDOWS = /^win/.test(process.platform);
4
+ const path = require('path');
5
+ const assert = require('assert');
6
+ const run = require('./utils').run;
7
+ const IS_WINDOWS = /^win/.test(process.platform);
7
8
 
8
- // If true, output of commands are shown
9
- var DEBUG_TESTS = process.env.DEBUG_TESTS === 'true';
10
- var TEST_DIR = 'dir/';
9
+ // Note: Set the DEBUG_TESTS environment variable to `true` to see output of test commands.
10
+
11
+ const TEST_DIR = 'dir/';
11
12
 
12
13
  // Abs path to test directory
13
- var testDir = path.resolve(__dirname);
14
+ const testDir = path.resolve(__dirname);
14
15
  process.chdir(path.join(testDir, '..'));
15
16
 
16
17
  describe('concurrently', function() {
17
18
  this.timeout(5000);
18
19
 
19
20
  it('help should be successful', () => {
20
- return run('node ./src/main.js --help', {pipe: DEBUG_TESTS})
21
+ return run('node ./src/main.js --help')
21
22
  .then(function(exitCode) {
22
23
  // exit code 0 means success
23
24
  assert.strictEqual(exitCode, 0);
@@ -25,70 +26,58 @@ describe('concurrently', function() {
25
26
  });
26
27
 
27
28
  it('version should be successful', () => {
28
- return run('node ./src/main.js -V', {pipe: DEBUG_TESTS})
29
+ return run('node ./src/main.js -V')
29
30
  .then(function(exitCode) {
30
31
  assert.strictEqual(exitCode, 0);
31
32
  });
32
33
  });
33
34
 
34
35
  it('two successful commands should exit 0', () => {
35
- return run('node ./src/main.js "echo test" "echo test"', {pipe: DEBUG_TESTS})
36
+ return run('node ./src/main.js "echo test" "echo test"')
36
37
  .then(function(exitCode) {
37
38
  assert.strictEqual(exitCode, 0);
38
39
  });
39
40
  });
40
41
 
41
42
  it('at least one unsuccessful commands should exit non-zero', () => {
42
- return run('node ./src/main.js "echo test" "nosuchcmd" "echo test"', {pipe: DEBUG_TESTS})
43
+ return run('node ./src/main.js "echo test" "nosuchcmd" "echo test"')
43
44
  .then(function(exitCode) {
44
45
  assert.notStrictEqual(exitCode, 0);
45
46
  });
46
47
  });
47
48
 
48
49
  it('--kill-others should kill other commands if one dies', () => {
49
- return run('node ./src/main.js --kill-others "sleep 1" "echo test" "sleep 0.1 && nosuchcmd"', {pipe: DEBUG_TESTS})
50
+ return run('node ./src/main.js --kill-others "sleep 1" "echo test" "sleep 0.1 && nosuchcmd"')
50
51
  .then(function(exitCode) {
51
52
  assert.notStrictEqual(exitCode, 0);
52
53
  });
53
54
  });
54
55
 
55
56
  it('--kill-others-on-fail should kill other commands if one exits with non-zero status code', () => {
56
- return run('node ./src/main.js --kill-others-on-fail "sleep 1" "exit 1" "sleep 1"', {pipe: DEBUG_TESTS})
57
+ return run('node ./src/main.js --kill-others-on-fail "sleep 1" "exit 1" "sleep 1"')
57
58
  .then(function(exitCode) {
58
59
  assert.notStrictEqual(exitCode, 0);
59
60
  });
60
61
  });
61
62
 
62
63
  it('--kill-others-on-fail should NOT kill other commands if none of them exits with non-zero status code', (done) => {
63
- var readline = require('readline');
64
- var exits = 0;
65
- var sigtermInOutput = false;
64
+ const readline = require('readline');
65
+ let exits = 0;
66
+ let sigtermInOutput = false;
66
67
 
67
68
  run('node ./src/main.js --kill-others-on-fail "echo killTest1" "echo killTest2" "echo killTest3"', {
68
- pipe: false,
69
- callback: function(child) {
70
- var rl = readline.createInterface({
71
- input: child.stdout,
72
- output: null
73
- });
74
-
75
- rl.on('line', function(line) {
76
- if (DEBUG_TESTS) {
77
- console.log(line);
78
- }
69
+ onOutputLine: function(line) {
70
+ if (/SIGTERM/.test(line)) {
71
+ sigtermInOutput = true;
72
+ }
79
73
 
80
- if (/SIGTERM/.test(line)) {
81
- sigtermInOutput = true;
82
- }
83
-
84
- // waiting for exits
85
- if (/killTest\d$/.test(line)) {
86
- exits++;
87
- }
88
- });
74
+ // waiting for exits
75
+ if (/killTest\d$/.test(line)) {
76
+ exits++;
77
+ }
89
78
  }
90
79
  }).then(function() {
91
- if(sigtermInOutput) {
80
+ if (sigtermInOutput) {
92
81
  done(new Error('There was a "SIGTERM" in console output'));
93
82
  } else if (exits !== 3) {
94
83
  done(new Error('There was wrong number of echoes(' + exits + ') from executed commands'));
@@ -99,7 +88,7 @@ describe('concurrently', function() {
99
88
  });
100
89
 
101
90
  it('--success=first should return first exit code', () => {
102
- return run('node ./src/main.js -k --success first "echo test" "sleep 0.1 && nosuchcmd"', {pipe: DEBUG_TESTS})
91
+ return run('node ./src/main.js -k --success first "echo test" "sleep 0.1 && nosuchcmd"')
103
92
  // When killed, sleep returns null exit code
104
93
  .then(function(exitCode) {
105
94
  assert.strictEqual(exitCode, 0);
@@ -108,78 +97,330 @@ describe('concurrently', function() {
108
97
 
109
98
  it('--success=last should return last exit code', () => {
110
99
  // When killed, sleep returns null exit code
111
- return run('node ./src/main.js -k --success last "echo test" "sleep 0.1 && nosuchcmd"', {pipe: DEBUG_TESTS})
100
+ return run('node ./src/main.js -k --success last "echo test" "sleep 0.1 && nosuchcmd"')
112
101
  .then(function(exitCode) {
113
102
  assert.notStrictEqual(exitCode, 0);
114
103
  });
115
104
  });
116
105
 
117
106
  it('&& nosuchcmd should return non-zero exit code', () => {
118
- return run('node ./src/main.js "echo 1 && nosuchcmd" "echo 1 && nosuchcmd" ', {pipe: DEBUG_TESTS})
107
+ return run('node ./src/main.js "echo 1 && nosuchcmd" "echo 1 && nosuchcmd" ')
119
108
  .then(function(exitCode) {
120
109
  assert.strictEqual(exitCode, 1);
121
110
  });
122
111
  });
123
112
 
124
113
  it('--prefix-colors should handle non-existent colors without failing', () => {
125
- return run('node ./src/main.js -c "not.a.color" "echo colors"', {pipe: DEBUG_TESTS})
114
+ return run('node ./src/main.js -c "not.a.color" "echo colors"')
126
115
  .then(function(exitCode) {
127
116
  assert.strictEqual(exitCode, 0);
128
117
  });
129
118
  });
130
119
 
131
- ['SIGINT', 'SIGTERM'].forEach((signal) => {
132
- if (IS_WINDOWS) {
133
- console.log('IS_WINDOWS=true');
134
- console.log('Skipping SIGINT/SIGTERM propagation tests ..');
135
- return;
136
- }
137
-
138
- it('killing it with ' + signal + ' should propagate the signal to the children', function(done) {
139
- var readline = require('readline');
140
- var waitingStart = 2;
141
- var waitingSignal = 2;
142
-
143
- function waitForSignal(cb) {
144
- if (waitingSignal) {
145
- setTimeout(waitForSignal, 100);
146
- } else {
147
- cb();
148
- }
149
- }
120
+ it('--prefix can contain PID', () => {
121
+ const collectedLines = [];
122
+ return run('node ./src/main.js --prefix pid "echo one" "echo two"', {
123
+ onOutputLine(line) {
124
+ collectedLines.push(line);
125
+ }
126
+ }).then(() => {
127
+ assert.ok(collectedLines.every(line => /^\[\d+\] /.test(line)));
128
+ });
129
+ });
150
130
 
151
- run('node ./src/main.js "node ./test/support/signal.js" "node ./test/support/signal.js"', {
152
- pipe: false,
153
- callback: function(child) {
154
- var rl = readline.createInterface({
155
- input: child.stdout,
156
- output: null
131
+ it('--prefix can contain command itself', () => {
132
+ const collectedLines = [];
133
+ return run('node ./src/main.js --prefix "[{command}]" "echo one" "echo two"', {
134
+ onOutputLine(line) {
135
+ collectedLines.push(line);
136
+ }
137
+ }).then(() => {
138
+ assert.ok(collectedLines.every(line => /^\[echo (one|two)\] /.test(line)));
139
+ });
140
+ });
141
+
142
+ it('--prefix can contain time', () => {
143
+ const collectedLines = [];
144
+ return run('node ./src/main.js --prefix time "echo one" "echo two"', {
145
+ onOutputLine(line) {
146
+ collectedLines.push(line);
147
+ }
148
+ }).then(() => {
149
+ assert.ok(collectedLines.every(line => /^\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}\] /.test(line)));
150
+ });
151
+ });
152
+
153
+ it('--prefix should default to "index"', () => {
154
+ const collectedLines = [];
155
+
156
+ return run('node ./src/main.js "echo one" "echo two"', {
157
+ onOutputLine: (line) => {
158
+ if (/(one|two)$/.exec(line)) {
159
+ collectedLines.push(line);
160
+ }
161
+ }
162
+ })
163
+ .then(function(exitCode) {
164
+ assert.strictEqual(exitCode, 0);
165
+
166
+ collectedLines.sort();
167
+ assert.deepEqual(collectedLines, [
168
+ '[0] one',
169
+ '[1] two'
170
+ ]);
157
171
  });
172
+ });
158
173
 
159
- rl.on('line', function(line) {
160
- if (DEBUG_TESTS) {
161
- console.log(line);
162
- }
163
-
164
- // waiting for startup
165
- if (/STARTED/.test(line)) {
166
- waitingStart--;
167
- }
168
- if (!waitingStart) {
169
- // both processes are started
170
- child.kill(signal);
171
- }
172
-
173
- // waiting for signal
174
- if (new RegExp(signal).test(line)) {
175
- waitingSignal--;
176
- }
174
+ it('--names should set a different default prefix', () => {
175
+ const collectedLines = [];
176
+
177
+ return run('node ./src/main.js -n aa,bb "echo one" "echo two"', {
178
+ onOutputLine: (line) => {
179
+ if (/(one|two)$/.exec(line)) {
180
+ collectedLines.push(line);
181
+ }
182
+ }
183
+ })
184
+ .then(function(exitCode) {
185
+ assert.strictEqual(exitCode, 0);
186
+
187
+ collectedLines.sort();
188
+ assert.deepEqual(collectedLines, [
189
+ '[aa] one',
190
+ '[bb] two'
191
+ ]);
177
192
  });
178
- }
193
+ });
194
+
195
+ it('--allow-restart should restart a proccess with non-zero exit code', (done) => {
196
+ const readline = require('readline');
197
+ let exitedWithOne = false;
198
+ let restarted = false;
199
+
200
+ run('node ./src/main.js --allow-restart "sleep 0.1 && exit 1" "sleep 1"', {
201
+ pipe: false,
202
+ onOutputLine: (line) => {
203
+ const re = /exited with code (.+)/.exec(line);
204
+ if (re && re[1] === '1') {
205
+ exitedWithOne = true;
206
+ }
207
+
208
+ if (/restarted/.test(line)) {
209
+ restarted = true;
210
+ }
211
+ }
212
+ }).then(function() {
213
+ if (exitedWithOne && restarted) {
214
+ done();
215
+ } else {
216
+ done(new Error('No restarted process exited with code 1'));
217
+ }
218
+ });
219
+ });
220
+
221
+ it('--restart-after=n should restart a proccess after n miliseconds', (done) => {
222
+ const readline = require('readline');
223
+ let start, end;
224
+
225
+ run('node ./src/main.js --allow-restart --restart-after 300 "exit 1" "sleep 1"', {
226
+ pipe: false,
227
+ onOutputLine: (line) => {
228
+ if (!start && /exited with code (.+)/.test(line)) {
229
+ start = new Date().getTime();
230
+ }
231
+
232
+ if (!end && /restarted/.test(line)) {
233
+ end = new Date().getTime();
234
+ }
235
+ }
236
+ }).then(function() {
237
+ // we accept 100 miliseconds of error
238
+ if (end - start >= 300 && end - start < 400) {
239
+ done();
240
+ } else {
241
+ done(new Error('No restarted process after 300 miliseconds'));
242
+ }
243
+ });
244
+ });
245
+ it('--restart-tries=n should restart a proccess at most n times', (done) => {
246
+ const readline = require('readline');
247
+ let restartedTimes = 0;
248
+
249
+ run('node ./src/main.js --allow-restart --restart-tries 2 "exit 1" "sleep 1"', {
250
+ pipe: false,
251
+ onOutputLine: (line) => {
252
+ if (/restarted/.test(line)) {
253
+ restartedTimes++;
254
+ }
255
+ }
179
256
  }).then(function() {
180
- waitForSignal(done);
257
+ if (restartedTimes === 2) {
258
+ done();
259
+ } else {
260
+ done(new Error('No restarted process twice'));
261
+ }
181
262
  });
182
- });
263
+ });
264
+
265
+ ['SIGINT', 'SIGTERM'].forEach((signal) => {
266
+ if (IS_WINDOWS) {
267
+ console.log('IS_WINDOWS=true');
268
+ console.log('Skipping SIGINT/SIGTERM propagation tests ..');
269
+ return;
270
+ }
271
+
272
+ it('killing it with ' + signal + ' should propagate the signal to the children', function(done) {
273
+ const readline = require('readline');
274
+ let waitingStart = 2;
275
+ let waitingSignal = 2;
276
+
277
+ function waitForSignal(cb) {
278
+ if (waitingSignal) {
279
+ setTimeout(waitForSignal, 100);
280
+ } else {
281
+ cb();
282
+ }
283
+ }
284
+
285
+ run('node ./src/main.js "node ./test/support/signal.js" "node ./test/support/signal.js"', {
286
+ onOutputLine: function(line, child) {
287
+ // waiting for startup
288
+ if (/STARTED/.test(line)) {
289
+ waitingStart--;
290
+ }
291
+ if (!waitingStart) {
292
+ // both processes are started
293
+ child.kill(signal);
294
+ }
295
+
296
+ // waiting for signal
297
+ if (new RegExp(signal).test(line)) {
298
+ waitingSignal--;
299
+ }
300
+ }
301
+ }).then(function() {
302
+ waitForSignal(done);
303
+ });
304
+ });
305
+ });
306
+
307
+ it('sends input to default stdin target process', (done) => {
308
+ let echoed = false;
309
+ run('node ./src/main.js "node ./test/support/read-echo.js"', {
310
+ onOutputLine: (line, child) => {
311
+ if (/READING/.test(line)) {
312
+ child.stdin.write('stop\n');
313
+ }
314
+
315
+ if (/\[\d+\] stop/.test(line)) {
316
+ echoed = true;
317
+ }
318
+ }
319
+ })
320
+ .then(() => {
321
+ assert(echoed);
322
+ })
323
+ .then(done, done);
324
+ });
325
+
326
+ it('sends input to specified default stdin target process', (done) => {
327
+ let echoed = false;
328
+ run('node ./src/main.js --default-input-target 1 "echo test" "node ./test/support/read-echo.js"', {
329
+ onOutputLine: (line, child) => {
330
+ if (/READING/.test(line)) {
331
+ child.stdin.write('stop\n');
332
+ }
333
+
334
+ if (/\[1\] stop/.test(line)) {
335
+ echoed = true;
336
+ }
337
+ }
338
+ })
339
+ .then(() => {
340
+ assert(echoed);
341
+ })
342
+ .then(done, done);
343
+ });
344
+
345
+ it('sends input to child specified by index', (done) => {
346
+ let echoed = false;
347
+ run('node ./src/main.js "echo test" "node ./test/support/read-echo.js"', {
348
+ onOutputLine: (line, child) => {
349
+ if (/READING/.test(line)) {
350
+ child.stdin.write('1:stop\n');
351
+ }
352
+
353
+ if (/\[1\] stop/.test(line)) {
354
+ echoed = true;
355
+ }
356
+ }
357
+ })
358
+ .then(() => {
359
+ assert(echoed);
360
+ })
361
+ .then(done, done);
362
+ });
363
+
364
+ it('emits error when specified read stream is not found', (done) => {
365
+ let errorEmitted = false;
366
+ run('node ./src/main.js "echo test" "node ./test/support/read-echo.js"', {
367
+ onOutputLine: (line, child) => {
368
+ if (/READING/.test(line)) {
369
+ child.stdin.write('2:stop\n');
370
+ }
371
+
372
+ if ('Unable to find command [2]' === line.trim()) {
373
+ errorEmitted = true;
374
+
375
+ // Stop read process to continue the test
376
+ child.stdin.write('1:stop\n');
377
+ }
378
+ }
379
+ })
380
+ .then(() => {
381
+ assert(errorEmitted);
382
+ })
383
+ .then(done, done);
384
+ });
385
+
386
+ it('should expand npm: command shortcuts', (done) => {
387
+ let echo1 = false;
388
+ let echo2 = false;
389
+ run('node ./src/main.js "npm:echo-test" "npm:echo -- testarg"', {
390
+ onOutputLine: function(line, child) {
391
+ if (line === '[echo-test] test') {
392
+ echo1 = true;
393
+ } else if (line === '[echo] testarg') {
394
+ echo2 = true;
395
+ }
396
+ }
397
+ })
398
+ .then((exitCode) => {
399
+ assert.strictEqual(exitCode, 0);
400
+ assert.ok(echo1);
401
+ assert.ok(echo2);
402
+ })
403
+ .then(done, done);
404
+ });
405
+
406
+ it('expands npm run shortcut wildcards', (done) => {
407
+ let echoBeep = false;
408
+ let echoBoop = false;
409
+ run('node ./src/main.js "npm:echo-sound-*"', {
410
+ onOutputLine: (line, child) => {
411
+ if (line === '[beep] beep') {
412
+ echoBeep = true;
413
+ } else if (line === '[boop] boop') {
414
+ echoBoop = true;
415
+ }
416
+ }
417
+ })
418
+ .then((exitCode) => {
419
+ assert.strictEqual(exitCode, 0);
420
+ assert.ok(echoBeep);
421
+ assert.ok(echoBoop);
422
+ })
423
+ .then(done, done);
183
424
  });
184
425
  });
185
426