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 #2 #1151

Merged
merged 2 commits into from
Jun 15, 2016
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
bin/
docs/
**/coverage/**
**/node_modules/**
**/vendor/**
website/
**/coverage/**
bin/
docs/
packages/*/build/**
types/**
website/
48 changes: 38 additions & 10 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 'types/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,
};

// 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(message: string) {
this._process.stdout.write(message + '\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 Down Expand Up @@ -158,7 +186,7 @@ class DefaultTestReporter {
return snapshotFailure ? false : aggregatedResults.success;
}

_getSnapshotSummary(aggregatedResults) {
_getSnapshotSummary(aggregatedResults: AggregatedResult): SnapshotSummary {
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
13 changes: 11 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,15 @@ 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 +38,7 @@ class IstanbulTestReporter extends DefaultTestReporter {
}
}

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

if (config.collectCoverage) {
Expand Down
78 changes: 44 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,62 @@
* 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 {
AssertionResult,
Suite,
} from 'types/TestResult';
import type {Process} from 'types/Process';

const chalk = require('chalk');

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

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

logTestResults(testResults) {
groupTestsBySuites(testResults).forEach(suite =>
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;
}

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 +71,7 @@ class VerboseLogger {
);
}

_getIcon(status) {
_getIcon(status: string) {
if (status === 'failed') {
return chalk.red('\u2715');
} else if (status === 'pending') {
Expand All @@ -44,42 +81,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;
6 changes: 5 additions & 1 deletion packages/jest-snapshot/src/SnapshotFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export type MatchResult = {
pass: boolean,
};

type SnapshotData = {[key: string]: string};

type SaveStatus = {
deleted: boolean,
saved: boolean,
Expand All @@ -47,7 +49,7 @@ const fileExists = (filePath: Path): boolean => {

class SnapshotFile {

_content: {[key: string]: any};
_content: SnapshotData;
_dirty: boolean;
_filename: Path;
_uncheckedKeys: Set;
Expand All @@ -59,7 +61,9 @@ class SnapshotFile {
this._content = Object.create(null);
if (this.fileExists(filename)) {
try {
/* eslint-disable no-useless-call */
Object.assign(this._content, require.call(null, filename));
/* eslint-enable no-useless-call */
} catch (e) {}
}
this._uncheckedKeys = new Set(Object.keys(this._content));
Expand Down
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
4 changes: 4 additions & 0 deletions types/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;
};
23 changes: 23 additions & 0 deletions types/TestResult.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,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