Skip to content

Commit

Permalink
add methods to custom and buffered consoles (#5514)
Browse files Browse the repository at this point in the history
* add methods to custom and buffered consoles

* update changelog with the console methods addition

* use spyOn console to mock the implementation

* refactor console's calls to use ...args instead of arguments
  • Loading branch information
ranyitz authored and cpojer committed Feb 10, 2018
1 parent 09adc31 commit f29c03e
Show file tree
Hide file tree
Showing 6 changed files with 493 additions and 26 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
## master

### Features

* `[jest-util]` Add the following methods to the "console" implementations:
`assert`, `count`, `countReset`, `dir`, `dirxml`, `group`, `groupCollapsed`,
`groupEnd`, `time`, `timeEnd`
([#5514](https://github.com/facebook/jest/pull/5514))

## jest 22.2.2

### Fixes
Expand All @@ -16,8 +23,9 @@
([#5494](https://github.com/facebook/jest/pull/5494))

### Chore & Maintenance
* `[filenames]` Standardize file names in root ([#5500](https://github.com/facebook/jest/pull/5500))

* `[filenames]` Standardize file names in root
([#5500](https://github.com/facebook/jest/pull/5500))

## jest 22.2.1

Expand Down
104 changes: 92 additions & 12 deletions packages/jest-util/src/Console.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,21 @@
*/
/* global stream$Writable */

import type {LogType, LogMessage} from 'types/Console';
import type {LogType, LogMessage, LogCounters, LogTimers} from 'types/Console';

import {format} from 'util';
import {Console} from 'console';
import chalk from 'chalk';
import clearLine from './clear_line';

type Formatter = (type: LogType, message: LogMessage) => string;

export default class CustomConsole extends Console {
_stdout: stream$Writable;
_formatBuffer: Formatter;
_counters: LogCounters;
_timers: LogTimers;
_groupDepth: number;

constructor(
stdout: stream$Writable,
Expand All @@ -27,31 +31,107 @@ export default class CustomConsole extends Console {
) {
super(stdout, stderr);
this._formatBuffer = formatBuffer || ((type, message) => message);
this._counters = {};
this._timers = {};
this._groupDepth = 0;
}

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

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

assert(...args: Array<any>) {
if (args[0]) {
this._log('assert', format(...args.slice(1)));
}
}

count(label: string = 'default') {
if (!this._counters[label]) {
this._counters[label] = 0;
}

this._log('count', format(`${label}: ${++this._counters[label]}`));
}

debug(...args: Array<mixed>) {
this._log('debug', format.apply(null, arguments));
countReset(label: string = 'default') {
this._counters[label] = 0;
}

log(...args: Array<mixed>) {
this._log('log', format.apply(null, arguments));
debug(...args: Array<any>) {
this._log('debug', format(...args));
}

info(...args: Array<mixed>) {
this._log('info', format.apply(null, arguments));
dir(...args: Array<any>) {
this._log('dir', format(...args));
}

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

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

group(...args: Array<any>) {
this._groupDepth++;

if (args.length > 0) {
this._log('group', chalk.bold(format(...args)));
}
}

warn(...args: Array<mixed>) {
this._log('warn', format.apply(null, arguments));
groupCollapsed(...args: Array<any>) {
this._groupDepth++;

if (args.length > 0) {
this._log('groupCollapsed', chalk.bold(format(...args)));
}
}

groupEnd() {
if (this._groupDepth > 0) {
this._groupDepth--;
}
}

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

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

time(label: string = 'default') {
if (this._timers[label]) {
return;
}

this._timers[label] = new Date();
}

timeEnd(label: string = 'default') {
const startTime = this._timers[label];

if (startTime) {
const endTime = new Date();
const time = (endTime - startTime) / 1000;
this._log('time', format(`${label}: ${time}ms`));
delete this._timers[label];
}
}

error(...args: Array<mixed>) {
this._log('error', format.apply(null, arguments));
warn(...args: Array<any>) {
this._log('warn', format(...args));
}

getBuffer() {
Expand Down
134 changes: 134 additions & 0 deletions packages/jest-util/src/__tests__/buffered_console.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

import chalk from 'chalk';
import BufferedConsole from '../buffered_console';

describe('CustomConsole', () => {
let _console;
const stdout = () =>
_console
.getBuffer()
.map(log => log.message)
.join('\n');

beforeEach(() => {
_console = new BufferedConsole();
});

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

expect(stdout()).toMatch('ok');
});

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

expect(stdout()).toEqual('');
});
});

describe('count', () => {
test('count using the default counter', () => {
_console.count();
_console.count();
_console.count();

expect(stdout()).toEqual('default: 1\ndefault: 2\ndefault: 3');
});

test('count using the a labeled counter', () => {
_console.count('custom');
_console.count('custom');
_console.count('custom');

expect(stdout()).toEqual('custom: 1\ncustom: 2\ncustom: 3');
});

test('countReset restarts default counter', () => {
_console.count();
_console.count();
_console.countReset();
_console.count();
expect(stdout()).toEqual('default: 1\ndefault: 2\ndefault: 1');
});

test('countReset restarts custom counter', () => {
_console.count('custom');
_console.count('custom');
_console.countReset('custom');
_console.count('custom');

expect(stdout()).toEqual('custom: 1\ncustom: 2\ncustom: 1');
});
});

describe('group', () => {
test('group without label', () => {
_console.group();
_console.log('hey');
_console.group();
_console.log('there');

expect(stdout()).toEqual(' hey\n there');
});

test('group with label', () => {
_console.group('first');
_console.log('hey');
_console.group('second');
_console.log('there');

expect(stdout()).toEqual(` ${chalk.bold('first')}
hey
${chalk.bold('second')}
there`);
});

test('groupEnd remove the indentation of the current group', () => {
_console.group();
_console.log('hey');
_console.groupEnd();
_console.log('there');

expect(stdout()).toEqual(' hey\nthere');
});

test('groupEnd can not remove the indentation below the starting point', () => {
_console.groupEnd();
_console.groupEnd();
_console.group();
_console.log('hey');
_console.groupEnd();
_console.log('there');

expect(stdout()).toEqual(' hey\nthere');
});
});

describe('time', () => {
test('should return the time between time() and timeEnd() on default timer', () => {
_console.time();
_console.timeEnd();

expect(stdout()).toMatch('default: ');
expect(stdout()).toMatch('ms');
});

test('should return the time between time() and timeEnd() on custom timer', () => {
_console.time('custom');
_console.timeEnd('custom');

expect(stdout()).toMatch('custom: ');
expect(stdout()).toMatch('ms');
});
});
});
Loading

0 comments on commit f29c03e

Please sign in to comment.