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

Flowify reporters in jest-cli #1147

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions interfaces/Process.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface Process {
stdout : stream$Writable | tty$WriteStream;
exit(code? : number) : void;
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hope this is a good convention. let me know otherwise :)

50 changes: 39 additions & 11 deletions packages/jest-cli/src/reporters/DefaultTestReporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,34 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
*/
'use strict';

import type {AggregatedResult, TestResult} from '../../../../types/TestResult';
import type {Config} from '../../../../types/Config';
import type {Process} from '../../../../interfaces/Process';

const chalk = require('chalk');
const formatFailureMessage = require('jest-util').formatFailureMessage;
const path = require('path');
const VerboseLogger = require('./VerboseLogger');

type SnapshotSummary = {
added: number,
didUpdate: boolean,
filesAdded: number,
filesRemoved: number,
filesUnmatched: number,
filesUpdated: number,
matched: number,
total: number,
unchecked: number,
unmatched: number,
updated: number,
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unsure if this is worth defining

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is awesome. Yes, it was very confusing.


// Explicitly reset for these messages since they can get written out in the
// middle of error logging (should have listened to Spengler and not crossed the
// streams).
Expand All @@ -34,23 +54,31 @@ const pluralize = (word, count) => `${count} ${word}${count === 1 ? '' : 's'}`;

class DefaultTestReporter {

constructor(customProcess) {
_config: Config;
_process: Process;
verboseLogger: VerboseLogger;

constructor(customProcess: Process) {
this._process = customProcess || process;
}

log(string) {
this._process.stdout.write(string + '\n');
log(str: string) {
this._process.stdout.write(str + '\n');
}

onRunStart(config, results) {
onRunStart(config: Config, results: AggregatedResult) {
this._config = config;
this._printWaitingOn(results);
if (this._config.verbose) {
this.verboseLogger = new VerboseLogger(this._process);
}
}

onTestResult(config, testResult, results) {
onTestResult(
config: Config,
testResult: TestResult,
results: AggregatedResult
) {
this._clearWaitingOn();

const pathStr =
Expand Down Expand Up @@ -105,7 +133,7 @@ class DefaultTestReporter {
this._printWaitingOn(results);
}

onRunComplete(config, aggregatedResults) {
onRunComplete(config: Config, aggregatedResults: AggregatedResult) {
const totalTestSuites = aggregatedResults.numTotalTestSuites;
const failedTests = aggregatedResults.numFailedTests;
const passedTests = aggregatedResults.numPassedTests;
Expand All @@ -118,7 +146,7 @@ class DefaultTestReporter {
return true;
}

const snapshots = this._getSnapshotSummary(aggregatedResults);
const snapshots: SnapshotSummary = this._getSnapshotSummary(aggregatedResults);
const snapshotFailure = !!(!snapshots.didUpdate && (
snapshots.unchecked ||
snapshots.unmatched ||
Expand Down Expand Up @@ -158,7 +186,7 @@ class DefaultTestReporter {
return snapshotFailure ? false : aggregatedResults.success;
}

_getSnapshotSummary(aggregatedResults) {
_getSnapshotSummary(aggregatedResults: AggregatedResult) {
let added = 0;
let filesAdded = 0;
let filesRemoved = aggregatedResults.snapshotFilesRemoved;
Expand Down Expand Up @@ -204,7 +232,7 @@ class DefaultTestReporter {
};
}

_printSnapshotSummary(snapshots) {
_printSnapshotSummary(snapshots: SnapshotSummary) {
if (
snapshots.added ||
snapshots.filesRemoved ||
Expand Down Expand Up @@ -265,7 +293,7 @@ class DefaultTestReporter {
}
}

_printSummary(aggregatedResults) {
_printSummary(aggregatedResults: AggregatedResult) {
// If there were any failing tests and there was a large number of tests
// executed, re-print the failing results at the end of execution output.
const failedTests = aggregatedResults.numFailedTests;
Expand Down Expand Up @@ -305,7 +333,7 @@ class DefaultTestReporter {
this._process.stdout.write(this._config.noHighlight ? '' : '\r\x1B[K');
}

_printWaitingOn(results) {
_printWaitingOn(results: AggregatedResult) {
const remaining = results.numTotalTestSuites -
results.numPassedTestSuites -
results.numFailedTestSuites -
Expand Down
9 changes: 7 additions & 2 deletions packages/jest-cli/src/reporters/IstanbulTestReporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
*/
'use strict';

Expand All @@ -16,8 +18,11 @@ const reporter = new istanbul.Reporter();

const FAIL_COLOR = chalk.bold.red;

import type {Config} from '../../../../types/Config';
import type {AggregatedResult, TestResult} from '../../../../types/TestResult';

class IstanbulTestReporter extends DefaultTestReporter {
onTestResult(config, testResult, aggregatedResults) {
onTestResult(config: Config, testResult: TestResult, aggregatedResults: AggregatedResult) {
super.onTestResult(config, testResult, aggregatedResults);

if (config.collectCoverage && testResult.coverage) {
Expand All @@ -29,7 +34,7 @@ class IstanbulTestReporter extends DefaultTestReporter {
}
}

onRunComplete(config, aggregatedResults) {
onRunComplete(config: Config, aggregatedResults: AggregatedResult) {
aggregatedResults.success = super.onRunComplete(config, aggregatedResults);

if (config.collectCoverage) {
Expand Down
80 changes: 46 additions & 34 deletions packages/jest-cli/src/reporters/VerboseLogger.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,64 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
*/
'use strict';

import type {
AggregatedResult,
AssertionResult,
Suite,
TestResult,
} from '../../../../types/TestResult';
import type {Process} from '../../../../interfaces/Process';

const chalk = require('chalk');

class VerboseLogger {
constructor(customProcess) {
_process: Process;

static groupTestsBySuites(testResults: Array<AssertionResult>) {
const root: Suite = {
suites: [],
tests: [],
title: 'Root Suite',
};

testResults.forEach(testResult => {
let targetSuite = root;

// Find the target suite for this test,
// creating nested suites as necessary.
for (const title of testResult.ancestorTitles) {
let matchingSuite = targetSuite.suites.find(s => s.title === title);
if (!matchingSuite) {
matchingSuite = {title, suites: [], tests: []};
targetSuite.suites.push(matchingSuite);
}
targetSuite = matchingSuite;
}

targetSuite.tests.push(testResult);
});

return root.suites;
};

constructor(customProcess: Process) {
this._process = customProcess || process;
}

logTestResults(testResults) {
groupTestsBySuites(testResults).forEach(suite =>
logTestResults(testResults: Array<AssertionResult>) {
VerboseLogger.groupTestsBySuites(testResults).forEach(suite =>
this._logSuite(suite, 0)
);

this._logLine();
}

_logSuite(suite, indentLevel) {
_logSuite(suite: Suite, indentLevel: number) {
this._logLine(suite.title, indentLevel);

suite.tests.forEach(test =>
Expand All @@ -34,7 +73,7 @@ class VerboseLogger {
);
}

_getIcon(status) {
_getIcon(status: string) {
if (status === 'failed') {
return chalk.red('\u2715');
} else if (status === 'pending') {
Expand All @@ -44,42 +83,15 @@ class VerboseLogger {
}
}

_logTest(test, indentLevel) {
_logTest(test: AssertionResult, indentLevel: number) {
const status = this._getIcon(test.status);
this._logLine(`${status} ${chalk.gray(test.title)}`, indentLevel);
}

_logLine(str, indentLevel) {
str = str || '';
indentLevel = indentLevel || 0;

_logLine(str: string = '', indentLevel: number = 0) {
const indentation = ' '.repeat(indentLevel);
this._process.stdout.write(`${indentation}${str}\n`);
}
}

function groupTestsBySuites(testResults) {
const root = {suites: []};

testResults.forEach(testResult => {
let targetSuite = root;

// Find the target suite for this test,
// creating nested suites as necessary.
for (const title of testResult.ancestorTitles) {
let matchingSuite = targetSuite.suites.find(s => s.title === title);
if (!matchingSuite) {
matchingSuite = {title, suites: [], tests: []};
targetSuite.suites.push(matchingSuite);
}
targetSuite = matchingSuite;
}

targetSuite.tests.push(testResult);
});

return root.suites;
}

VerboseLogger.groupTestsBySuites = groupTestsBySuites;
module.exports = VerboseLogger;
5 changes: 5 additions & 0 deletions types/Config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export type Config = {
colors: boolean,
coverageCollector: Path,
coverageReporters: Array<string>,
coverageThreshold: {
global: {
[key: string]: number
}
},
globals: ConfigGlobals,
haste: HasteConfig,
mocksPattern: string,
Expand Down
23 changes: 23 additions & 0 deletions types/TestResult.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,32 @@ export type AssertionResult = {
numPassingAsserts: number,
};

export type AggregatedResult = {
didUpdate: boolean,
numFailedTests: number,
numFailedTestSuites: number,
numPassedTests: number,
numPassedTestSuites: number,
numPendingTests: number,
numRuntimeErrorTestSuites: number,
numTotalTests: number,
numTotalTestSuites: number,
snapshotFilesRemoved: number,
startTime: number,
success: boolean,
testResults: Array<TestResult>,
};

export type Suite = {
title: string,
suites: Array<Suite>,
tests: Array<AssertionResult>,
};

export type TestResult = {
coverage: ?Coverage,
hasUncheckedKeys: boolean,
message: string,
numFailingTests: number,
numPassingTests: number,
numPendingTests: number,
Expand Down