diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f43bc722dd2..907bf592e760 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Fixes +* `[jest-cli]` Hide interactive mode if there are no failed snapshot tests ([#5450](https://github.com/facebook/jest/pull/5450)) * `[babel-jest]` Remove retainLines from babel-jest ([#5326](https://github.com/facebook/jest/pull/5439)) * `[jest-cli]` Glob patterns ignore non-`require`-able files (e.g. `README.md`) @@ -25,7 +26,7 @@ * `[expect]` Make `rejects` and `resolves` synchronously validate its argument. ([#5364](https://github.com/facebook/jest/pull/5364)) * `[docs]` Add tutorial page for ES6 class mocks. - ([#5383]https://github.com/facebook/jest/pull/5383)) + ([#5383](https://github.com/facebook/jest/pull/5383)) * `[jest-resolve]` Search required modules in node_modules and then in custom paths. ([#5403](https://github.com/facebook/jest/pull/5403)) * `[jest-resolve]` Get builtin modules from node core. diff --git a/packages/jest-cli/src/__tests__/__snapshots__/watch.test.js.snap b/packages/jest-cli/src/__tests__/__snapshots__/watch.test.js.snap index 73a5abba0eb3..fc19800cbe6b 100644 --- a/packages/jest-cli/src/__tests__/__snapshots__/watch.test.js.snap +++ b/packages/jest-cli/src/__tests__/__snapshots__/watch.test.js.snap @@ -38,3 +38,38 @@ Watch Usage ], ] `; + +exports[`Watch mode flows shows update snapshot prompt (with interactive) 1`] = ` +Array [ + Array [ + " +Watch Usage + › Press a to run all tests. + › Press f to run only failed tests. + › Press u to update failing snapshots. + › Press i to update failing snapshots interactively. + › Press p to filter by a filename regex pattern. + › Press t to filter by a test name regex pattern. + › Press q to quit watch mode. + › Press Enter to trigger a test run. +", + ], +] +`; + +exports[`Watch mode flows shows update snapshot prompt (without interactive) 1`] = ` +Array [ + Array [ + " +Watch Usage + › Press a to run all tests. + › Press f to run only failed tests. + › Press u to update failing snapshots. + › Press p to filter by a filename regex pattern. + › Press t to filter by a test name regex pattern. + › Press q to quit watch mode. + › Press Enter to trigger a test run. +", + ], +] +`; diff --git a/packages/jest-cli/src/__tests__/watch.test.js b/packages/jest-cli/src/__tests__/watch.test.js index 56e4aea3bce7..99f994077470 100644 --- a/packages/jest-cli/src/__tests__/watch.test.js +++ b/packages/jest-cli/src/__tests__/watch.test.js @@ -13,9 +13,9 @@ import TestWatcher from '../test_watcher'; import {KEYS} from '../constants'; const runJestMock = jest.fn(); - const watchPluginPath = `${__dirname}/__fixtures__/watch_plugin`; const watchPlugin2Path = `${__dirname}/__fixtures__/watch_plugin2`; +let results; jest.doMock('chalk', () => new chalk.constructor({enabled: false})); jest.doMock( @@ -27,7 +27,7 @@ jest.doMock( runJestMock.apply(null, args); // Call the callback - onComplete({snapshot: {}}); + onComplete(results); return Promise.resolve(); }, @@ -70,6 +70,7 @@ describe('Watch mode flows', () => { hasteMapInstances = [{on: () => {}}]; contexts = [{config}]; stdin = new MockStdin(); + results = {snapshot: {}}; }); it('Correctly passing test path pattern', () => { @@ -175,6 +176,61 @@ describe('Watch mode flows', () => { expect(pipeMockCalls.slice(determiningTestsToRun + 1)).toMatchSnapshot(); }); + it('shows update snapshot prompt (without interactive)', async () => { + jest.unmock('jest-util'); + const util = require('jest-util'); + util.isInteractive = true; + results = {snapshot: {failure: true}}; + + const ci_watch = require('../watch').default; + ci_watch( + Object.assign({}, globalConfig, { + rootDir: __dirname, + watchPlugins: [], + }), + contexts, + pipe, + hasteMapInstances, + stdin, + ); + + const pipeMockCalls = pipe.write.mock.calls; + + const determiningTestsToRun = pipeMockCalls.findIndex( + ([c]) => c === 'Determining test suites to run...', + ); + + expect(pipeMockCalls.slice(determiningTestsToRun + 1)).toMatchSnapshot(); + }); + + it('shows update snapshot prompt (with interactive)', async () => { + jest.unmock('jest-util'); + const util = require('jest-util'); + util.isInteractive = true; + util.getFailedSnapshotTests = jest.fn(() => ['test.js']); + results = {snapshot: {failure: true}}; + + const ci_watch = require('../watch').default; + ci_watch( + Object.assign({}, globalConfig, { + rootDir: __dirname, + watchPlugins: [], + }), + contexts, + pipe, + hasteMapInstances, + stdin, + ); + + const pipeMockCalls = pipe.write.mock.calls; + + const determiningTestsToRun = pipeMockCalls.findIndex( + ([c]) => c === 'Determining test suites to run...', + ); + + expect(pipeMockCalls.slice(determiningTestsToRun + 1)).toMatchSnapshot(); + }); + it('triggers enter on a WatchPlugin when its key is pressed', () => { const plugin = require(watchPluginPath); diff --git a/packages/jest-cli/src/watch.js b/packages/jest-cli/src/watch.js index d0e09c4c9d45..027fc8ab79a2 100644 --- a/packages/jest-cli/src/watch.js +++ b/packages/jest-cli/src/watch.js @@ -69,6 +69,7 @@ export default function watch( searchSource: new SearchSource(context), })); let hasSnapshotFailure = false; + let hasSnapshotFailureInteractive = false; let isRunning = false; let testWatcher; let shouldDisplayWatchUsage = true; @@ -130,8 +131,9 @@ export default function watch( globalConfig, onComplete: results => { isRunning = false; - hasSnapshotFailure = !!results.snapshot.failure; failedSnapshotTestPaths = getFailedSnapshotTests(results); + hasSnapshotFailure = !!results.snapshot.failure; + hasSnapshotFailureInteractive = failedSnapshotTestPaths.length > 0; // Create a new testWatcher instance so that re-runs won't be blocked. // The old instance that was passed to Jest will still be interrupted @@ -149,7 +151,12 @@ export default function watch( } if (shouldDisplayWatchUsage) { outputStream.write( - usage(globalConfig, watchPlugins, hasSnapshotFailure), + usage( + globalConfig, + watchPlugins, + hasSnapshotFailure, + hasSnapshotFailureInteractive, + ), ); shouldDisplayWatchUsage = false; // hide Watch Usage after first run isWatchUsageDisplayed = true; @@ -327,7 +334,12 @@ export default function watch( outputStream.write(ansiEscapes.cursorUp()); outputStream.write(ansiEscapes.eraseDown); outputStream.write( - usage(globalConfig, watchPlugins, hasSnapshotFailure), + usage( + globalConfig, + watchPlugins, + hasSnapshotFailure, + hasSnapshotFailureInteractive, + ), ); isWatchUsageDisplayed = true; shouldDisplayWatchUsage = false; @@ -339,7 +351,14 @@ export default function watch( const onCancelPatternPrompt = () => { outputStream.write(ansiEscapes.cursorHide); outputStream.write(ansiEscapes.clearScreen); - outputStream.write(usage(globalConfig, watchPlugins, hasSnapshotFailure)); + outputStream.write( + usage( + globalConfig, + watchPlugins, + hasSnapshotFailure, + hasSnapshotFailureInteractive, + ), + ); outputStream.write(ansiEscapes.cursorShow); }; @@ -380,6 +399,7 @@ const usage = ( globalConfig, watchPlugins: WatchPluginRegistry, snapshotFailure, + snapshotFailureInteractive, delimiter = '\n', ) => { const messages = [ @@ -415,7 +435,7 @@ const usage = ( chalk.dim(' to update failing snapshots.') : null, - snapshotFailure + snapshotFailureInteractive ? chalk.dim(' \u203A Press ') + 'i' + chalk.dim(' to update failing snapshots interactively.')