Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CustomConsole: print console.error and console.assert to stderr #8261

Merged
merged 7 commits into from Apr 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,8 @@

### Fixes

- `[@jest/console]` Print to stderr when calling `console.error`, `console.warn` or `console.assert` using the `jest-runtime` CLI ([#8261](https://github.com/facebook/jest/pull/8261))

### Chore & Maintenance

### Performance
Expand Down
25 changes: 15 additions & 10 deletions packages/jest-console/src/CustomConsole.ts
Expand Up @@ -12,8 +12,8 @@ import chalk from 'chalk';
import {LogCounters, LogMessage, LogTimers, LogType} from './types';

// TODO: Copied from `jest-util`. Import from it in Jest 25
function clearLine(stream: NodeJS.WritableStream) {
if (process.stdout.isTTY) {
function clearLine(stream: NodeJS.WritableStream & {isTTY?: boolean}) {
if (stream.isTTY) {
stream.write('\x1b[999D\x1b[K');
}
}
Expand All @@ -22,6 +22,7 @@ type Formatter = (type: LogType, message: LogMessage) => string;

export default class CustomConsole extends Console {
private _stdout: NodeJS.WritableStream;
private _stderr: NodeJS.WritableStream;
private _formatBuffer: Formatter;
private _counters: LogCounters;
private _timers: LogTimers;
Expand All @@ -34,19 +35,23 @@ export default class CustomConsole extends Console {
) {
super(stdout, stderr);
this._stdout = stdout;
this._stderr = stderr;
this._formatBuffer = formatBuffer;
this._counters = {};
this._timers = {};
this._groupDepth = 0;
}

private _logToParentConsole(message: string) {
super.log(message);
}

private _log(type: LogType, message: string) {
clearLine(this._stdout);
this._logToParentConsole(
super.log(
this._formatBuffer(type, ' '.repeat(this._groupDepth) + message),
);
}

private _logError(type: LogType, message: string) {
clearLine(this._stderr);
super.error(
this._formatBuffer(type, ' '.repeat(this._groupDepth) + message),
);
}
Expand All @@ -55,7 +60,7 @@ export default class CustomConsole extends Console {
try {
assert(value, message);
} catch (error) {
this._log('assert', error.toString());
this._logError('assert', error.toString());
}
}

Expand Down Expand Up @@ -84,7 +89,7 @@ export default class CustomConsole extends Console {
}

error(firstArg: any, ...args: Array<any>) {
this._log('error', format(firstArg, ...args));
this._logError('error', format(firstArg, ...args));
}

group(title?: string, ...args: Array<any>) {
Expand Down Expand Up @@ -137,7 +142,7 @@ export default class CustomConsole extends Console {
}

warn(firstArg: any, ...args: Array<any>) {
this._log('warn', format(firstArg, ...args));
this._logError('warn', format(firstArg, ...args));
}

getBuffer() {
Expand Down
Expand Up @@ -5,47 +5,88 @@
* LICENSE file in the root directory of this source tree.
*/

import {Writable} from 'stream';
import chalk from 'chalk';
import CustomConsole from '../CustomConsole';

describe('CustomConsole', () => {
let _console;
let _stdout = '';
let _stdout;
let _stderr;

beforeEach(() => {
_console = new CustomConsole(process.stdout, process.stderr);
jest.spyOn(_console, '_logToParentConsole').mockImplementation(message => {
_stdout += message + '\n';
_stdout = '';
_stderr = '';

const stdout = new Writable({
write(chunk, encoding, callback) {
_stdout += chunk.toString();
callback();
},
});

_stdout = '';
const stderr = new Writable({
write(chunk, encoding, callback) {
_stderr += chunk.toString();
callback();
},
});

_console = new CustomConsole(stdout, stderr);
});

describe('log', () => {
test('should print to stdout', () => {
_console.log('Hello world!');

expect(_stdout).toBe('Hello world!\n');
});
});

describe('error', () => {
test('should print to stderr', () => {
_console.error('Found some error!');

expect(_stderr).toBe('Found some error!\n');
});
});

describe('warn', () => {
test('should print to stderr', () => {
_console.warn('Found some warning!');

expect(_stderr).toBe('Found some warning!\n');
});
});

describe('assert', () => {
test('do not log when the assertion is truthy', () => {
_console.assert(true);

expect(_stdout).toMatch('');
expect(_stderr).toMatch('');
});

test('do not log when the assertion is truthy and there is a message', () => {
_console.assert(true, 'ok');

expect(_stdout).toMatch('');
expect(_stderr).toMatch('');
});

test('log the assertion error when the assertion is falsy', () => {
_console.assert(false);

expect(_stdout).toMatch('AssertionError');
expect(_stdout).toMatch('false == true');
expect(_stderr).toMatch('AssertionError');
expect(_stderr).toMatch(
// The message may differ across Node versions
/(false == true)|(The expression evaluated to a falsy value:)/,
);
});

test('log the assertion error when the assertion is falsy with another message argument', () => {
_console.assert(false, 'ok');
_console.assert(false, 'this should not happen');

expect(_stdout).toMatch('AssertionError');
expect(_stdout).toMatch('ok');
expect(_stderr).toMatch('AssertionError');
expect(_stderr).toMatch('this should not happen');
});
});

Expand Down
8 changes: 2 additions & 6 deletions packages/jest-runner/src/runTest.ts
Expand Up @@ -135,13 +135,9 @@ async function runTestInternal(
let testConsole;

if (globalConfig.silent) {
testConsole = new NullConsole(consoleOut, process.stderr, consoleFormatter);
testConsole = new NullConsole(consoleOut, consoleOut, consoleFormatter);
} else if (globalConfig.verbose) {
testConsole = new CustomConsole(
consoleOut,
process.stderr,
consoleFormatter,
);
testConsole = new CustomConsole(consoleOut, consoleOut, consoleFormatter);
} else {
testConsole = new BufferedConsole(() => runtime && runtime.getSourceMaps());
}
Expand Down