diff --git a/integration_tests/utils.js b/integration_tests/utils.js index 66646a1a7f1a..8f989015d7ca 100644 --- a/integration_tests/utils.js +++ b/integration_tests/utils.js @@ -94,15 +94,16 @@ const extractSummary = stdout => { `); } + const summary = match[0] + .replace(/\d*\.?\d+m?s/g, '<>') + .replace(/, estimated <>/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, '<>'), - rest, - }; + return {summary, rest}; }; module.exports = { diff --git a/packages/jest-cli/src/reporters/CoverageReporter.js b/packages/jest-cli/src/reporters/CoverageReporter.js index e5994463f751..e1d14435db06 100644 --- a/packages/jest-cli/src/reporters/CoverageReporter.js +++ b/packages/jest-cli/src/reporters/CoverageReporter.js @@ -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(); + } } } diff --git a/packages/jest-cli/src/reporters/VerboseReporter.js b/packages/jest-cli/src/reporters/VerboseReporter.js index 21d5ef2098c1..64c5db817fe8 100644 --- a/packages/jest-cli/src/reporters/VerboseReporter.js +++ b/packages/jest-cli/src/reporters/VerboseReporter.js @@ -92,7 +92,7 @@ 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'); } } diff --git a/packages/jest-cli/src/reporters/utils.js b/packages/jest-cli/src/reporters/utils.js index 8f355e994308..0c0b94084fb0 100644 --- a/packages/jest-cli/src/reporters/utils.js +++ b/packages/jest-cli/src/reporters/utils.js @@ -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