concurrently 5.0.0 → 5.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.
- package/README.md +19 -18
- package/bin/concurrently.js +9 -1
- package/bin/epilogue.txt +0 -4
- package/index.js +3 -1
- package/package.json +11 -4
- package/src/completion-listener.js +26 -22
- package/src/concurrently.js +27 -9
- package/src/defaults.js +2 -0
- package/src/flow-control/kill-on-signal.js +1 -1
- package/src/get-spawn-opts.js +5 -4
- package/.editorconfig +0 -28
- package/.eslintrc.json +0 -23
- package/.travis.yml +0 -11
- package/.vscode/settings.json +0 -6
- package/CONTRIBUTING.md +0 -23
- package/appveyor.yml +0 -19
- package/bin/concurrently.spec.js +0 -365
- package/bin/fixtures/read-echo.js +0 -10
- package/docs/demo.gif +0 -0
- package/docs/frontend-demo.gif +0 -0
- package/docs/kill-demo.gif +0 -0
- package/docs/raw-demo.gif +0 -0
- package/src/command-parser/expand-npm-shortcut.spec.js +0 -36
- package/src/command-parser/expand-npm-wildcard.spec.js +0 -58
- package/src/command-parser/strip-quotes.spec.js +0 -20
- package/src/command.spec.js +0 -142
- package/src/completion-listener.spec.js +0 -88
- package/src/concurrently.spec.js +0 -77
- package/src/flow-control/input-handler.spec.js +0 -79
- package/src/flow-control/kill-on-signal.spec.js +0 -79
- package/src/flow-control/kill-others.spec.js +0 -66
- package/src/flow-control/log-error.spec.js +0 -40
- package/src/flow-control/log-exit.spec.js +0 -36
- package/src/flow-control/log-output.spec.js +0 -41
- package/src/flow-control/restart-process.spec.js +0 -129
- package/src/get-spawn-opts.spec.js +0 -18
- package/src/logger.spec.js +0 -178
package/bin/concurrently.spec.js
DELETED
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
const readline = require('readline');
|
|
2
|
-
const _ = require('lodash');
|
|
3
|
-
const Rx = require('rxjs');
|
|
4
|
-
const { buffer, map } = require('rxjs/operators');
|
|
5
|
-
const spawn = require('spawn-command');
|
|
6
|
-
|
|
7
|
-
const isWindows = process.platform === 'win32';
|
|
8
|
-
const createKillMessage = prefix => new RegExp(
|
|
9
|
-
_.escapeRegExp(prefix) +
|
|
10
|
-
' exited with code ' +
|
|
11
|
-
(isWindows ? 1 : '(SIGTERM|143)')
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
const run = args => {
|
|
15
|
-
const child = spawn('node ./concurrently.js ' + args, {
|
|
16
|
-
cwd: __dirname,
|
|
17
|
-
env: Object.assign({}, process.env, {
|
|
18
|
-
// When upgrading from jest 23 -> 24, colors started printing in the test output.
|
|
19
|
-
// They are forcibly disabled here
|
|
20
|
-
FORCE_COLOR: 0
|
|
21
|
-
}),
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
const stdout = readline.createInterface({
|
|
25
|
-
input: child.stdout,
|
|
26
|
-
output: null
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const stderr = readline.createInterface({
|
|
30
|
-
input: child.stderr,
|
|
31
|
-
output: null
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
const close = Rx.fromEvent(child, 'close');
|
|
35
|
-
const log = Rx.merge(
|
|
36
|
-
Rx.fromEvent(stdout, 'line'),
|
|
37
|
-
Rx.fromEvent(stderr, 'line')
|
|
38
|
-
).pipe(map(data => data.toString()));
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
close,
|
|
42
|
-
log,
|
|
43
|
-
stdin: child.stdin,
|
|
44
|
-
pid: child.pid
|
|
45
|
-
};
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
it('has help command', done => {
|
|
49
|
-
run('--help').close.subscribe(event => {
|
|
50
|
-
expect(event[0]).toBe(0);
|
|
51
|
-
done();
|
|
52
|
-
}, done);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('has version command', done => {
|
|
56
|
-
Rx.combineLatest(
|
|
57
|
-
run('--version').close,
|
|
58
|
-
run('-V').close,
|
|
59
|
-
run('-v').close
|
|
60
|
-
).subscribe(events => {
|
|
61
|
-
expect(events[0][0]).toBe(0);
|
|
62
|
-
expect(events[1][0]).toBe(0);
|
|
63
|
-
expect(events[2][0]).toBe(0);
|
|
64
|
-
done();
|
|
65
|
-
}, done);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
describe('exiting conditions', () => {
|
|
69
|
-
it('is of success by default when running successful commands', done => {
|
|
70
|
-
run('"echo foo" "echo bar"')
|
|
71
|
-
.close
|
|
72
|
-
.subscribe(exit => {
|
|
73
|
-
expect(exit[0]).toBe(0);
|
|
74
|
-
done();
|
|
75
|
-
}, done);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('is of failure by default when one of the command fails', done => {
|
|
79
|
-
run('"echo foo" "exit 1"')
|
|
80
|
-
.close
|
|
81
|
-
.subscribe(exit => {
|
|
82
|
-
expect(exit[0]).toBeGreaterThan(0);
|
|
83
|
-
done();
|
|
84
|
-
}, done);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('is of success when --success=first and first command to exit succeeds', done => {
|
|
88
|
-
run('--success=first "echo foo" "sleep 0.5 && exit 1"')
|
|
89
|
-
.close
|
|
90
|
-
.subscribe(exit => {
|
|
91
|
-
expect(exit[0]).toBe(0);
|
|
92
|
-
done();
|
|
93
|
-
}, done);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('is of failure when --success=first and first command to exit fails', done => {
|
|
97
|
-
run('--success=first "exit 1" "sleep 0.5 && echo foo"')
|
|
98
|
-
.close
|
|
99
|
-
.subscribe(exit => {
|
|
100
|
-
expect(exit[0]).toBeGreaterThan(0);
|
|
101
|
-
done();
|
|
102
|
-
}, done);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('is of success when --success=last and last command to exit succeeds', done => {
|
|
106
|
-
run('--success=last "exit 1" "sleep 0.5 && echo foo"')
|
|
107
|
-
.close
|
|
108
|
-
.subscribe(exit => {
|
|
109
|
-
expect(exit[0]).toBe(0);
|
|
110
|
-
done();
|
|
111
|
-
}, done);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('is of failure when --success=last and last command to exit fails', done => {
|
|
115
|
-
run('--success=last "echo foo" "sleep 0.5 && exit 1"')
|
|
116
|
-
.close
|
|
117
|
-
.subscribe(exit => {
|
|
118
|
-
expect(exit[0]).toBeGreaterThan(0);
|
|
119
|
-
done();
|
|
120
|
-
}, done);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it.skip('is of success when a SIGINT is sent', done => {
|
|
124
|
-
const child = run('"node fixtures/read-echo.js"');
|
|
125
|
-
child.close.subscribe(exit => {
|
|
126
|
-
// TODO This is null within Node, but should be 0 outside (eg from real terminal)
|
|
127
|
-
expect(exit[0]).toBe(0);
|
|
128
|
-
done();
|
|
129
|
-
}, done);
|
|
130
|
-
|
|
131
|
-
process.kill(child.pid, 'SIGINT');
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it('is aliased to -s', done => {
|
|
135
|
-
run('-s last "exit 1" "sleep 0.5 && echo foo"')
|
|
136
|
-
.close
|
|
137
|
-
.subscribe(exit => {
|
|
138
|
-
expect(exit[0]).toBe(0);
|
|
139
|
-
done();
|
|
140
|
-
}, done);
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
describe('--raw', () => {
|
|
145
|
-
it('is aliased to -r', done => {
|
|
146
|
-
const child = run('-r "echo foo" "echo bar"');
|
|
147
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
148
|
-
expect(lines).toHaveLength(2);
|
|
149
|
-
expect(lines).toContainEqual(expect.stringContaining('foo'));
|
|
150
|
-
expect(lines).toContainEqual(expect.stringContaining('bar'));
|
|
151
|
-
done();
|
|
152
|
-
}, done);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('does not log any extra output', done => {
|
|
156
|
-
const child = run('--raw "echo foo" "echo bar"');
|
|
157
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
158
|
-
expect(lines).toHaveLength(2);
|
|
159
|
-
expect(lines).toContainEqual(expect.stringContaining('foo'));
|
|
160
|
-
expect(lines).toContainEqual(expect.stringContaining('bar'));
|
|
161
|
-
done();
|
|
162
|
-
}, done);
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
describe('--names', () => {
|
|
167
|
-
it('is aliased to -n', done => {
|
|
168
|
-
const child = run('-n foo,bar "echo foo" "echo bar"');
|
|
169
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
170
|
-
expect(lines).toContainEqual(expect.stringContaining('[foo] foo'));
|
|
171
|
-
expect(lines).toContainEqual(expect.stringContaining('[bar] bar'));
|
|
172
|
-
done();
|
|
173
|
-
}, done);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('prefixes with names', done => {
|
|
177
|
-
const child = run('--names foo,bar "echo foo" "echo bar"');
|
|
178
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
179
|
-
expect(lines).toContainEqual(expect.stringContaining('[foo] foo'));
|
|
180
|
-
expect(lines).toContainEqual(expect.stringContaining('[bar] bar'));
|
|
181
|
-
done();
|
|
182
|
-
}, done);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it('is split using --name-separator arg', done => {
|
|
186
|
-
const child = run('--names "foo|bar" --name-separator "|" "echo foo" "echo bar"');
|
|
187
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
188
|
-
expect(lines).toContainEqual(expect.stringContaining('[foo] foo'));
|
|
189
|
-
expect(lines).toContainEqual(expect.stringContaining('[bar] bar'));
|
|
190
|
-
done();
|
|
191
|
-
}, done);
|
|
192
|
-
});
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
describe('--prefix', () => {
|
|
196
|
-
it('is alised to -p', done => {
|
|
197
|
-
const child = run('-p command "echo foo" "echo bar"');
|
|
198
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
199
|
-
expect(lines).toContainEqual(expect.stringContaining('[echo foo] foo'));
|
|
200
|
-
expect(lines).toContainEqual(expect.stringContaining('[echo bar] bar'));
|
|
201
|
-
done();
|
|
202
|
-
}, done);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it('specifies custom prefix', done => {
|
|
206
|
-
const child = run('--prefix command "echo foo" "echo bar"');
|
|
207
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
208
|
-
expect(lines).toContainEqual(expect.stringContaining('[echo foo] foo'));
|
|
209
|
-
expect(lines).toContainEqual(expect.stringContaining('[echo bar] bar'));
|
|
210
|
-
done();
|
|
211
|
-
}, done);
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
describe('--prefix-length', () => {
|
|
216
|
-
it('is alised to -l', done => {
|
|
217
|
-
const child = run('-p command -l 5 "echo foo" "echo bar"');
|
|
218
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
219
|
-
expect(lines).toContainEqual(expect.stringContaining('[ec..o] foo'));
|
|
220
|
-
expect(lines).toContainEqual(expect.stringContaining('[ec..r] bar'));
|
|
221
|
-
done();
|
|
222
|
-
}, done);
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it('specifies custom prefix length', done => {
|
|
226
|
-
const child = run('--prefix command --prefix-length 5 "echo foo" "echo bar"');
|
|
227
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
228
|
-
expect(lines).toContainEqual(expect.stringContaining('[ec..o] foo'));
|
|
229
|
-
expect(lines).toContainEqual(expect.stringContaining('[ec..r] bar'));
|
|
230
|
-
done();
|
|
231
|
-
}, done);
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
describe('--restart-tries', () => {
|
|
236
|
-
it('changes how many times a command will restart', done => {
|
|
237
|
-
const child = run('--restart-tries 1 "exit 1"');
|
|
238
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
239
|
-
expect(lines).toEqual([
|
|
240
|
-
expect.stringContaining('[0] exit 1 exited with code 1'),
|
|
241
|
-
expect.stringContaining('[0] exit 1 restarted'),
|
|
242
|
-
expect.stringContaining('[0] exit 1 exited with code 1'),
|
|
243
|
-
]);
|
|
244
|
-
done();
|
|
245
|
-
}, done);
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
describe('--kill-others', () => {
|
|
250
|
-
it('is alised to -k', done => {
|
|
251
|
-
const child = run('-k "sleep 10" "exit 0"');
|
|
252
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
253
|
-
expect(lines).toContainEqual(expect.stringContaining('[1] exit 0 exited with code 0'));
|
|
254
|
-
expect(lines).toContainEqual(expect.stringContaining('Sending SIGTERM to other processes'));
|
|
255
|
-
expect(lines).toContainEqual(expect.stringMatching(createKillMessage('[0] sleep 10')));
|
|
256
|
-
done();
|
|
257
|
-
}, done);
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
it('kills on success', done => {
|
|
261
|
-
const child = run('--kill-others "sleep 10" "exit 0"');
|
|
262
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
263
|
-
expect(lines).toContainEqual(expect.stringContaining('[1] exit 0 exited with code 0'));
|
|
264
|
-
expect(lines).toContainEqual(expect.stringContaining('Sending SIGTERM to other processes'));
|
|
265
|
-
expect(lines).toContainEqual(expect.stringMatching(createKillMessage('[0] sleep 10')));
|
|
266
|
-
done();
|
|
267
|
-
}, done);
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
it('kills on failure', done => {
|
|
271
|
-
const child = run('--kill-others "sleep 10" "exit 1"');
|
|
272
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
273
|
-
expect(lines).toContainEqual(expect.stringContaining('[1] exit 1 exited with code 1'));
|
|
274
|
-
expect(lines).toContainEqual(expect.stringContaining('Sending SIGTERM to other processes'));
|
|
275
|
-
expect(lines).toContainEqual(expect.stringMatching(createKillMessage('[0] sleep 10')));
|
|
276
|
-
done();
|
|
277
|
-
}, done);
|
|
278
|
-
});
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
describe('--kill-others-on-fail', () => {
|
|
282
|
-
it('does not kill on success', done => {
|
|
283
|
-
const child = run('--kill-others-on-fail "sleep 0.5" "exit 0"');
|
|
284
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
285
|
-
expect(lines).toContainEqual(expect.stringContaining('[1] exit 0 exited with code 0'));
|
|
286
|
-
expect(lines).toContainEqual(expect.stringContaining('[0] sleep 0.5 exited with code 0'));
|
|
287
|
-
done();
|
|
288
|
-
}, done);
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
it('kills on failure', done => {
|
|
292
|
-
const child = run('--kill-others-on-fail "sleep 10" "exit 1"');
|
|
293
|
-
child.log.pipe(buffer(child.close)).subscribe(lines => {
|
|
294
|
-
expect(lines).toContainEqual(expect.stringContaining('[1] exit 1 exited with code 1'));
|
|
295
|
-
expect(lines).toContainEqual(expect.stringContaining('Sending SIGTERM to other processes'));
|
|
296
|
-
expect(lines).toContainEqual(expect.stringMatching(createKillMessage('[0] sleep 10')));
|
|
297
|
-
done();
|
|
298
|
-
}, done);
|
|
299
|
-
});
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
describe('--handle-input', () => {
|
|
303
|
-
it('is alised to -i', done => {
|
|
304
|
-
const child = run('-i "node fixtures/read-echo.js"');
|
|
305
|
-
child.log.subscribe(line => {
|
|
306
|
-
if (/READING/.test(line)) {
|
|
307
|
-
child.stdin.write('stop\n');
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
if (/\[0\] stop/.test(line)) {
|
|
311
|
-
done();
|
|
312
|
-
}
|
|
313
|
-
}, done);
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
it('forwards input to first process by default', done => {
|
|
317
|
-
const child = run('--handle-input "node fixtures/read-echo.js"');
|
|
318
|
-
child.log.subscribe(line => {
|
|
319
|
-
if (/READING/.test(line)) {
|
|
320
|
-
child.stdin.write('stop\n');
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
if (/\[0\] stop/.test(line)) {
|
|
324
|
-
done();
|
|
325
|
-
}
|
|
326
|
-
}, done);
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
it('forwards input to process --default-input-target', done => {
|
|
331
|
-
const lines = [];
|
|
332
|
-
const child = run('-ki --default-input-target 1 "node fixtures/read-echo.js" "node fixtures/read-echo.js"');
|
|
333
|
-
child.log.subscribe(line => {
|
|
334
|
-
lines.push(line);
|
|
335
|
-
if (/\[1\] READING/.test(line)) {
|
|
336
|
-
child.stdin.write('stop\n');
|
|
337
|
-
}
|
|
338
|
-
}, done);
|
|
339
|
-
|
|
340
|
-
child.close.subscribe(exit => {
|
|
341
|
-
expect(exit[0]).toBeGreaterThan(0);
|
|
342
|
-
expect(lines).toContainEqual(expect.stringContaining('[1] stop'));
|
|
343
|
-
expect(lines).toContainEqual(expect.stringMatching(createKillMessage('[0] node fixtures/read-echo.js')));
|
|
344
|
-
done();
|
|
345
|
-
}, done);
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
it('forwards input to specified process', done => {
|
|
349
|
-
const lines = [];
|
|
350
|
-
const child = run('-ki "node fixtures/read-echo.js" "node fixtures/read-echo.js"');
|
|
351
|
-
child.log.subscribe(line => {
|
|
352
|
-
lines.push(line);
|
|
353
|
-
if (/\[1\] READING/.test(line)) {
|
|
354
|
-
child.stdin.write('1:stop\n');
|
|
355
|
-
}
|
|
356
|
-
}, done);
|
|
357
|
-
|
|
358
|
-
child.close.subscribe(exit => {
|
|
359
|
-
expect(exit[0]).toBeGreaterThan(0);
|
|
360
|
-
expect(lines).toContainEqual(expect.stringContaining('[1] stop'));
|
|
361
|
-
expect(lines).toContainEqual(expect.stringMatching(createKillMessage('[0] node fixtures/read-echo.js')));
|
|
362
|
-
done();
|
|
363
|
-
}, done);
|
|
364
|
-
});
|
|
365
|
-
});
|
package/docs/demo.gif
DELETED
|
Binary file
|
package/docs/frontend-demo.gif
DELETED
|
Binary file
|
package/docs/kill-demo.gif
DELETED
|
Binary file
|
package/docs/raw-demo.gif
DELETED
|
Binary file
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
const ExpandNpmShortcut = require('./expand-npm-shortcut');
|
|
2
|
-
const parser = new ExpandNpmShortcut();
|
|
3
|
-
|
|
4
|
-
it('returns same command if no npm: prefix is present', () => {
|
|
5
|
-
const commandInfo = {
|
|
6
|
-
name: 'echo',
|
|
7
|
-
command: 'echo foo'
|
|
8
|
-
};
|
|
9
|
-
expect(parser.parse(commandInfo)).toBe(commandInfo);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
for (const npmCmd of ['npm', 'yarn']) {
|
|
13
|
-
describe(`with ${npmCmd}: prefix`, () => {
|
|
14
|
-
it(`expands to "${npmCmd} run <script> <args>"`, () => {
|
|
15
|
-
const commandInfo = {
|
|
16
|
-
name: 'echo',
|
|
17
|
-
command: `${npmCmd}:foo -- bar`
|
|
18
|
-
};
|
|
19
|
-
expect(parser.parse(commandInfo)).toEqual({
|
|
20
|
-
name: 'echo',
|
|
21
|
-
command: `${npmCmd} run foo -- bar`
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('sets name to script name if none', () => {
|
|
26
|
-
const commandInfo = {
|
|
27
|
-
command: `${npmCmd}:foo -- bar`
|
|
28
|
-
};
|
|
29
|
-
expect(parser.parse(commandInfo)).toEqual({
|
|
30
|
-
name: 'foo',
|
|
31
|
-
command: `${npmCmd} run foo -- bar`
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
const ExpandNpmWildcard = require('./expand-npm-wildcard');
|
|
2
|
-
|
|
3
|
-
let parser, readPkg;
|
|
4
|
-
|
|
5
|
-
beforeEach(() => {
|
|
6
|
-
readPkg = jest.fn();
|
|
7
|
-
parser = new ExpandNpmWildcard(readPkg);
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it('returns same command if not an npm run command', () => {
|
|
11
|
-
const commandInfo = {
|
|
12
|
-
command: 'npm test'
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
expect(readPkg).not.toHaveBeenCalled();
|
|
16
|
-
expect(parser.parse(commandInfo)).toBe(commandInfo);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('returns same command if no wildcard present', () => {
|
|
20
|
-
const commandInfo = {
|
|
21
|
-
command: 'npm run foo bar'
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
expect(readPkg).not.toHaveBeenCalled();
|
|
25
|
-
expect(parser.parse(commandInfo)).toBe(commandInfo);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('expands to nothing if no scripts exist in package.json', () => {
|
|
29
|
-
readPkg.mockReturnValue({});
|
|
30
|
-
|
|
31
|
-
expect(parser.parse({ command: 'npm run foo-*-baz qux' })).toEqual([]);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
for (const npmCmd of ['npm', 'yarn']) {
|
|
35
|
-
describe(`with an ${npmCmd}: prefix`, () => {
|
|
36
|
-
it('expands to all scripts matching pattern', () => {
|
|
37
|
-
readPkg.mockReturnValue({
|
|
38
|
-
scripts: {
|
|
39
|
-
'foo-bar-baz': '',
|
|
40
|
-
'foo--baz': '',
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
expect(parser.parse({ command: `${npmCmd} run foo-*-baz qux` })).toEqual([
|
|
45
|
-
{ name: 'foo-bar-baz', command: `${npmCmd} run foo-bar-baz qux` },
|
|
46
|
-
{ name: 'foo--baz', command: `${npmCmd} run foo--baz qux` },
|
|
47
|
-
]);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('caches scripts upon calls', () => {
|
|
51
|
-
readPkg.mockReturnValue({});
|
|
52
|
-
parser.parse({ command: `${npmCmd} run foo-*-baz qux` });
|
|
53
|
-
parser.parse({ command: `${npmCmd} run foo-*-baz qux` });
|
|
54
|
-
|
|
55
|
-
expect(readPkg).toHaveBeenCalledTimes(1);
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
const StripQuotes = require('./strip-quotes');
|
|
2
|
-
const parser = new StripQuotes();
|
|
3
|
-
|
|
4
|
-
it('returns command as is if no single/double quote at the beginning', () => {
|
|
5
|
-
expect(parser.parse({ command: 'echo foo' })).toEqual({ command: 'echo foo' });
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
it('strips single quotes', () => {
|
|
9
|
-
expect(parser.parse({ command: '\'echo foo\'' })).toEqual({ command: 'echo foo' });
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('strips double quotes', () => {
|
|
13
|
-
expect(parser.parse({ command: '"echo foo"' })).toEqual({ command: 'echo foo' });
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('does not remove quotes if they are impaired', () => {
|
|
17
|
-
expect(parser.parse({ command: '"echo foo' })).toEqual({ command: '"echo foo' });
|
|
18
|
-
expect(parser.parse({ command: 'echo foo\'' })).toEqual({ command: 'echo foo\'' });
|
|
19
|
-
expect(parser.parse({ command: '"echo foo\'' })).toEqual({ command: '"echo foo\'' });
|
|
20
|
-
});
|
package/src/command.spec.js
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
const EventEmitter = require('events');
|
|
2
|
-
const Command = require('./command');
|
|
3
|
-
|
|
4
|
-
const createProcess = () => {
|
|
5
|
-
const process = new EventEmitter();
|
|
6
|
-
process.pid = 1;
|
|
7
|
-
return process;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const createProcessWithIO = () => {
|
|
11
|
-
const process = createProcess();
|
|
12
|
-
return Object.assign(process, {
|
|
13
|
-
stdout: new EventEmitter(),
|
|
14
|
-
stderr: new EventEmitter(),
|
|
15
|
-
stdin: new EventEmitter()
|
|
16
|
-
});
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
describe('#start()', () => {
|
|
20
|
-
it('spawns process with given command and options', () => {
|
|
21
|
-
const spawn = jest.fn().mockReturnValue(createProcess());
|
|
22
|
-
const command = new Command({
|
|
23
|
-
spawn,
|
|
24
|
-
spawnOpts: { bla: true },
|
|
25
|
-
command: 'echo foo',
|
|
26
|
-
});
|
|
27
|
-
command.start();
|
|
28
|
-
|
|
29
|
-
expect(spawn).toHaveBeenCalledTimes(1);
|
|
30
|
-
expect(spawn).toHaveBeenCalledWith(command.command, { bla: true });
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('sets stdin, process and PID', () => {
|
|
34
|
-
const process = createProcessWithIO();
|
|
35
|
-
const command = new Command({ spawn: () => process });
|
|
36
|
-
|
|
37
|
-
command.start();
|
|
38
|
-
expect(command.process).toBe(process);
|
|
39
|
-
expect(command.pid).toBe(process.pid);
|
|
40
|
-
expect(command.stdin).toBe(process.stdin);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('shares errors to the error stream', done => {
|
|
44
|
-
const process = createProcess();
|
|
45
|
-
const command = new Command({ spawn: () => process });
|
|
46
|
-
|
|
47
|
-
command.error.subscribe(data => {
|
|
48
|
-
expect(data).toBe('foo');
|
|
49
|
-
expect(command.process).toBeUndefined();
|
|
50
|
-
done();
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
command.start();
|
|
54
|
-
process.emit('error', 'foo');
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('shares closes to the close stream with exit code', done => {
|
|
58
|
-
const process = createProcess();
|
|
59
|
-
const command = new Command({ spawn: () => process });
|
|
60
|
-
|
|
61
|
-
command.close.subscribe(data => {
|
|
62
|
-
expect(data).toBe(0);
|
|
63
|
-
expect(command.process).toBeUndefined();
|
|
64
|
-
done();
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
command.start();
|
|
68
|
-
process.emit('close', 0, null);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('shares closes to the close stream with signal', done => {
|
|
72
|
-
const process = createProcess();
|
|
73
|
-
const command = new Command({ spawn: () => process });
|
|
74
|
-
|
|
75
|
-
command.close.subscribe(data => {
|
|
76
|
-
expect(data).toBe('SIGKILL');
|
|
77
|
-
done();
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
command.start();
|
|
81
|
-
process.emit('close', null, 'SIGKILL');
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('shares stdout to the stdout stream', done => {
|
|
85
|
-
const process = createProcessWithIO();
|
|
86
|
-
const command = new Command({ spawn: () => process });
|
|
87
|
-
|
|
88
|
-
command.stdout.subscribe(data => {
|
|
89
|
-
expect(data.toString()).toBe('hello');
|
|
90
|
-
done();
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
command.start();
|
|
94
|
-
process.stdout.emit('data', Buffer.from('hello'));
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('shares stderr to the stdout stream', done => {
|
|
98
|
-
const process = createProcessWithIO();
|
|
99
|
-
const command = new Command({ spawn: () => process });
|
|
100
|
-
|
|
101
|
-
command.stderr.subscribe(data => {
|
|
102
|
-
expect(data.toString()).toBe('dang');
|
|
103
|
-
done();
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
command.start();
|
|
107
|
-
process.stderr.emit('data', Buffer.from('dang'));
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
describe('#kill()', () => {
|
|
112
|
-
let process, killProcess, command;
|
|
113
|
-
beforeEach(() => {
|
|
114
|
-
process = createProcess();
|
|
115
|
-
killProcess = jest.fn();
|
|
116
|
-
command = new Command({ spawn: () => process, killProcess });
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('kills process', () => {
|
|
120
|
-
command.start();
|
|
121
|
-
command.kill();
|
|
122
|
-
|
|
123
|
-
expect(killProcess).toHaveBeenCalledTimes(1);
|
|
124
|
-
expect(killProcess).toHaveBeenCalledWith(command.pid, undefined);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('kills process with some signal', () => {
|
|
128
|
-
command.start();
|
|
129
|
-
command.kill('SIGKILL');
|
|
130
|
-
|
|
131
|
-
expect(killProcess).toHaveBeenCalledTimes(1);
|
|
132
|
-
expect(killProcess).toHaveBeenCalledWith(command.pid, 'SIGKILL');
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('does not try to kill inexistent process', () => {
|
|
136
|
-
command.start();
|
|
137
|
-
process.emit('error');
|
|
138
|
-
command.kill();
|
|
139
|
-
|
|
140
|
-
expect(killProcess).not.toHaveBeenCalled();
|
|
141
|
-
});
|
|
142
|
-
});
|