Skip to content
/ jest Public
forked from jestjs/jest

Commit

Permalink
Intercept process.stdout and process.stderr
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB committed Jun 22, 2018
1 parent d1ce3cd commit 2db9c9b
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 436 deletions.
10 changes: 9 additions & 1 deletion e2e/__tests__/__snapshots__/console.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ exports[`console printing 1`] = `
This is a warning message.
console.error __tests__/console.test.js:16
This is an error message.
process.stdout.write __tests__/console.test.js:18
write directly to stdout
process.stderr.write __tests__/console.test.js:20
write directly to stderr
"
Expand All @@ -37,7 +41,11 @@ exports[`console printing with --verbose 1`] = `
console.error __tests__/console.test.js:16
This is an error message.
"
process.stdout.write __tests__/console.test.js:18
write directly to stdout
process.stderr.write __tests__/console.test.js:20
write directly to stderr"
`;
exports[`console printing with --verbose 2`] = `
Expand Down
4 changes: 4 additions & 0 deletions e2e/console/__tests__/console.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ test('works just fine', () => {
console.warn('This is a warning message.');

console.error('This is an error message.');

process.stdout.write('write directly to stdout');

process.stderr.write('write directly to stderr');
});
1 change: 1 addition & 0 deletions packages/jest-runner/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"jest-runtime": "^23.1.0",
"jest-util": "^23.1.0",
"jest-worker": "^23.0.1",
"readable-stream": "^2.3.6",
"source-map-support": "^0.5.6",
"throat": "^4.0.0"
}
Expand Down
102 changes: 99 additions & 3 deletions packages/jest-runner/src/run_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import LeakDetector from 'jest-leak-detector';
import {getTestEnvironment} from 'jest-config';
import * as docblock from 'jest-docblock';
import sourcemapSupport from 'source-map-support';
import {Transform} from 'readable-stream';

type RunTestInternalResult = {
leakDetector: ?LeakDetector,
Expand Down Expand Up @@ -75,7 +76,7 @@ async function runTestInternal(
let runtime = undefined;

const consoleOut = globalConfig.useStderr ? process.stderr : process.stdout;
const consoleFormatter = (type, message) =>
const consoleFormatter = (type, message, api, level = 4) =>
getConsoleOutput(
config.cwd,
!!globalConfig.verbose,
Expand All @@ -84,21 +85,107 @@ async function runTestInternal(
[],
type,
message,
4,
level,
runtime && runtime.getSourceMaps(),
api,
),
);

let testConsole;
let testStdOut;
let testStdErr;
let buffer;

if (globalConfig.silent) {
testConsole = new NullConsole(consoleOut, process.stderr, consoleFormatter);
testStdOut = new Transform({
transform(chunk, encoding, callback) {
callback(null);
},
});
testStdErr = new Transform({
transform(chunk, encoding, callback) {
callback(null);
},
});
} else if (globalConfig.verbose) {
testConsole = new Console(consoleOut, process.stderr, consoleFormatter);
testStdOut = new Transform({
transform(chunk, encoding, callback) {
callback(null, chunk);
},
});
testStdErr = new Transform({
transform(chunk, encoding, callback) {
callback(null, chunk);
},
});
} else {
testConsole = new BufferedConsole(() => runtime && runtime.getSourceMaps());
buffer = [];
testConsole = new BufferedConsole(
() => runtime && runtime.getSourceMaps(),
buffer,
);
testStdOut = new Transform({
transform(chunk, encoding, callback) {
callback(null, chunk);
},
});
testStdErr = new Transform({
transform(chunk, encoding, callback) {
callback(null, chunk);
},
});
}

const originalStdOutWrite = testStdOut.write;
const originalStdErrWrite = testStdErr.write;

testStdOut.write = (chunk, ...rest) => {
const type = 'write';
const message = chunk.toString();
const api = 'process.stdout';

if (buffer) {
BufferedConsole.write(
buffer,
type,
message,
2,
runtime && runtime.getSourceMaps(),
api,
);
} else if (globalConfig.verbose) {
consoleOut.write(consoleFormatter(type, message, api, 3));
}

return originalStdOutWrite.call(testStdOut, chunk, ...rest);
};

testStdErr.write = (chunk, ...rest) => {
const type = 'write';
const message = chunk.toString();
const api = 'process.stderr';

if (buffer) {
BufferedConsole.write(
buffer,
type,
message,
2,
runtime && runtime.getSourceMaps(),
api,
);
} else if (globalConfig.verbose) {
consoleOut.write(consoleFormatter(type, message, api, 3));
}

return originalStdErrWrite.call(testStdErr, chunk, ...rest);
};

testStdOut.setEncoding('utf8');
testStdErr.setEncoding('utf8');

const environment = new TestEnvironment(config, {console: testConsole});
const leakDetector = config.detectLeaks
? new LeakDetector(environment)
Expand All @@ -107,6 +194,15 @@ async function runTestInternal(
const cacheFS = {[path]: testSource};
setGlobal(environment.global, 'console', testConsole);

Object.defineProperty(environment.global.process, 'stdout', {
value: testStdOut,
writable: false,
});
Object.defineProperty(environment.global.process, 'stderr', {
value: testStdErr,
writable: false,
});

runtime = new Runtime(config, environment, resolver, cacheFS, {
collectCoverage: globalConfig.collectCoverage,
collectCoverageFrom: globalConfig.collectCoverageFrom,
Expand Down
6 changes: 4 additions & 2 deletions packages/jest-util/src/buffered_console.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import type {
ConsoleBuffer,
LogApi,
LogMessage,
LogType,
LogCounters,
Expand All @@ -30,8 +31,7 @@ export default class BufferedConsole extends Console {
_groupDepth: number;
_getSourceMaps: () => ?SourceMapRegistry;

constructor(getSourceMaps: () => ?SourceMapRegistry) {
const buffer = [];
constructor(getSourceMaps: () => ?SourceMapRegistry, buffer = []) {
super({
write: message =>
BufferedConsole.write(buffer, 'log', message, null, getSourceMaps()),
Expand All @@ -49,11 +49,13 @@ export default class BufferedConsole extends Console {
message: LogMessage,
level: ?number,
sourceMaps: ?SourceMapRegistry,
api: LogApi,
) {
const callsite = getCallsite(level != null ? level : 2, sourceMaps);
const origin = callsite.getFileName() + ':' + callsite.getLineNumber();

buffer.push({
api,
message,
origin,
type,
Expand Down
6 changes: 3 additions & 3 deletions packages/jest-util/src/get_console_output.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ export default (root: string, verbose: boolean, buffer: ConsoleBuffer) => {
const TITLE_INDENT = verbose ? ' ' : ' ';
const CONSOLE_INDENT = TITLE_INDENT + ' ';

return buffer.reduce((output, {type, message, origin}) => {
return buffer.reduce((output, {api = 'console', type, message, origin}) => {
origin = slash(path.relative(root, origin));
message = message
.split(/\n/)
.map(line => CONSOLE_INDENT + line)
.join('\n');

let typeMessage = 'console.' + type;
let typeMessage = `${api}.${type}`;
if (type === 'warn') {
message = chalk.yellow(message);
typeMessage = chalk.yellow(typeMessage);
} else if (type === 'error') {
} else if (type === 'error' || api === 'process.stderr') {
message = chalk.red(message);
typeMessage = chalk.red(typeMessage);
}
Expand Down
2 changes: 2 additions & 0 deletions types/Console.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
* @flow
*/

export type LogApi = 'console' | 'process.stdout' | 'process.stderr';
export type LogMessage = string;
export type LogEntry = {|
api: LogApi,
message: LogMessage,
origin: string,
type: LogType,
Expand Down
Loading

0 comments on commit 2db9c9b

Please sign in to comment.