Repository: sindresorhus/execa
Pull request #240 (2019-05-13 12:08:11)

Fix `stripFinalNewline` not applied on `error.stdout|stderr|all`
The `stripFinalNewline` option was applied on the `stdout`, `stderr` and `all` properties of the resolved result (on success) but not of the rejected error (on failure).

This also adds more tests for this option.


Patch:
diff --git a/fixtures/noop-throw b/fixtures/noop-throw
new file mode 100755
index 0000000..521e70a
--- /dev/null
+++ b/fixtures/noop-throw
@@ -0,0 +1,4 @@
+#!/usr/bin/env node
+'use strict';
+console.error(process.argv[2]);
+process.exit(2);
diff --git a/index.js b/index.js
index dd14df7..3e96202 100644
--- a/index.js
+++ b/index.js
@@ -350,10 +350,10 @@ const execa = (command, args, options) => {
 		const finalize = async () => {
 			const results = await processComplete;
 
-			const result = results[0];
-			result.stdout = results[1];
-			result.stderr = results[2];
-			result.all = results[3];
+			const [result, stdout, stderr, all] = results;
+			result.stdout = handleOutput(parsed.options, stdout);
+			result.stderr = handleOutput(parsed.options, stderr);
+			result.all = handleOutput(parsed.options, all);
 
 			if (result.error || result.code !== 0 || result.signal !== null) {
 				const error = makeError(result, {
@@ -372,9 +372,9 @@ const execa = (command, args, options) => {
 			}
 
 			return {
-				stdout: handleOutput(parsed.options, result.stdout),
-				stderr: handleOutput(parsed.options, result.stderr),
-				all: handleOutput(parsed.options, result.all),
+				stdout: result.stdout,
+				stderr: result.stderr,
+				all: result.all,
 				code: 0,
 				exitCode: 0,
 				exitCodeName: 'SUCCESS',
@@ -425,6 +425,8 @@ module.exports.sync = (command, args, options) => {
 
 	const result = childProcess.spawnSync(parsed.command, parsed.args, parsed.options);
 	result.code = result.status;
+	result.stdout = handleOutput(parsed.options, result.stdout);
+	result.stderr = handleOutput(parsed.options, result.stderr);
 
 	if (result.error || result.status !== 0 || result.signal !== null) {
 		const error = makeError(result, {
@@ -442,8 +444,8 @@ module.exports.sync = (command, args, options) => {
 	}
 
 	return {
-		stdout: handleOutput(parsed.options, result.stdout),
-		stderr: handleOutput(parsed.options, result.stderr),
+		stdout: result.stdout,
+		stderr: result.stderr,
 		code: 0,
 		exitCode: 0,
 		exitCodeName: 'SUCCESS',


Test patch:
diff --git a/test.js b/test.js
index 31e4819..9579764 100644
--- a/test.js
+++ b/test.js
@@ -120,11 +120,31 @@ test('skip throwing when using reject option in sync mode', t => {
 	t.is(error.exitCode, 2);
 });
 
-test('stripFinalNewline option', async t => {
+test('stripFinalNewline: true', async t => {
+	const {stdout} = await execa('noop', ['foo']);
+	t.is(stdout, 'foo');
+});
+
+test('stripFinalNewline: false', async t => {
 	const {stdout} = await execa('noop', ['foo'], {stripFinalNewline: false});
 	t.is(stdout, 'foo\n');
 });
 
+test('stripFinalNewline on failure', async t => {
+	const {stderr} = await t.throwsAsync(execa('noop-throw', ['foo'], {stripFinalNewline: true}));
+	t.is(stderr, 'foo');
+});
+
+test('stripFinalNewline in sync mode', t => {
+	const {stdout} = execa.sync('noop', ['foo'], {stripFinalNewline: true});
+	t.is(stdout, 'foo');
+});
+
+test('stripFinalNewline in sync mode on failure', t => {
+	const {stderr} = t.throws(() => execa.sync('noop-throw', ['foo'], {stripFinalNewline: true}));
+	t.is(stderr, 'foo');
+});
+
 test('preferLocal option', async t => {
 	await execa('ava', ['--version'], {env: {PATH: ''}});
 	const errorRegExp = process.platform === 'win32' ? /failed with exit code 1/ : /spawn ava ENOENT/;