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

Concurrent reporter + Run failed tests first #1480

Merged
merged 6 commits into from
Sep 23, 2016
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Progress bar + printing cleanups.
  • Loading branch information
cpojer committed Sep 23, 2016
commit 07445b7144a026156b177173a1f9dc42f351da1d
50 changes: 43 additions & 7 deletions integration_tests/__tests__/__snapshots__/globals-test.js.snap
Original file line number Diff line number Diff line change
@@ -10,6 +10,25 @@ Test Summary
› Ran all tests."
`;

exports[`test basic test constructs 2`] = `
"Test Suites: 1 passed, 1 total
Tests: 4 passed, 4 total
Snapshots: 0 passed, 0 total
Time: <<REPLACED>>
Ran all tests.
"
`;

exports[`test global jest variables 2`] = `
"Test Summary: › Ran all tests.

suites: 1 passed (1 total)
tests: 4 passed (11 total)
snapshots: 0 passed (0 total)
time: <<REPLACED>>
"
`;

exports[`test only 1`] = `
" PASS __tests__/only-constructs-test.js
✓ test.only
@@ -28,6 +47,15 @@ Test Summary
› Ran all tests."
`;

exports[`test only 2`] = `
"Test Suites: 1 passed, 1 total
Tests: 7 passed, 8 total
Snapshots: 0 passed, 0 total
Time: <<REPLACED>>
Ran all tests.
"
`;

exports[`test skips 1`] = `
" PASS __tests__/skips-constructs-test.js
✓ it
@@ -47,6 +75,15 @@ Test Summary
› Ran all tests."
`;

exports[`test skips 2`] = `
"Test Suites: 1 passed, 1 total
Tests: 1 passed, 9 total
Snapshots: 0 passed, 0 total
Time: <<REPLACED>>
Ran all tests.
"
`;

exports[`test tests with no implementation 1`] = `
" PASS __tests__/only-constructs-test.js
✓ it
@@ -57,12 +94,11 @@ exports[`test tests with no implementation 1`] = `
"
`;

exports[`test global jest variables 2`] = `
"Test Summary: › Ran all tests.

suites: 1 passed (1 total)
tests: 4 passed (11 total)
snapshots: 0 passed (0 total)
time: <<REPLACED>>
exports[`test tests with no implementation 2`] = `
"Test Suites: 1 passed, 1 total
Tests: 1 passed, 3 total
Snapshots: 0 passed, 0 total
Time: <<REPLACED>>
Ran all tests.
"
`;
9 changes: 5 additions & 4 deletions integration_tests/utils.js
Original file line number Diff line number Diff line change
@@ -94,15 +94,16 @@ const extractSummary = stdout => {
`);
}

const summary = match[0]
.replace(/\d*\.?\d+m?s/g, '<<REPLACED>>')
.replace(/, estimated <<REPLACED>>/g, '');

const rest = stdout
.slice(0, -match[0].length)
// remove all timestamps
.replace(/\s*\(.*ms\)/gm, '');

return {
summary: match[0].replace(/\d*\.?\d+m?s/g, '<<REPLACED>>'),
rest,
};
return {summary, rest};
};

module.exports = {
1 change: 0 additions & 1 deletion packages/jest-cli/src/TestRunner.js
Original file line number Diff line number Diff line change
@@ -338,7 +338,6 @@ class TestRunner {
if (this._config.notify) {
this.addReporter(new NotifyReporter());
}

}

_bailIfNeeded(aggregatedResults: AggregatedResult) {
15 changes: 11 additions & 4 deletions packages/jest-cli/src/reporters/CoverageReporter.js
Original file line number Diff line number Diff line change
@@ -26,12 +26,15 @@ const {createReporter} = require('istanbul-api');
const chalk = require('chalk');
const fs = require('fs');
const generateEmptyCoverage = require('../generateEmptyCoverage');
const isCI = require('is-ci');
const istanbulCoverage = require('istanbul-lib-coverage');

const COVERAGE_SUMMARY = chalk.bold;
const FAIL_COLOR = chalk.bold.red;
const RUNNING_TEST_COLOR = chalk.bold.dim;

const isInteractive = process.stdout.isTTY && !isCI;

class CoverageReporter extends BaseReporter {
_coverageMap: CoverageMap;

@@ -93,9 +96,11 @@ class CoverageReporter extends BaseReporter {

_addUntestedFiles(config: Config, runnerContext: RunnerContext) {
if (config.collectCoverageFrom && config.collectCoverageFrom.length) {
process.stderr.write(RUNNING_TEST_COLOR(
'Running coverage on untested files...',
));
if (isInteractive) {
process.stderr.write(RUNNING_TEST_COLOR(
'Running coverage on untested files...',
));
}
const files = runnerContext.hasteFS.matchFilesWithGlob(
config.collectCoverageFrom,
config.rootDir,
@@ -118,7 +123,9 @@ class CoverageReporter extends BaseReporter {
}
}
});
this.clearLine();
if (isInteractive) {
this.clearLine();
}
}
}

18 changes: 12 additions & 6 deletions packages/jest-cli/src/reporters/DefaultReporter.js
Original file line number Diff line number Diff line change
@@ -24,17 +24,19 @@ const getConsoleOutput = require('./getConsoleOutput');
const getResultHeader = require('./getResultHeader');
const isCI = require('is-ci');

type write = (chunk: string, enc?: any, cb?: () => void) => boolean;

const TITLE_BULLET = chalk.bold('\u25cf ');

type write = (chunk: string, enc?: any, cb?: () => void) => boolean;
const isInteractive = process.stdin.isTTY && !isCI;

class DefaultReporter extends BaseReporter {
_out: write;
_err: write;
_clear: string; // ANSI clear sequence for the last printed status
_currentStatusHeight: number;
_currentlyRunning: Map<Path, Config>;
_currentStatusHeight: number;
_err: write;
_lastAggregatedResults: AggregatedResult;
_out: write;
_status: Status;

constructor() {
@@ -91,13 +93,17 @@ class DefaultReporter extends BaseReporter {
}

_clearStatus() {
process.stdin.isTTY && !isCI && this._out(this._clear);
if (isInteractive) {
this._out(this._clear);
}
}

_printStatus() {
const {content, clear} = this._status.get();
this._clear = clear;
process.stdin.isTTY && !isCI && this._out(content);
if (isInteractive) {
this._out(content);
}
}

onRunStart(
12 changes: 4 additions & 8 deletions packages/jest-cli/src/reporters/Status.js
Original file line number Diff line number Diff line change
@@ -151,18 +151,14 @@ class Status {
}

content += '\n';

let clear = '';
let height = 1;

for (let i = 0; i < content.length; i++) {
content[i] === '\n' && height++;
}

for (let i = 0; i < height - 1; i++) {
clear += '\r\x1B[K\r\x1B[1A';
if (content[i] === '\n') {
height++;
}
}

const clear = '\r\x1B[K\r\x1B[1A'.repeat(height - 1);
return this._cache = {content, clear};
}

14 changes: 5 additions & 9 deletions packages/jest-cli/src/reporters/SummaryReporter.js
Original file line number Diff line number Diff line change
@@ -79,22 +79,18 @@ class SummareReporter extends BaseReporter {
aggregatedResults: AggregatedResult,
runnerContext: RunnerContext,
) {
const totalTestSuites = aggregatedResults.numTotalTestSuites;
const snapshots = aggregatedResults.snapshot;

this._printSummary(aggregatedResults, config);
this._printSnapshotSummary(snapshots, config);

const results =
this._printSnapshotSummary(aggregatedResults.snapshot, config);
this.log(
'\n' +
(totalTestSuites
(aggregatedResults.numTotalTestSuites
? getSummary(aggregatedResults, {
estimatedTime: this._estimatedTime,
})
: ''
) +
'\n' + runnerContext.getTestSummary();
this.log(results);
'\n' + runnerContext.getTestSummary(),
);
}

_printSnapshotSummary(snapshots: SnapshotSummary, config: Config) {
10 changes: 4 additions & 6 deletions packages/jest-cli/src/reporters/VerboseReporter.js
Original file line number Diff line number Diff line change
@@ -22,9 +22,9 @@ const chalk = require('chalk');
const isWindows = process.platform === 'win32';

class VerboseReporter extends DefaultReporter {

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

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

@@ -41,7 +41,6 @@ class VerboseReporter extends DefaultReporter {

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

return root;
}

@@ -50,9 +49,7 @@ class VerboseReporter extends DefaultReporter {
testResult: TestResult,
aggregatedResults: AggregatedResult,
) {

this._status.testFinished(config, testResult, aggregatedResults);
this._printTestFileSummary(testResult.testFilePath, config, testResult);
super.onTestResult(config, testResult, aggregatedResults);
if (!testResult.testExecError) {
this._logTestResults(testResult.testResults);
}
@@ -92,8 +89,9 @@ class VerboseReporter extends DefaultReporter {

_logLine(str?: string, indentLevel?: number) {
const indentation = ' '.repeat(indentLevel || 0);
process.stderr.write(indentation + (str || '') + '\n');
this._write(indentation + (str || '') + '\n');
}

}

module.exports = VerboseReporter;
61 changes: 51 additions & 10 deletions packages/jest-cli/src/reporters/utils.js
Original file line number Diff line number Diff line change
@@ -23,6 +23,8 @@ type SummaryOptions = {
width?: number,
};

const PROGRESS_BAR_WIDTH = 40;

const formatTestPath = (config: Config, testPath: Path) => {
const {dirname, basename} = relativePath(config, testPath);
return chalk.gray(dirname + path.sep) + chalk.bold(basename);
@@ -48,18 +50,24 @@ const getSummary = (
}
const estimatedTime = (options && options.estimatedTime) || 0;
const snapshotResults = aggregatedResults.snapshot;
const width = (options && options.width) || 0;

let suites = chalk.bold('Test Suites: ');
const suitesFailed = aggregatedResults.numFailedTestSuites;
const suitesPassed = aggregatedResults.numPassedTestSuites;
const suitesRun = suitesFailed + suitesPassed;
const suitesTotal = aggregatedResults.numTotalTestSuites;

if (suitesFailed) {
suites += chalk.bold.red(`${suitesFailed} failed`) + ', ';
}

suites += chalk.bold.green(`${suitesPassed} passed`);
suites += ` (${suitesTotal} total)`;
suites +=
chalk.bold.green(`${suitesPassed} passed`) + ', ' +
(suitesRun !== suitesTotal
? suitesRun + '/' + suitesTotal
: suitesTotal
) + ` total`;

let tests = chalk.bold('Tests: ');
const testsPassed = aggregatedResults.numPassedTests;
@@ -70,8 +78,9 @@ const getSummary = (
tests += chalk.bold.red(`${testsFailed} failed`) + ', ';
}

tests += chalk.bold.green(`${testsPassed} passed`);
tests += ` (${testsTotal} total)`;
tests +=
chalk.bold.green(`${testsPassed} passed`) +
`, ${testsTotal} total`;

let snapshots = chalk.bold('Snapshots: ');
const snapshotsPassed = snapshotResults.matched;
@@ -92,15 +101,47 @@ const getSummary = (
snapshots += chalk.bold.green(`${snapshotsAdded} added`) + ', ';
}

snapshots += chalk.bold.green(`${snapshotsPassed} passed`);
snapshots += ` (${snapshotsTotal} total)`;
snapshots +=
chalk.bold.green(`${snapshotsPassed} passed`) +
`, ${snapshotsTotal} total`;

const time = renderTime(runTime, estimatedTime, width);
return [suites, tests, snapshots, time].join('\n');
};

let time = chalk.bold(`Time:`) + ` ${runTime}s`;
if (estimatedTime) {
time += ` (${estimatedTime}s estimated)`;
const renderTime = (
runTime,
estimatedTime,
width,
) => {
const renderedTime = (estimatedTime && runTime >= estimatedTime)
? chalk.bold.red(runTime + 's')
: runTime + 's';
let time = chalk.bold(`Time:`) + ` ${renderedTime}`;
if (runTime < estimatedTime) {
time += `, estimated ${estimatedTime}s`;
}

return [suites, tests, snapshots, time].join('\n');
// Only show a progress bar if the test run is actually going to take
// some time.
if (
estimatedTime > 2 &&
runTime < estimatedTime &&
width
) {
const availableWidth = Math.min(PROGRESS_BAR_WIDTH, width);
const length = Math.min(
Math.floor(runTime / estimatedTime * availableWidth),
availableWidth,
);
if (availableWidth >= 2) {
time +=
'\n' +
chalk.green.inverse(' ').repeat(length) +
chalk.white.inverse(' ').repeat(availableWidth - length);
}
}
return time;
};

// wrap a string that contains ANSI escape sequences. ANSI escape sequences