concurrently 4.0.0 → 4.1.2
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/.travis.yml +3 -0
- package/.vscode/settings.json +2 -1
- package/CONTRIBUTING.md +1 -4
- package/README.md +11 -8
- package/bin/concurrently.js +2 -1
- package/bin/concurrently.spec.js +36 -11
- package/package.json +11 -9
- package/src/command-parser/expand-npm-shortcut.js +2 -2
- package/src/command-parser/expand-npm-shortcut.spec.js +21 -18
- package/src/command-parser/expand-npm-wildcard.js +2 -2
- package/src/command-parser/expand-npm-wildcard.spec.js +24 -20
- package/src/command-parser/strip-quotes.js +1 -1
- package/src/command-parser/strip-quotes.spec.js +6 -0
- package/src/completion-listener.js +4 -2
- package/src/completion-listener.spec.js +12 -12
- package/src/flow-control/kill-on-signal.spec.js +22 -0
- package/src/flow-control/restart-process.spec.js +10 -0
package/.travis.yml
CHANGED
package/.vscode/settings.json
CHANGED
package/CONTRIBUTING.md
CHANGED
|
@@ -6,7 +6,6 @@ updated.
|
|
|
6
6
|
|
|
7
7
|
**Pull requests:** You don't need to bump version numbers or modify anything related to releasing. That stuff is fully automated, just write the functionality.
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
# Maintaining
|
|
11
10
|
|
|
12
11
|
## Test
|
|
@@ -14,11 +13,9 @@ updated.
|
|
|
14
13
|
Tests can be run with command:
|
|
15
14
|
|
|
16
15
|
```bash
|
|
17
|
-
|
|
16
|
+
npm run test
|
|
18
17
|
```
|
|
19
18
|
|
|
20
|
-
You need to have *mocha* installed globally with `npm install -g mocha`.
|
|
21
|
-
|
|
22
19
|
## Release
|
|
23
20
|
|
|
24
21
|
* Commit all changes
|
package/README.md
CHANGED
|
@@ -225,25 +225,25 @@ For more details, visit https://github.com/kimmobrunfeldt/concurrently
|
|
|
225
225
|
concurrently can be used programmatically by using the API documented below:
|
|
226
226
|
|
|
227
227
|
### `concurrently(commands[, options])`
|
|
228
|
-
- `commands`: an array of either strings (containing the commands to run) or objects
|
|
228
|
+
- `commands`: an array of either strings (containing the commands to run) or objects
|
|
229
229
|
with the shape `{ command, name, prefixColor }`.
|
|
230
230
|
- `options` (optional): an object containing any of the below:
|
|
231
|
-
- `defaultInputTarget`: the default input target when reading from `inputStream`.
|
|
231
|
+
- `defaultInputTarget`: the default input target when reading from `inputStream`.
|
|
232
232
|
Default: `0`.
|
|
233
|
-
- `inputStream`: a [`Readable` stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html#stream_readable_streams)
|
|
233
|
+
- `inputStream`: a [`Readable` stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html#stream_readable_streams)
|
|
234
234
|
to read the input from, eg `process.stdin`.
|
|
235
|
-
- `killOthers`: an array of exitting conditions that will cause a process to kill others.
|
|
235
|
+
- `killOthers`: an array of exitting conditions that will cause a process to kill others.
|
|
236
236
|
Can contain any of `success` or `failure`.
|
|
237
237
|
- `outputStream`: a [`Writable` stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html#stream_writable_streams)
|
|
238
238
|
to write logs to. Default: `process.stdout`.
|
|
239
|
-
- `prefix`: the prefix type to use when logging processes output.
|
|
240
|
-
Possible values: `index`, `pid`, `time`, `command`, `name`, `none`, or a template (eg `[{time} process: {pid}]`).
|
|
239
|
+
- `prefix`: the prefix type to use when logging processes output.
|
|
240
|
+
Possible values: `index`, `pid`, `time`, `command`, `name`, `none`, or a template (eg `[{time} process: {pid}]`).
|
|
241
241
|
Default: the name of the process, or its index if no name is set.
|
|
242
242
|
- `prefixLength`: how many characters to show when prefixing with `command`. Default: `10`
|
|
243
243
|
- `raw`: whether raw mode should be used, meaning strictly process output will
|
|
244
244
|
be logged, without any prefixes, colouring or extra stuff.
|
|
245
245
|
- `successCondition`: the condition to consider the run was successful.
|
|
246
|
-
If `first`, only the first process will make up the success of the run; if `last`, the last.
|
|
246
|
+
If `first`, only the first process to exit will make up the success of the run; if `last`, the last process that exits will determine whether the run succeeds.
|
|
247
247
|
Anything else means all processes should exit successfully.
|
|
248
248
|
- `restartTries`: how many attempts to restart a process that dies will be made. Default: `0`.
|
|
249
249
|
- `restartDelay`: how many milliseconds to wait between process restarts. Default: `0`.
|
|
@@ -258,7 +258,7 @@ Example:
|
|
|
258
258
|
```js
|
|
259
259
|
const concurrently = require('concurrently');
|
|
260
260
|
concurrently([
|
|
261
|
-
'npm:watch-*',
|
|
261
|
+
'npm:watch-*',
|
|
262
262
|
{ command: 'nodemon', name: 'server' }
|
|
263
263
|
], {
|
|
264
264
|
prefix: 'name',
|
|
@@ -282,3 +282,6 @@ concurrently([
|
|
|
282
282
|
So *null* means the process didn't terminate normally. This will make **concurrent**
|
|
283
283
|
to return non-zero exit code too.
|
|
284
284
|
|
|
285
|
+
* Does this work with the npm-replacement [yarn](https://github.com/yarnpkg/yarn)?
|
|
286
|
+
|
|
287
|
+
Yes! In all examples above, you may replace "`npm`" with "`yarn`".
|
package/bin/concurrently.js
CHANGED
|
@@ -8,7 +8,7 @@ const args = yargs
|
|
|
8
8
|
.usage('$0 [options] <command ...>')
|
|
9
9
|
.help('h')
|
|
10
10
|
.alias('h', 'help')
|
|
11
|
-
.version('v')
|
|
11
|
+
.version('v', require('../package.json').version)
|
|
12
12
|
.alias('v', 'V')
|
|
13
13
|
.alias('v', 'version')
|
|
14
14
|
.options({
|
|
@@ -154,6 +154,7 @@ concurrently(args._.map((command, index) => {
|
|
|
154
154
|
: (args.killOthersOnFail ? ['failure'] : []),
|
|
155
155
|
raw: args.raw,
|
|
156
156
|
prefix: args.prefix,
|
|
157
|
+
prefixLength: args.prefixLength,
|
|
157
158
|
restartDelay: args.restartAfter,
|
|
158
159
|
restartTries: args.restartTries,
|
|
159
160
|
successCondition: args.success,
|
package/bin/concurrently.spec.js
CHANGED
|
@@ -13,7 +13,12 @@ const createKillMessage = prefix => new RegExp(
|
|
|
13
13
|
|
|
14
14
|
const run = args => {
|
|
15
15
|
const child = spawn('node ./concurrently.js ' + args, {
|
|
16
|
-
cwd: __dirname
|
|
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
|
+
}),
|
|
17
22
|
});
|
|
18
23
|
|
|
19
24
|
const stdout = readline.createInterface({
|
|
@@ -60,7 +65,7 @@ it('has version command', done => {
|
|
|
60
65
|
}, done);
|
|
61
66
|
});
|
|
62
67
|
|
|
63
|
-
describe('
|
|
68
|
+
describe('exiting conditions', () => {
|
|
64
69
|
it('is of success by default when running successful commands', done => {
|
|
65
70
|
run('"echo foo" "echo bar"')
|
|
66
71
|
.close
|
|
@@ -79,8 +84,8 @@ describe('exitting conditions', () => {
|
|
|
79
84
|
}, done);
|
|
80
85
|
});
|
|
81
86
|
|
|
82
|
-
it('is of success when --success=first and first command succeeds', done => {
|
|
83
|
-
run('--success=first "echo foo" "exit 1"')
|
|
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"')
|
|
84
89
|
.close
|
|
85
90
|
.subscribe(exit => {
|
|
86
91
|
expect(exit[0]).toBe(0);
|
|
@@ -88,8 +93,8 @@ describe('exitting conditions', () => {
|
|
|
88
93
|
}, done);
|
|
89
94
|
});
|
|
90
95
|
|
|
91
|
-
it('is of failure when --success=first and first command fails', done => {
|
|
92
|
-
run('--success=first "exit 1" "echo foo"')
|
|
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"')
|
|
93
98
|
.close
|
|
94
99
|
.subscribe(exit => {
|
|
95
100
|
expect(exit[0]).toBeGreaterThan(0);
|
|
@@ -97,8 +102,8 @@ describe('exitting conditions', () => {
|
|
|
97
102
|
}, done);
|
|
98
103
|
});
|
|
99
104
|
|
|
100
|
-
it('is of success when --success=last and last command succeeds', done => {
|
|
101
|
-
run('--success=last "exit 1" "echo foo"')
|
|
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"')
|
|
102
107
|
.close
|
|
103
108
|
.subscribe(exit => {
|
|
104
109
|
expect(exit[0]).toBe(0);
|
|
@@ -106,8 +111,8 @@ describe('exitting conditions', () => {
|
|
|
106
111
|
}, done);
|
|
107
112
|
});
|
|
108
113
|
|
|
109
|
-
it('is of failure when --success=last and last command fails', done => {
|
|
110
|
-
run('--success=last "echo foo" "exit 1"')
|
|
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"')
|
|
111
116
|
.close
|
|
112
117
|
.subscribe(exit => {
|
|
113
118
|
expect(exit[0]).toBeGreaterThan(0);
|
|
@@ -127,7 +132,7 @@ describe('exitting conditions', () => {
|
|
|
127
132
|
});
|
|
128
133
|
|
|
129
134
|
it('is aliased to -s', done => {
|
|
130
|
-
run('-s last "exit 1" "echo foo"')
|
|
135
|
+
run('-s last "exit 1" "sleep 0.5 && echo foo"')
|
|
131
136
|
.close
|
|
132
137
|
.subscribe(exit => {
|
|
133
138
|
expect(exit[0]).toBe(0);
|
|
@@ -207,6 +212,26 @@ describe('--prefix', () => {
|
|
|
207
212
|
});
|
|
208
213
|
});
|
|
209
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
|
+
|
|
210
235
|
describe('--restart-tries', () => {
|
|
211
236
|
it('changes how many times a command will restart', done => {
|
|
212
237
|
const child = run('--restart-tries 1 "exit 1"');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "concurrently",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.2",
|
|
4
4
|
"description": "Run commands concurrently",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"lint": "eslint . --ignore-path .gitignore",
|
|
14
|
+
"report-coverage": "cat coverage/lcov.info | coveralls",
|
|
14
15
|
"test": "jest"
|
|
15
16
|
},
|
|
16
17
|
"repository": {
|
|
@@ -28,19 +29,20 @@
|
|
|
28
29
|
"author": "Kimmo Brunfeldt",
|
|
29
30
|
"license": "MIT",
|
|
30
31
|
"dependencies": {
|
|
31
|
-
"chalk": "^2.4.
|
|
32
|
-
"date-fns": "^1.
|
|
33
|
-
"lodash": "^4.17.
|
|
32
|
+
"chalk": "^2.4.2",
|
|
33
|
+
"date-fns": "^1.30.1",
|
|
34
|
+
"lodash": "^4.17.15",
|
|
34
35
|
"read-pkg": "^4.0.1",
|
|
35
|
-
"rxjs": "6.
|
|
36
|
+
"rxjs": "^6.5.2",
|
|
36
37
|
"spawn-command": "^0.0.2-1",
|
|
37
38
|
"supports-color": "^4.5.0",
|
|
38
|
-
"tree-kill": "^1.1
|
|
39
|
-
"yargs": "^12.0.
|
|
39
|
+
"tree-kill": "^1.2.1",
|
|
40
|
+
"yargs": "^12.0.5"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
|
-
"
|
|
43
|
-
"
|
|
43
|
+
"coveralls": "^3.0.4",
|
|
44
|
+
"eslint": "^5.16.0",
|
|
45
|
+
"jest": "^24.8.0",
|
|
44
46
|
"jest-create-mock-instance": "^1.1.0"
|
|
45
47
|
},
|
|
46
48
|
"jest": {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
module.exports = class ExpandNpmShortcut {
|
|
2
2
|
parse(commandInfo) {
|
|
3
|
-
const [, cmdName, args] = commandInfo.command.match(/^npm:(\S+)(.*)/) || [];
|
|
3
|
+
const [, npmCmd, cmdName, args] = commandInfo.command.match(/^(npm|yarn):(\S+)(.*)/) || [];
|
|
4
4
|
if (!cmdName) {
|
|
5
5
|
return commandInfo;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
return Object.assign({}, commandInfo, {
|
|
9
9
|
name: commandInfo.name || cmdName,
|
|
10
|
-
command:
|
|
10
|
+
command: `${npmCmd} run ${cmdName}${args}`
|
|
11
11
|
});
|
|
12
12
|
}
|
|
13
13
|
};
|
|
@@ -9,25 +9,28 @@ it('returns same command if no npm: prefix is present', () => {
|
|
|
9
9
|
expect(parser.parse(commandInfo)).toBe(commandInfo);
|
|
10
10
|
});
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
+
});
|
|
21
23
|
});
|
|
22
|
-
});
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
+
});
|
|
31
33
|
});
|
|
32
34
|
});
|
|
33
|
-
|
|
35
|
+
|
|
36
|
+
}
|
|
@@ -7,7 +7,7 @@ module.exports = class ExpandNpmWildcard {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
parse(commandInfo) {
|
|
10
|
-
const [, cmdName, args] = commandInfo.command.match(/npm run (\S+)([^&]*)/) || [];
|
|
10
|
+
const [, npmCmd, cmdName, args] = commandInfo.command.match(/(npm|yarn) run (\S+)([^&]*)/) || [];
|
|
11
11
|
const wildcardPosition = (cmdName || '').indexOf('*');
|
|
12
12
|
|
|
13
13
|
// If the regex didn't match an npm script, or it has no wildcard,
|
|
@@ -27,7 +27,7 @@ module.exports = class ExpandNpmWildcard {
|
|
|
27
27
|
return this.scripts
|
|
28
28
|
.filter(script => wildcardRegex.test(script))
|
|
29
29
|
.map(script => Object.assign({}, commandInfo, {
|
|
30
|
-
command:
|
|
30
|
+
command: `${npmCmd} run ${script}${args}`,
|
|
31
31
|
name: script
|
|
32
32
|
}));
|
|
33
33
|
}
|
|
@@ -31,24 +31,28 @@ it('expands to nothing if no scripts exist in package.json', () => {
|
|
|
31
31
|
expect(parser.parse({ command: 'npm run foo-*-baz qux' })).toEqual([]);
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
scripts
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
+
});
|
|
40
57
|
});
|
|
41
|
-
|
|
42
|
-
expect(parser.parse({ command: 'npm run foo-*-baz qux' })).toEqual([
|
|
43
|
-
{ name: 'foo-bar-baz', command: 'npm run foo-bar-baz qux' },
|
|
44
|
-
{ name: 'foo--baz', command: 'npm run foo--baz qux' },
|
|
45
|
-
]);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('caches scripts upon calls', () => {
|
|
49
|
-
readPkg.mockReturnValue({});
|
|
50
|
-
parser.parse({ command: 'npm run foo-*-baz qux' });
|
|
51
|
-
parser.parse({ command: 'npm run foo-*-baz qux' });
|
|
52
|
-
|
|
53
|
-
expect(readPkg).toHaveBeenCalledTimes(1);
|
|
54
|
-
});
|
|
58
|
+
}
|
|
@@ -3,7 +3,7 @@ module.exports = class StripQuotes {
|
|
|
3
3
|
let { command } = commandInfo;
|
|
4
4
|
|
|
5
5
|
// Removes the quotes surrounding a command.
|
|
6
|
-
if (command
|
|
6
|
+
if (/^"(.+?)"$/.test(command) || /^'(.+?)'$/.test(command)) {
|
|
7
7
|
command = command.substr(1, command.length - 2);
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -12,3 +12,9 @@ it('strips single quotes', () => {
|
|
|
12
12
|
it('strips double quotes', () => {
|
|
13
13
|
expect(parser.parse({ command: '"echo foo"' })).toEqual({ command: 'echo foo' });
|
|
14
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
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const Rx = require('rxjs');
|
|
2
|
-
const { map, switchMap, take } = require('rxjs/operators');
|
|
2
|
+
const { bufferCount, map, switchMap, take } = require('rxjs/operators');
|
|
3
3
|
|
|
4
4
|
module.exports = class CompletionListener {
|
|
5
5
|
constructor({ successCondition, scheduler }) {
|
|
@@ -9,7 +9,9 @@ module.exports = class CompletionListener {
|
|
|
9
9
|
|
|
10
10
|
listen(commands) {
|
|
11
11
|
const closeStreams = commands.map(command => command.close);
|
|
12
|
-
|
|
12
|
+
const allClosed = Rx.zip(...closeStreams);
|
|
13
|
+
return Rx.merge(...closeStreams).pipe(
|
|
14
|
+
bufferCount(closeStreams.length),
|
|
13
15
|
map(exitCodes => {
|
|
14
16
|
switch (this.successCondition) {
|
|
15
17
|
/* eslint-disable indent */
|
|
@@ -40,22 +40,22 @@ describe('with default success condition set', () => {
|
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
describe('with success condition set to first', () => {
|
|
43
|
-
it('succeeds if first process
|
|
43
|
+
it('succeeds if first process to exit has code 0', () => {
|
|
44
44
|
const result = createController('first').listen(commands);
|
|
45
45
|
|
|
46
|
-
commands[
|
|
47
|
-
commands[
|
|
46
|
+
commands[1].close.next(0);
|
|
47
|
+
commands[0].close.next(1);
|
|
48
48
|
|
|
49
49
|
scheduler.flush();
|
|
50
50
|
|
|
51
51
|
return expect(result).resolves.toBeNull();
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
it('fails if first process
|
|
54
|
+
it('fails if first process to exit has non-0 code', () => {
|
|
55
55
|
const result = createController('first').listen(commands);
|
|
56
56
|
|
|
57
|
-
commands[
|
|
58
|
-
commands[
|
|
57
|
+
commands[1].close.next(1);
|
|
58
|
+
commands[0].close.next(0);
|
|
59
59
|
|
|
60
60
|
scheduler.flush();
|
|
61
61
|
|
|
@@ -64,22 +64,22 @@ describe('with success condition set to first', () => {
|
|
|
64
64
|
});
|
|
65
65
|
|
|
66
66
|
describe('with success condition set to last', () => {
|
|
67
|
-
it('succeeds if last process
|
|
67
|
+
it('succeeds if last process to exit has code 0', () => {
|
|
68
68
|
const result = createController('last').listen(commands);
|
|
69
69
|
|
|
70
|
-
commands[
|
|
71
|
-
commands[
|
|
70
|
+
commands[1].close.next(1);
|
|
71
|
+
commands[0].close.next(0);
|
|
72
72
|
|
|
73
73
|
scheduler.flush();
|
|
74
74
|
|
|
75
75
|
return expect(result).resolves.toBeNull();
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
-
it('fails if
|
|
78
|
+
it('fails if last process to exit has non-0 code', () => {
|
|
79
79
|
const result = createController('last').listen(commands);
|
|
80
80
|
|
|
81
|
-
commands[
|
|
82
|
-
commands[
|
|
81
|
+
commands[1].close.next(0);
|
|
82
|
+
commands[0].close.next(1);
|
|
83
83
|
|
|
84
84
|
scheduler.flush();
|
|
85
85
|
|
|
@@ -13,6 +13,16 @@ beforeEach(() => {
|
|
|
13
13
|
controller = new KillOnSignal({ process });
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
+
it('returns commands that keep non-close streams from original commands', () => {
|
|
17
|
+
const newCommands = controller.handle(commands);
|
|
18
|
+
newCommands.forEach((newCommand, i) => {
|
|
19
|
+
expect(newCommand.close).not.toBe(commands[i].close);
|
|
20
|
+
expect(newCommand.error).toBe(commands[i].error);
|
|
21
|
+
expect(newCommand.stdout).toBe(commands[i].stdout);
|
|
22
|
+
expect(newCommand.stderr).toBe(commands[i].stderr);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
16
26
|
it('returns commands that map SIGINT to exit code 0', () => {
|
|
17
27
|
const newCommands = controller.handle(commands);
|
|
18
28
|
expect(newCommands).not.toBe(commands);
|
|
@@ -29,6 +39,18 @@ it('returns commands that map SIGINT to exit code 0', () => {
|
|
|
29
39
|
expect(callback).toHaveBeenCalledWith(0);
|
|
30
40
|
});
|
|
31
41
|
|
|
42
|
+
it('returns commands that keep non-SIGINT exit codes', () => {
|
|
43
|
+
const newCommands = controller.handle(commands);
|
|
44
|
+
expect(newCommands).not.toBe(commands);
|
|
45
|
+
expect(newCommands).toHaveLength(commands.length);
|
|
46
|
+
|
|
47
|
+
const callback = jest.fn();
|
|
48
|
+
newCommands[0].close.subscribe(callback);
|
|
49
|
+
commands[0].close.next(1);
|
|
50
|
+
|
|
51
|
+
expect(callback).toHaveBeenCalledWith(1);
|
|
52
|
+
});
|
|
53
|
+
|
|
32
54
|
it('kills all commands on SIGINT', () => {
|
|
33
55
|
controller.handle(commands);
|
|
34
56
|
process.emit('SIGINT');
|
|
@@ -116,4 +116,14 @@ describe('returned commands', () => {
|
|
|
116
116
|
// 1 failure from commands[0], 1 success from commands[1]
|
|
117
117
|
expect(callback).toHaveBeenCalledTimes(2);
|
|
118
118
|
});
|
|
119
|
+
|
|
120
|
+
it('keep non-close streams from original commands', () => {
|
|
121
|
+
const newCommands = controller.handle(commands);
|
|
122
|
+
newCommands.forEach((newCommand, i) => {
|
|
123
|
+
expect(newCommand.close).not.toBe(commands[i].close);
|
|
124
|
+
expect(newCommand.error).toBe(commands[i].error);
|
|
125
|
+
expect(newCommand.stdout).toBe(commands[i].stdout);
|
|
126
|
+
expect(newCommand.stderr).toBe(commands[i].stderr);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
119
129
|
});
|