Skip to content

Commit

Permalink
feat: add log level to reporter logs
Browse files Browse the repository at this point in the history
  • Loading branch information
carpasse committed Nov 2, 2017
1 parent 18045ee commit 31f1c87
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 44 deletions.
35 changes: 18 additions & 17 deletions src/TapReporter.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,41 @@
/* eslint-disable id-match, class-methods-use-this, no-console */
const chalk = require('chalk');
const ms = require('ms');
const Logger = require('./helpers/Logger');

class TapReporter {
constructor (globalConfig = {}, options = {}) {
const {logLevel = 'INFO'} = options;

this._globalConfig = globalConfig;
this._options = options;
this._shouldFail = false;
this.logger = new Logger({
logLevel
});

console.log('\n\nStarting ...\n');
this.logger.log('\n\n# Starting ...\n');
}

onTestResult (contexts, {testResults}) {
const text = [];

testResults.forEach((test, idx) => {
if (test.status === 'passed') {
text.push(`${chalk.green('ok')} ${idx + 1} ${test.title}`);
this.logger.log(`${chalk.green('ok')} ${idx + 1} ${test.title}`);
} else if (test.status === 'failed') {
text.push(`${chalk.red('not ok')} ${idx + 1} ${test.title}`);
this.logger.log(`${chalk.red('not ok')} ${idx + 1} ${test.title}`);

if (test.failureMessages.length > 0) {
const diagnostics = test.failureMessages
.reduce((lines, msg) => lines.concat(msg.split('\n')), [])
.map((line) => chalk.grey(`# ${line}`))
.join('\n');

text.push(diagnostics);
this.logger.error(diagnostics);
}
} else if (test.status === 'pending') {
text.push(`${chalk.yellow('ok')} ${idx + 1} ${test.title} ${chalk.yellow('# SKIP')}`);
this.logger.log(`${chalk.yellow('ok')} ${idx + 1} ${test.title} ${chalk.yellow('# SKIP')}`);
}
});

console.log(text.join('\n'));
}

onRunComplete (contexts, results) {
Expand All @@ -50,25 +52,24 @@ class TapReporter {
} = results;
const skippedTestSuites = numPendingTestSuites > 0 ? `${chalk.yellow(`${numPendingTestSuites} skipped`)}, ` : '';
const skippedTests = numPendingTests > 0 ? `${chalk.yellow(`${numPendingTests} skipped`)}, ` : '';
const text = [];

this._shouldFail = numFailedTestSuites > 0 || numFailedTests > 0;

this.logger.info('\n');
if (numFailedTestSuites > 0) {
text.push(`# testSuites: ${skippedTestSuites}${chalk.red(`${numFailedTestSuites} failed`)}, ${numTotalTestSuites} total`);
this.logger.info(`# testSuites: ${skippedTestSuites}${chalk.red(`${numFailedTestSuites} failed`)}, ${numTotalTestSuites} total`);
} else {
text.push(`# testSuites: ${skippedTestSuites}${chalk.green(`${numPassedTestSuites} passed`)}, ${numTotalTestSuites} total`);
this.logger.info(`# testSuites: ${skippedTestSuites}${chalk.green(`${numPassedTestSuites} passed`)}, ${numTotalTestSuites} total`);
}

if (numFailedTests > 0) {
text.push(`# tests: ${skippedTests}${chalk.red(`${numFailedTests} failed`)}, ${numTotalTests} total`);
this.logger.info(`# tests: ${skippedTests}${chalk.red(`${numFailedTests} failed`)}, ${numTotalTests} total`);
} else {
text.push(`# tests: ${skippedTests}${chalk.green(`${numPassedTests} passed`)}, ${numTotalTests} total`);
this.logger.info(`# tests: ${skippedTests}${chalk.green(`${numPassedTests} passed`)}, ${numTotalTests} total`);
}

text.push(`# time: ${ms(Date.now() - startTime)}`);

console.log(`\n${text.join('\n')}\n`);
this.logger.info(`# time: ${ms(Date.now() - startTime)}`);
this.logger.info('\n');
}

getLastError () {
Expand Down
54 changes: 54 additions & 0 deletions src/helpers/Logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/* eslint-disable sort-keys */
const LEVELS = {
ERROR: 1,
WARN: 2,
INFO: 3
};
/* eslint-enable sort-keys */

// eslint-disable-next-line no-console
const DEFAULT_LOG = (...args) => console.log(...args);
const level = Symbol('level');

class Logger {
constructor ({log = DEFAULT_LOG, logLevel} = {}) {
this.log = log;
this.setLevel(logLevel || 'INFO');
}

setLevel (newLevel) {
if (typeof LEVELS[newLevel] === 'undefined') {
throw new TypeError('Unknown level');
}

this[level] = LEVELS[newLevel];
}

getLevel () {
return Object.keys(LEVELS).filter((key) => LEVELS[key] === this[level])[0];
}

info (...args) {
if (this[level] >= LEVELS.INFO) {
this.log(...args);
}
}

warn (...args) {
if (this[level] >= LEVELS.WARN) {
this.log(...args);
}
}

error (...args) {
if (this[level] >= LEVELS.ERROR) {
this.log(...args);
}
}

log (...args) {
this.log(...args);
}
}

module.exports = Logger;
45 changes: 18 additions & 27 deletions test/TapReporter.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ test('TapReporter must log the start of the tests', () => {
const tapReporter = new TapReporter();

expect(console.log).toHaveBeenCalledTimes(1);
expect(console.log).toHaveBeenCalledWith('\n\nStarting ...\n');
expect(console.log).toHaveBeenCalledWith('\n\n# Starting ...\n');
});

test('TapReporter onTestResults must output error tests', () => {
Expand All @@ -104,16 +104,17 @@ test('TapReporter onTestResults must output error tests', () => {

tapReporter.onTestResult({}, failingTestSuite);

expect(console.log).toHaveBeenCalledTimes(1);

const {
description,
diagnostics,
directive,
status,
testNumber
} = processTestLine(console.log.mock.calls[0][0]);

const {
diagnostics
} = processTestLine(console.log.mock.calls[1][0]);

expect(status).toBe('not ok');
expect(testNumber).toBe('1');
expect(description).not.toBe(string.notEmpty);
Expand Down Expand Up @@ -180,9 +181,7 @@ test('TapReporter onTestResults must output all the tests on a suite tests', ()

tapReporter.onTestResult({}, severalTestsSuite);

expect(console.log).toHaveBeenCalledTimes(1);

const testLines = console.log.mock.calls[0][0].split('\n');
const testLines = console.log.mock.calls.map((call) => call[0]);

testLines.forEach((testLine, idx) => {
const {
Expand Down Expand Up @@ -251,11 +250,9 @@ test('TapReporter onRunComplete all suites and tests pass', () => {

tapReporter.onRunComplete({}, results);

expect(console.log).toHaveBeenCalledWith(`
# testSuites: 2 passed, 2 total
# tests: 10 passed, 10 total
# time: 2s
`);
expect(console.log).toHaveBeenCalledWith('# testSuites: 2 passed, 2 total');
expect(console.log).toHaveBeenCalledWith('# tests: 10 passed, 10 total');
expect(console.log).toHaveBeenCalledWith('# time: 2s');
});

test('TapReporter onRunComplete some suites and tests fail', () => {
Expand All @@ -274,11 +271,9 @@ test('TapReporter onRunComplete some suites and tests fail', () => {

tapReporter.onRunComplete({}, results);

expect(console.log).toHaveBeenCalledWith(`
# testSuites: 1 failed, 2 total
# tests: 1 failed, 10 total
# time: 2s
`);
expect(console.log).toHaveBeenCalledWith('# testSuites: 1 failed, 2 total');
expect(console.log).toHaveBeenCalledWith('# tests: 1 failed, 10 total');
expect(console.log).toHaveBeenCalledWith('# time: 2s');
});

test('TapReporter onRunComplete 1 suite failed to execute', () => {
Expand All @@ -297,11 +292,9 @@ test('TapReporter onRunComplete 1 suite failed to execute', () => {

tapReporter.onRunComplete({}, results);

expect(console.log).toHaveBeenCalledWith(`
# testSuites: 1 failed, 2 total
# tests: 10 passed, 10 total
# time: 2s
`);
expect(console.log).toHaveBeenCalledWith('# testSuites: 1 failed, 2 total');
expect(console.log).toHaveBeenCalledWith('# tests: 10 passed, 10 total');
expect(console.log).toHaveBeenCalledWith('# time: 2s');
});

test('TapReporter onRunComplete some suites and tests skipped', () => {
Expand All @@ -320,11 +313,9 @@ test('TapReporter onRunComplete some suites and tests skipped', () => {

tapReporter.onRunComplete({}, results);

expect(console.log).toHaveBeenCalledWith(`
# testSuites: 1 skipped, 1 passed, 2 total
# tests: 5 skipped, 5 passed, 10 total
# time: 2s
`);
expect(console.log).toHaveBeenCalledWith('# testSuites: 1 skipped, 1 passed, 2 total');
expect(console.log).toHaveBeenCalledWith('# tests: 5 skipped, 5 passed, 10 total');
expect(console.log).toHaveBeenCalledWith('# time: 2s');
});

test('TapReporter getLastError must return an error the run should fail and undefined otherwise', () => {
Expand Down
144 changes: 144 additions & 0 deletions test/helpers/Logger.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
const Logger = require('../../src/helpers/Logger');

test('Logger must set the INFO as the default level', () => {
const logger = new Logger();

expect(logger.getLevel()).toBe('INFO');
});

/* eslint-disable no-console */
test('Logger must use console.log as default log function', () => {
const realLog = console.log;

console.log = jest.fn();
const logger = new Logger();

logger.log('foo', 'bar');

expect(console.log).toHaveBeenCalledTimes(1);
expect(console.log).toHaveBeenCalledWith('foo', 'bar');

console.log = realLog;
});
/* eslint-enable no-console */

test('Logger must be possible to pass a log function', () => {
const log = jest.fn();
const logger = new Logger({log});

logger.log('foo', 'bar');

expect(log).toHaveBeenCalledTimes(1);
expect(log).toHaveBeenCalledWith('foo', 'bar');
});

test('Logger must be possible to pass a default log level', () => {
const config = {
logLevel: 'ERROR'
};
const logger = new Logger(config);

expect(logger.getLevel()).toBe('ERROR');
});

test('Logger must be possible to change the log level', () => {
const logger = new Logger();

expect(logger.getLevel()).toBe('INFO');
logger.setLevel('ERROR');
expect(logger.getLevel()).toBe('ERROR');
logger.setLevel('WARN');
expect(logger.getLevel()).toBe('WARN');
});

test('Logger must throw if you try to change the level with an unknown one', () => {
const logger = new Logger();

expect(() => logger.setLevel('asfasdfsadf')).toThrow(TypeError);
expect(() => logger.setLevel(23423)).toThrow(TypeError);
expect(() => logger.setLevel()).toThrow(TypeError);
});

test('logger warn log must log no matter the log level', () => {
const log = jest.fn();
const logger = new Logger({
log,
logLevel: 'INFO'
});

logger.log('INFO');
expect(log).toHaveBeenCalledWith('INFO');

logger.setLevel('WARN');
logger.log('WARN');
expect(log).toHaveBeenCalledWith('WARN');

logger.setLevel('ERROR');
logger.log('ERROR');
expect(log).toHaveBeenCalledWith('ERROR');

expect(log).toHaveBeenCalledTimes(3);
});

test('logger info must log if log level is INFO', () => {
const log = jest.fn();
const logger = new Logger({
log,
logLevel: 'ERROR'
});

logger.info('test');
expect(log).not.toHaveBeenCalled();

logger.setLevel('WARN');
logger.info('test');
expect(log).not.toHaveBeenCalled();

logger.setLevel('INFO');
logger.info('test');
expect(log).toHaveBeenCalledWith('test');

expect(log).toHaveBeenCalledTimes(1);
});

test('logger WARN must log if log level is INFO or WARN', () => {
const log = jest.fn();
const logger = new Logger({
log,
logLevel: 'ERROR'
});

logger.warn('test');
expect(log).not.toHaveBeenCalled();

logger.setLevel('WARN');
logger.warn('test');
expect(log).toHaveBeenCalledWith('test');

logger.setLevel('INFO');
logger.warn('test2');
expect(log).toHaveBeenCalledWith('test2');

expect(log).toHaveBeenCalledTimes(2);
});

test('logger ERROR must log if log level is INFO or WARN or ERROR', () => {
const log = jest.fn();
const logger = new Logger({
log,
logLevel: 'ERROR'
});

logger.error('test');
expect(log).toHaveBeenCalledWith('test');

logger.setLevel('WARN');
logger.error('test2');
expect(log).toHaveBeenCalledWith('test2');

logger.setLevel('INFO');
logger.error('test3');
expect(log).toHaveBeenCalledWith('test3');

expect(log).toHaveBeenCalledTimes(3);
});

0 comments on commit 31f1c87

Please sign in to comment.