Skip to content

Commit

Permalink
Add stdout/stderr to error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
ehmicky committed Dec 1, 2019
1 parent d50146b commit a043398
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 10 deletions.
11 changes: 8 additions & 3 deletions index.d.ts
Expand Up @@ -44,7 +44,7 @@ declare namespace execa {
This can be either an absolute path or a path relative to the `cwd` option.
Requires `preferLocal` to be `true`.
For example, this can be used together with [`get-node`](https://github.com/ehmicky/get-node) to run a specific Node.js version in a child process.
@default process.execPath
Expand Down Expand Up @@ -341,9 +341,14 @@ declare namespace execa {
message: string;

/**
Original error message. This is `undefined` unless the child process exited due to an `error` event or a timeout.
This is the same as the `message` property except it does not include the child process stdout/stderr.
*/
shortMessage: string;

/**
Original error message. This is the same as the `message` property except it includes neither the child process stdout/stderr nor some additional information added by Execa.
The `message` property contains both the `originalMessage` and some additional information added by Execa.
This is `undefined` unless the child process exited due to an `error` event or a timeout.
*/
originalMessage?: string;
}
Expand Down
2 changes: 2 additions & 0 deletions index.test-d.ts
Expand Up @@ -40,6 +40,7 @@ try {
expectType<boolean>(execaError.killed);
expectType<string | undefined>(execaError.signal);
expectType<string | undefined>(execaError.signalDescription);
expectType<string>(execaError.shortMessage);
expectType<string | undefined>(execaError.originalMessage);
}

Expand Down Expand Up @@ -70,6 +71,7 @@ try {
expectType<boolean>(execaError.killed);
expectType<string | undefined>(execaError.signal);
expectType<string | undefined>(execaError.signalDescription);
expectType<string>(execaError.shortMessage);
expectType<string | undefined>(execaError.originalMessage);
}

Expand Down
7 changes: 5 additions & 2 deletions lib/error.js
Expand Up @@ -47,15 +47,18 @@ const makeError = ({
const errorCode = error && error.code;

const prefix = getErrorPrefix({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled});
const message = `Command ${prefix}: ${command}`;
const execaMessage = `Command ${prefix}: ${command}`;
const shortMessage = error instanceof Error ? `${execaMessage}\n${error.message}` : execaMessage;
const message = [shortMessage, stderr, stdout].filter(Boolean).join('\n');

if (error instanceof Error) {
error.originalMessage = error.message;
error.message = `${message}\n${error.message}`;
error.message = message;
} else {
error = new Error(message);
}

error.shortMessage = shortMessage;
error.command = command;
error.exitCode = exitCode;
error.signal = signal;
Expand Down
16 changes: 12 additions & 4 deletions readme.md
Expand Up @@ -63,12 +63,13 @@ const execa = require('execa');
/*
{
message: 'Command failed with ENOENT: unknown command spawn unknown ENOENT',
errno: 'ENOENT',
errno: -2,
code: 'ENOENT',
syscall: 'spawn unknown',
path: 'unknown',
spawnargs: ['command'],
originalMessage: 'spawn unknown ENOENT',
shortMessage: 'Command failed with ENOENT: unknown command spawn unknown ENOENT',
command: 'unknown command',
stdout: '',
stderr: '',
Expand Down Expand Up @@ -115,12 +116,13 @@ try {
/*
{
message: 'Command failed with ENOENT: unknown command spawnSync unknown ENOENT',
errno: 'ENOENT',
errno: -2,
code: 'ENOENT',
syscall: 'spawnSync unknown',
path: 'unknown',
spawnargs: ['command'],
originalMessage: 'spawnSync unknown ENOENT',
shortMessage: 'Command failed with ENOENT: unknown command spawnSync unknown ENOENT',
command: 'unknown command',
stdout: '',
stderr: '',
Expand Down Expand Up @@ -306,13 +308,19 @@ A human-friendly description of the signal that was used to terminate the proces

If a signal terminated the process, this property is defined and included in the error message. Otherwise it is `undefined`. It is also `undefined` when the signal is very uncommon which should seldomly happen.

#### shortMessage

Type: `string`

This is the same as the `message` property except it does not include the child process stdout/stderr.

#### originalMessage

Type: `string | undefined`

Original error message. This is `undefined` unless the child process exited due to an `error` event or a timeout.
Original error message. This is the same as the `message` property except it includes neither the child process stdout/stderr nor some additional information added by Execa.

The `message` property contains both the `originalMessage` and some additional information added by Execa.
This is `undefined` unless the child process exited due to an `error` event or a timeout.

### options

Expand Down
20 changes: 19 additions & 1 deletion test/error.js
Expand Up @@ -51,7 +51,25 @@ test('exitCode is 3', testExitCode, 3);
test('exitCode is 4', testExitCode, 4);

test('error.message contains the command', async t => {
await t.throwsAsync(execa('exit', ['2', 'foo', 'bar'], {message: /exit 2 foo bar/}));
await t.throwsAsync(execa('exit', ['2', 'foo', 'bar']), {message: /exit 2 foo bar/});
});

test('error.message contains stdout/stderr if available', async t => {
const {message} = await t.throwsAsync(execa('echo-fail'));
t.true(message.includes('stderr'));
t.true(message.includes('stdout'));
});

test('error.message does not contain stdout/stderr if not available', async t => {
const {message} = await t.throwsAsync(execa('echo-fail', {stdio: 'ignore'}));
t.false(message.includes('stderr'));
t.false(message.includes('stdout'));
});

test('error.shortMessage does not contain stdout/stderr', async t => {
const {shortMessage} = await t.throwsAsync(execa('echo-fail'));
t.false(shortMessage.includes('stderr'));
t.false(shortMessage.includes('stdout'));
});

test('Original error.message is kept', async t => {
Expand Down
5 changes: 5 additions & 0 deletions test/fixtures/echo-fail
@@ -0,0 +1,5 @@
#!/usr/bin/env node
'use strict';
console.log('stdout');
console.error('stderr');
process.exit(1);

0 comments on commit a043398

Please sign in to comment.