From 947805ed9e9e070686f0817c1417a562914fa3ad Mon Sep 17 00:00:00 2001 From: Thomas Genin Date: Sat, 10 Jun 2017 00:12:34 -0700 Subject: [PATCH 01/12] Prototype Interactive Snapshot updates --- packages/jest-cli/src/constants.js | 2 + packages/jest-cli/src/watch.js | 88 +++++++++++++++++-- .../src/get_failed_snapshot_tests.js | 25 ++++++ packages/jest-util/src/index.js | 2 + 4 files changed, 108 insertions(+), 9 deletions(-) create mode 100644 packages/jest-util/src/get_failed_snapshot_tests.js diff --git a/packages/jest-cli/src/constants.js b/packages/jest-cli/src/constants.js index 36088a43b505..3efa5e4fd6ef 100644 --- a/packages/jest-cli/src/constants.js +++ b/packages/jest-cli/src/constants.js @@ -24,10 +24,12 @@ const KEYS = { CONTROL_D: '04', ENTER: '0d', ESCAPE: '1b', + I: '69', O: '6f', P: '70', Q: '71', QUESTION_MARK: '3f', + S: '73', T: '74', U: '75', W: '77', diff --git a/packages/jest-cli/src/watch.js b/packages/jest-cli/src/watch.js index 26a9156e78b6..29d3aa75ab40 100644 --- a/packages/jest-cli/src/watch.js +++ b/packages/jest-cli/src/watch.js @@ -15,6 +15,7 @@ import type {Context} from 'types/Context'; import ansiEscapes from 'ansi-escapes'; import chalk from 'chalk'; import {replacePathSepForRegex} from 'jest-regex-util'; +import {getFailedSnapshotTests} from 'jest-util'; import HasteMap from 'jest-haste-map'; import isCI from 'is-ci'; import isValidPath from './lib/isValidPath'; @@ -48,6 +49,10 @@ const watch = ( const prompt = new Prompt(); const testPathPatternPrompt = new TestPathPatternPrompt(pipe, prompt); const testNamePatternPrompt = new TestNamePatternPrompt(pipe, prompt); + + let failedSnapshotTestPaths = []; + let snapshotInteractiveMode = false; + let searchSources = contexts.map(context => ({ context, searchSource: new SearchSource(context), @@ -126,12 +131,17 @@ const watch = ( results => { isRunning = false; hasSnapshotFailure = !!results.snapshot.failure; + + if (hasSnapshotFailure && !snapshotInteractiveMode) { + failedSnapshotTestPaths = getFailedSnapshotTests(results); + } + // 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 // and prevent test runs from the previous run. testWatcher = new TestWatcher({isWatchMode: true}); if (shouldDisplayWatchUsage) { - pipe.write(usage(argv, hasSnapshotFailure)); + pipe.write(usage(argv, hasSnapshotFailure, snapshotInteractiveMode)); shouldDisplayWatchUsage = false; // hide Watch Usage after first run isWatchUsageDisplayed = true; } else { @@ -141,6 +151,11 @@ const watch = ( } testNamePatternPrompt.updateCachedTestResults(results.testResults); + + if (!hasSnapshotFailure && snapshotInteractiveMode) { + failedSnapshotTestPaths.shift(); + updateSnapshotInteractiveTarget(); + } }, ).catch(error => console.error(chalk.red(error.stack))); }; @@ -175,8 +190,16 @@ const watch = ( break; case KEYS.U: startRun({updateSnapshot: 'all'}); + break; + case KEYS.I: + if (hasSnapshotFailure && !snapshotInteractiveMode) { + snapshotInteractiveMode = true; + } + updateSnapshotInteractiveTarget(); + break; case KEYS.A: + snapshotInteractiveMode = false; updateArgv(argv, 'watchAll', { testNamePattern: '', testPathPattern: '', @@ -191,13 +214,10 @@ const watch = ( startRun(); break; case KEYS.O: - updateArgv(argv, 'watch', { - testNamePattern: '', - testPathPattern: '', - }); - startRun(); + resetAndRun(); break; case KEYS.P: + snapshotInteractiveMode = false; testPathPatternPrompt.run( testPathPattern => { updateArgv(argv, 'watch', { @@ -211,7 +231,14 @@ const watch = ( {header: activeFilters(argv)}, ); break; + case KEYS.S: + if (snapshotInteractiveMode) { + failedSnapshotTestPaths.shift(); + } + updateSnapshotInteractiveTarget(); + break; case KEYS.T: + snapshotInteractiveMode = false; testNamePatternPrompt.run( testNamePattern => { updateArgv(argv, 'watch', { @@ -231,7 +258,7 @@ const watch = ( if (!shouldDisplayWatchUsage && !isWatchUsageDisplayed) { pipe.write(ansiEscapes.cursorUp()); pipe.write(ansiEscapes.eraseDown); - pipe.write(usage(argv, hasSnapshotFailure)); + pipe.write(usage(argv, hasSnapshotFailure, snapshotInteractiveMode)); isWatchUsageDisplayed = true; shouldDisplayWatchUsage = false; } @@ -239,10 +266,43 @@ const watch = ( } }; + const resetAndRun = () => { + snapshotInteractiveMode = false; + updateArgv(argv, 'watch', { + testNamePattern: '', + testPathPattern: '', + }); + startRun(); + }; + + const updateSnapshotInteractiveTarget = () => { + if (!failedSnapshotTestPaths.length) { + resetAndRun(); + return; + } + + let pattern = ''; + searchSources.forEach(({context}) => { + context.config.roots.forEach(rootPath => { + if (failedSnapshotTestPaths[0].substr(0, rootPath.length) === rootPath) { + pattern = failedSnapshotTestPaths[0].substr(rootPath.length+1); + } + }) + }); + + updateArgv(argv, 'watch', { + testNamePattern: '', + testPathPattern: replacePathSepForRegex(pattern), + }); + + startRun(); + + }; + const onCancelPatternPrompt = () => { pipe.write(ansiEscapes.cursorHide); pipe.write(ansiEscapes.clearScreen); - pipe.write(usage(argv, hasSnapshotFailure)); + pipe.write(usage(argv, hasSnapshotFailure, snapshotInteractiveMode)); pipe.write(ansiEscapes.cursorShow); }; @@ -279,7 +339,7 @@ const activeFilters = (argv, delimiter = '\n') => { return ''; }; -const usage = (argv, snapshotFailure, delimiter = '\n') => { +const usage = (argv, snapshotFailure, snapshotInteractiveMode, delimiter = '\n') => { const messages = [ activeFilters(argv), argv.testPathPattern || argv.testNamePattern @@ -300,6 +360,16 @@ const usage = (argv, snapshotFailure, delimiter = '\n') => { 'u' + chalk.dim(' to update failing snapshots.') : null, + snapshotFailure && !snapshotInteractiveMode + ? chalk.dim(' \u203A Press ') + + 'i' + + chalk.dim(' to update failing snapshots interactively.') + : null, + snapshotInteractiveMode + ? chalk.dim(' \u203A Press ') + + 's' + + chalk.dim(' to skip.') + : null, chalk.dim(' \u203A Press ') + 'p' + chalk.dim(' to filter by a filename regex pattern.'), diff --git a/packages/jest-util/src/get_failed_snapshot_tests.js b/packages/jest-util/src/get_failed_snapshot_tests.js new file mode 100644 index 000000000000..95d974fe48a6 --- /dev/null +++ b/packages/jest-util/src/get_failed_snapshot_tests.js @@ -0,0 +1,25 @@ +/** + * @flow + */ + +import type { + AggregatedResult, +} from 'types/TestResult'; + + +function getFailedSnapshotTests(testResults: AggregatedResult) { + const res = []; + if (testResults.numFailedTests === 0) { + return res; + } + + testResults.testResults.forEach(testResult => { + if (testResult.snapshot.unmatched) { + res.push(testResult.testFilePath); + } + }); + + return res; +} + +module.exports = getFailedSnapshotTests; \ No newline at end of file diff --git a/packages/jest-util/src/index.js b/packages/jest-util/src/index.js index a678191bd70b..d9b066854199 100644 --- a/packages/jest-util/src/index.js +++ b/packages/jest-util/src/index.js @@ -15,6 +15,7 @@ import FakeTimers from './fake_timers'; import NullConsole from './null_console'; import clearLine from './clear_line'; import formatTestResults from './format_test_results'; +import getFailedSnapshotTests from './get_failed_snapshot_tests'; import installCommonGlobals from './install_common_globals'; import setGlobal from './set_global'; import validateCLIOptions from './validate_cli_options'; @@ -36,6 +37,7 @@ module.exports = { clearLine, createDirectory, formatTestResults, + getFailedSnapshotTests, installCommonGlobals, setGlobal, validateCLIOptions, From 290aaab13d641ded1cca8675593539431f625d4e Mon Sep 17 00:00:00 2001 From: Thomas Genin Date: Sun, 11 Jun 2017 19:57:03 -0700 Subject: [PATCH 02/12] SnapshotInteractive logic moved into a dedicate file --- .../jest-cli/src/SnapshotInteractiveMode.js | 137 +++++++++++++++++ packages/jest-cli/src/lib/terminalUtils.js | 9 +- packages/jest-cli/src/watch.js | 140 ++++++------------ .../src/get_failed_snapshot_tests.js | 27 ++-- 4 files changed, 206 insertions(+), 107 deletions(-) create mode 100644 packages/jest-cli/src/SnapshotInteractiveMode.js diff --git a/packages/jest-cli/src/SnapshotInteractiveMode.js b/packages/jest-cli/src/SnapshotInteractiveMode.js new file mode 100644 index 000000000000..2c413dc976ab --- /dev/null +++ b/packages/jest-cli/src/SnapshotInteractiveMode.js @@ -0,0 +1,137 @@ +/** + * @flow + */ + +import type {AggregatedResult} from 'types/TestResult'; + +const chalk = require('chalk'); +const ansiEscapes = require('ansi-escapes'); +const {pluralize} = require('./reporters/utils'); +const {rightPad} = require('./lib/terminalUtils'); +const {KEYS} = require('./constants'); + +module.exports = class SnapshotInteractiveMode { + _pipe: stream$Writable | tty$WriteStream; + _isActive: boolean; + _updateTestRunnerConfig: (a: string, jestRunnerOptions: Object) => *; + _testFilePaths: Array; + _countPaths: number; + + constructor(pipe: stream$Writable | tty$WriteStream) { + this._pipe = pipe; + this._isActive = false; + } + + isActive() { + return this._isActive; + } + + _drawUIOverlay() { + this._pipe.write(ansiEscapes.scrollDown); + this._pipe.write(ansiEscapes.scrollDown); + + this._pipe.write(ansiEscapes.cursorSavePosition); + this._pipe.write(ansiEscapes.cursorTo(0, 0)); + + const title = rightPad(' -> Interactive Snapshot Update Activated <-'); + this._pipe.write(chalk.black.bold.bgYellow(title)); + + this._pipe.write(ansiEscapes.cursorRestorePosition); + this._pipe.write(ansiEscapes.cursorUp(6)); + this._pipe.write(ansiEscapes.eraseDown); + + const numFailed = this._testFilePaths.length; + const numPass = this._countPaths - this._testFilePaths.length; + + let stats = chalk.bold.red(pluralize('suite', numFailed) + ' failed'); + if (numPass) { + stats += ', ' + chalk.bold.green(pluralize('suite', numPass) + ' passed'); + } + const messages = [ + '\n' + chalk.bold('Interactive Snapshot Progress'), + ' \u203A ' + stats, + '\n' + chalk.bold('Watch Usage'), + chalk.dim(' \u203A Press ') + + 'u' + + chalk.dim(' to update failing snapshots.'), + chalk.dim(' \u203A Press ') + + 's' + + chalk.dim(' to skip the current snapshot..'), + chalk.dim(' \u203A Press ') + + 'q' + + chalk.dim(' to quit interactive snapshot mode.'), + chalk.dim(' \u203A Press ') + + 'Enter' + + chalk.dim(' to trigger a test run.'), + ]; + + this._pipe.write(messages.filter(message => !!message).join('\n') + '\n'); + } + + put(key: string) { + switch (key) { + case KEYS.S: + const testFilePath = this._testFilePaths.shift(); + this._testFilePaths.push(testFilePath); + this._run({}); + break; + + case KEYS.U: + this._run({updateSnapshot: 'all'}); + break; + + case KEYS.Q: + case KEYS.ESCAPE: + this.abort(); + break; + + case KEYS.ENTER: + this._run({}); + break; + default: + console.log('got key event', key); + break; + } + } + + abort() { + this._isActive = false; + this._updateTestRunnerConfig('', {}); + } + + update(results: AggregatedResult) { + this._drawUIOverlay(); + + const hasSnapshotFailure = !!results.snapshot.failure; + if (hasSnapshotFailure) { + return; + } + + this._testFilePaths.shift(); + if (this._testFilePaths.length === 0) { + this.abort(); + return; + } + this._run({}); + } + + _run(jestRunnerOptions: Object) { + const testFilePath = this._testFilePaths[0]; + this._updateTestRunnerConfig(testFilePath, jestRunnerOptions); + } + + run( + failedSnapshotTestPaths: Array, + onConfigChange: (path: string, jestRunnerOptions: Object) => *, + ) { + if (!failedSnapshotTestPaths.length) { + return; + } + + this._testFilePaths = [].concat(failedSnapshotTestPaths); + this._countPaths = this._testFilePaths.length; + this._updateTestRunnerConfig = onConfigChange; + this._isActive = true; + this._run({}); + } +}; diff --git a/packages/jest-cli/src/lib/terminalUtils.js b/packages/jest-cli/src/lib/terminalUtils.js index 37d0bbba001d..35d66af8e460 100644 --- a/packages/jest-cli/src/lib/terminalUtils.js +++ b/packages/jest-cli/src/lib/terminalUtils.js @@ -9,8 +9,15 @@ */ /* $FlowFixMe */ -const getTerminalWidth = (): nubmer => process.stdout.columns; +const getTerminalWidth = (): number => process.stdout.columns; + +const rightPad = (input: string): string => { + const termWidth = getTerminalWidth(); + input += Array(termWidth - input.length + 1).join(' '); + return input; +}; module.exports = { getTerminalWidth, + rightPad, }; diff --git a/packages/jest-cli/src/watch.js b/packages/jest-cli/src/watch.js index 29d3aa75ab40..2b506915cc05 100644 --- a/packages/jest-cli/src/watch.js +++ b/packages/jest-cli/src/watch.js @@ -24,6 +24,7 @@ import createContext from './lib/createContext'; import runJest from './runJest'; import updateArgv from './lib/updateArgv'; import SearchSource from './SearchSource'; +import SnapshotInteractiveMode from './SnapshotInteractiveMode'; import TestWatcher from './TestWatcher'; import Prompt from './lib/Prompt'; import TestPathPatternPrompt from './TestPathPatternPrompt'; @@ -50,8 +51,9 @@ const watch = ( const testPathPatternPrompt = new TestPathPatternPrompt(pipe, prompt); const testNamePatternPrompt = new TestNamePatternPrompt(pipe, prompt); + const snapshotInteracticeMode = new SnapshotInteractiveMode(pipe); + let failedSnapshotTestPaths = []; - let snapshotInteractiveMode = false; let searchSources = contexts.map(context => ({ context, @@ -131,17 +133,22 @@ const watch = ( results => { isRunning = false; hasSnapshotFailure = !!results.snapshot.failure; - - if (hasSnapshotFailure && !snapshotInteractiveMode) { - failedSnapshotTestPaths = getFailedSnapshotTests(results); - } + failedSnapshotTestPaths = getFailedSnapshotTests(results); // 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 // and prevent test runs from the previous run. testWatcher = new TestWatcher({isWatchMode: true}); + + testNamePatternPrompt.updateCachedTestResults(results.testResults); + + if (snapshotInteracticeMode.isActive()) { + snapshotInteracticeMode.update(results); + return; + } + if (shouldDisplayWatchUsage) { - pipe.write(usage(argv, hasSnapshotFailure, snapshotInteractiveMode)); + pipe.write(usage(argv, hasSnapshotFailure)); shouldDisplayWatchUsage = false; // hide Watch Usage after first run isWatchUsageDisplayed = true; } else { @@ -149,13 +156,6 @@ const watch = ( shouldDisplayWatchUsage = false; isWatchUsageDisplayed = false; } - - testNamePatternPrompt.updateCachedTestResults(results.testResults); - - if (!hasSnapshotFailure && snapshotInteractiveMode) { - failedSnapshotTestPaths.shift(); - updateSnapshotInteractiveTarget(); - } }, ).catch(error => console.error(chalk.red(error.stack))); }; @@ -171,6 +171,11 @@ const watch = ( return; } + if (snapshotInteracticeMode.isActive()) { + snapshotInteracticeMode.put(key); + return; + } + // Abort test run if ( isRunning && @@ -192,61 +197,39 @@ const watch = ( startRun({updateSnapshot: 'all'}); break; case KEYS.I: - if (hasSnapshotFailure && !snapshotInteractiveMode) { - snapshotInteractiveMode = true; - } - updateSnapshotInteractiveTarget(); - + snapshotInteracticeMode.run( + failedSnapshotTestPaths, + (path: string, jestRunnerOptions: Object) => { + updateRunnerPatternMatching('watch', '', path, jestRunnerOptions); + }, + ); break; case KEYS.A: - snapshotInteractiveMode = false; - updateArgv(argv, 'watchAll', { - testNamePattern: '', - testPathPattern: '', - }); - startRun(); + updateRunnerPatternMatching('watchAll', '', ''); break; case KEYS.C: - updateArgv(argv, 'watch', { - testNamePattern: '', - testPathPattern: '', - }); - startRun(); + updateRunnerPatternMatching('watch', '', ''); break; case KEYS.O: - resetAndRun(); + updateRunnerPatternMatching('watch', '', ''); break; case KEYS.P: - snapshotInteractiveMode = false; testPathPatternPrompt.run( testPathPattern => { - updateArgv(argv, 'watch', { - testNamePattern: '', - testPathPattern: replacePathSepForRegex(testPathPattern), - }); - - startRun(); + updateRunnerPatternMatching('watch', '', testPathPattern); }, onCancelPatternPrompt, {header: activeFilters(argv)}, ); break; - case KEYS.S: - if (snapshotInteractiveMode) { - failedSnapshotTestPaths.shift(); - } - updateSnapshotInteractiveTarget(); - break; case KEYS.T: - snapshotInteractiveMode = false; testNamePatternPrompt.run( testNamePattern => { - updateArgv(argv, 'watch', { + updateRunnerPatternMatching( + 'watch', testNamePattern, - testPathPattern: argv.testPathPattern, - }); - - startRun(); + argv.testPathPattern, + ); }, onCancelPatternPrompt, {header: activeFilters(argv)}, @@ -258,7 +241,7 @@ const watch = ( if (!shouldDisplayWatchUsage && !isWatchUsageDisplayed) { pipe.write(ansiEscapes.cursorUp()); pipe.write(ansiEscapes.eraseDown); - pipe.write(usage(argv, hasSnapshotFailure, snapshotInteractiveMode)); + pipe.write(usage(argv, hasSnapshotFailure)); isWatchUsageDisplayed = true; shouldDisplayWatchUsage = false; } @@ -266,46 +249,26 @@ const watch = ( } }; - const resetAndRun = () => { - snapshotInteractiveMode = false; - updateArgv(argv, 'watch', { - testNamePattern: '', - testPathPattern: '', - }); - startRun(); - }; - - const updateSnapshotInteractiveTarget = () => { - if (!failedSnapshotTestPaths.length) { - resetAndRun(); - return; - } - - let pattern = ''; - searchSources.forEach(({context}) => { - context.config.roots.forEach(rootPath => { - if (failedSnapshotTestPaths[0].substr(0, rootPath.length) === rootPath) { - pattern = failedSnapshotTestPaths[0].substr(rootPath.length+1); - } - }) - }); - - updateArgv(argv, 'watch', { - testNamePattern: '', - testPathPattern: replacePathSepForRegex(pattern), - }); - - startRun(); - - }; - const onCancelPatternPrompt = () => { pipe.write(ansiEscapes.cursorHide); pipe.write(ansiEscapes.clearScreen); - pipe.write(usage(argv, hasSnapshotFailure, snapshotInteractiveMode)); + pipe.write(usage(argv, hasSnapshotFailure)); pipe.write(ansiEscapes.cursorShow); }; + const updateRunnerPatternMatching = ( + watchMode: 'watch' | 'watchAll', + namePattern: string, + filePattern: string, + jestRunnerOptions = {}, + ) => { + updateArgv(argv, watchMode, { + testNamePattern: namePattern, + testPathPattern: replacePathSepForRegex(filePattern), + }); + startRun(jestRunnerOptions); + }; + if (typeof stdin.setRawMode === 'function') { stdin.setRawMode(true); stdin.resume(); @@ -339,7 +302,7 @@ const activeFilters = (argv, delimiter = '\n') => { return ''; }; -const usage = (argv, snapshotFailure, snapshotInteractiveMode, delimiter = '\n') => { +const usage = (argv, snapshotFailure, delimiter = '\n') => { const messages = [ activeFilters(argv), argv.testPathPattern || argv.testNamePattern @@ -360,16 +323,11 @@ const usage = (argv, snapshotFailure, snapshotInteractiveMode, delimiter = '\n') 'u' + chalk.dim(' to update failing snapshots.') : null, - snapshotFailure && !snapshotInteractiveMode + snapshotFailure ? chalk.dim(' \u203A Press ') + 'i' + chalk.dim(' to update failing snapshots interactively.') : null, - snapshotInteractiveMode - ? chalk.dim(' \u203A Press ') + - 's' + - chalk.dim(' to skip.') - : null, chalk.dim(' \u203A Press ') + 'p' + chalk.dim(' to filter by a filename regex pattern.'), diff --git a/packages/jest-util/src/get_failed_snapshot_tests.js b/packages/jest-util/src/get_failed_snapshot_tests.js index 95d974fe48a6..39ec946a4d09 100644 --- a/packages/jest-util/src/get_failed_snapshot_tests.js +++ b/packages/jest-util/src/get_failed_snapshot_tests.js @@ -2,24 +2,21 @@ * @flow */ -import type { - AggregatedResult, -} from 'types/TestResult'; - +import type {AggregatedResult} from 'types/TestResult'; function getFailedSnapshotTests(testResults: AggregatedResult) { - const res = []; - if (testResults.numFailedTests === 0) { - return res; - } + const failedTestPaths = []; + if (testResults.numFailedTests === 0 || !testResults.testResults) { + return failedTestPaths; + } - testResults.testResults.forEach(testResult => { - if (testResult.snapshot.unmatched) { - res.push(testResult.testFilePath); - } - }); + testResults.testResults.forEach(testResult => { + if (testResult.snapshot && testResult.snapshot.unmatched) { + failedTestPaths.push(testResult.testFilePath); + } + }); - return res; + return failedTestPaths; } -module.exports = getFailedSnapshotTests; \ No newline at end of file +module.exports = getFailedSnapshotTests; From cbced772a05ecd5f07dad15f09cf7b08d75889d9 Mon Sep 17 00:00:00 2001 From: Thomas Genin Date: Sun, 11 Jun 2017 21:21:37 -0700 Subject: [PATCH 03/12] Unit tests for SnapshotInteractiveMode --- .../jest-cli/src/SnapshotInteractiveMode.js | 13 +- .../__tests__/SnapshotInteractiveMode-test.js | 138 +++++++++++++++++ .../SnapshotInteractiveMode-test.js.snap | 48 ++++++ .../watch-snapshot-interactive-test.js | 142 ++++++++++++++++++ packages/jest-cli/src/watch.js | 16 +- .../__tests__/getFailedSnapshotTests-test.js | 60 ++++++++ 6 files changed, 404 insertions(+), 13 deletions(-) create mode 100644 packages/jest-cli/src/__tests__/SnapshotInteractiveMode-test.js create mode 100644 packages/jest-cli/src/__tests__/__snapshots__/SnapshotInteractiveMode-test.js.snap create mode 100644 packages/jest-cli/src/__tests__/watch-snapshot-interactive-test.js create mode 100644 packages/jest-util/src/__tests__/getFailedSnapshotTests-test.js diff --git a/packages/jest-cli/src/SnapshotInteractiveMode.js b/packages/jest-cli/src/SnapshotInteractiveMode.js index 2c413dc976ab..df293c4f039b 100644 --- a/packages/jest-cli/src/SnapshotInteractiveMode.js +++ b/packages/jest-cli/src/SnapshotInteractiveMode.js @@ -54,9 +54,11 @@ module.exports = class SnapshotInteractiveMode { chalk.dim(' \u203A Press ') + 'u' + chalk.dim(' to update failing snapshots.'), - chalk.dim(' \u203A Press ') + - 's' + - chalk.dim(' to skip the current snapshot..'), + this._testFilePaths.length > 1 + ? chalk.dim(' \u203A Press ') + + 's' + + chalk.dim(' to skip the current snapshot..') + : '', chalk.dim(' \u203A Press ') + 'q' + chalk.dim(' to quit interactive snapshot mode.'), @@ -99,11 +101,10 @@ module.exports = class SnapshotInteractiveMode { this._updateTestRunnerConfig('', {}); } - update(results: AggregatedResult) { - this._drawUIOverlay(); - + updateWithResults(results: AggregatedResult) { const hasSnapshotFailure = !!results.snapshot.failure; if (hasSnapshotFailure) { + this._drawUIOverlay(); return; } diff --git a/packages/jest-cli/src/__tests__/SnapshotInteractiveMode-test.js b/packages/jest-cli/src/__tests__/SnapshotInteractiveMode-test.js new file mode 100644 index 000000000000..07c308d51a05 --- /dev/null +++ b/packages/jest-cli/src/__tests__/SnapshotInteractiveMode-test.js @@ -0,0 +1,138 @@ +const chalk = require('chalk'); +import {KEYS} from '../constants'; +import SnapshotInteractiveMode from '../SnapshotInteractiveMode'; + +jest.mock('../lib/terminalUtils', () => ({ + getTerminalWidth: () => 80, + rightPad: () => { + ''; + }, +})); + +jest.mock('ansi-escapes', () => ({ + cursorRestorePosition: '[MOCK - cursorRestorePosition]', + cursorSavePosition: '[MOCK - cursorSavePosition]', + cursorScrollDown: '[MOCK - cursorScrollDown]', + cursorTo: (x, y) => `[MOCK - cursorTo(${x}, ${y})]`, + cursorUp: () => '[MOCK - cursorUp]', + eraseDown: '[MOCK - eraseDown]', +})); + +jest.doMock('chalk', () => + Object.assign(new chalk.constructor({enabled: false}), { + stripColor: str => str, + }), +); + +describe('SnapshotInteractiveMode', () => { + let pipe; + let instance; + + beforeEach(() => { + pipe = {write: jest.fn()}; + instance = new SnapshotInteractiveMode(pipe); + }); + + test('is inactive at construction', () => { + expect(instance.isActive()).toBeFalsy(); + }); + + test('call to run process the first file', () => { + const mockCallback = jest.fn(); + instance.run(['first.js', 'second.js'], mockCallback); + expect(instance.isActive()).toBeTruthy(); + expect(mockCallback).toBeCalledWith('first.js', {}); + }); + + test('call to abort', () => { + const mockCallback = jest.fn(); + instance.run(['first.js', 'second.js'], mockCallback); + expect(instance.isActive()).toBeTruthy(); + instance.abort(); + expect(instance.isActive()).toBeFalsy(); + expect(mockCallback).toBeCalledWith('', {}); + }); + describe('key press handler', () => { + test('call to skip trigger a processing of next file', () => { + const mockCallback = jest.fn(); + instance.run(['first.js', 'second.js'], mockCallback); + expect(mockCallback.mock.calls[0]).toEqual(['first.js', {}]); + instance.put(KEYS.S); + expect(mockCallback.mock.calls[1]).toEqual(['second.js', {}]); + instance.put(KEYS.S); + expect(mockCallback.mock.calls[2]).toEqual(['first.js', {}]); + }); + + test('call to skip works with 1 file', () => { + const mockCallback = jest.fn(); + instance.run(['first.js'], mockCallback); + expect(mockCallback.mock.calls[0]).toEqual(['first.js', {}]); + instance.put(KEYS.S); + expect(mockCallback.mock.calls[1]).toEqual(['first.js', {}]); + }); + + test('press U trigger a snapshot update call', () => { + const mockCallback = jest.fn(); + instance.run(['first.js'], mockCallback); + expect(mockCallback.mock.calls[0]).toEqual(['first.js', {}]); + instance.put(KEYS.U); + expect(mockCallback.mock.calls[1]).toEqual([ + 'first.js', + {updateSnapshot: 'all'}, + ]); + }); + + test('press Q or ESC triggers an abort', () => { + instance.abort = jest.fn(); + instance.put(KEYS.Q); + instance.put(KEYS.ESCAPE); + expect(instance.abort).toHaveBeenCalledTimes(2); + }); + + test('press ENTER trigger a run', () => { + const mockCallback = jest.fn(); + instance.run(['first.js'], mockCallback); + instance.put(KEYS.ENTER); + expect(mockCallback).toHaveBeenCalledTimes(2); + expect(mockCallback).toHaveBeenCalledWith('first.js', {}); + }); + }); + describe('updateWithResults', () => { + test('with a test failure simply update UI', () => { + const mockCallback = jest.fn(); + instance.run(['first.js'], mockCallback); + pipe.write('TEST RESULTS CONTENTS'); + instance.updateWithResults({snapshot: {failure: true}}); + expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); + expect(mockCallback).toHaveBeenCalledTimes(1); + }); + + test('with a test success, call the next test', () => { + const mockCallback = jest.fn(); + instance.run(['first.js', 'second.js'], mockCallback); + pipe.write('TEST RESULTS CONTENTS'); + instance.updateWithResults({snapshot: {failure: false}}); + expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); + expect(mockCallback.mock.calls[1]).toEqual(['second.js', {}]); + }); + + test('overlay handle progress UI', () => { + const mockCallback = jest.fn(); + instance.run(['first.js', 'second.js', 'third.js'], mockCallback); + pipe.write('TEST RESULTS CONTENTS'); + instance.updateWithResults({snapshot: {failure: false}}); + instance.updateWithResults({snapshot: {failure: true}}); + expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); + }); + + test('last test success, trigger end of interactive mode', () => { + const mockCallback = jest.fn(); + instance.abort = jest.fn(); + instance.run(['first.js'], mockCallback); + pipe.write('TEST RESULTS CONTENTS'); + instance.updateWithResults({snapshot: {failure: false}}); + expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); + expect(instance.abort).toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/jest-cli/src/__tests__/__snapshots__/SnapshotInteractiveMode-test.js.snap b/packages/jest-cli/src/__tests__/__snapshots__/SnapshotInteractiveMode-test.js.snap new file mode 100644 index 000000000000..e28cc3ca7134 --- /dev/null +++ b/packages/jest-cli/src/__tests__/__snapshots__/SnapshotInteractiveMode-test.js.snap @@ -0,0 +1,48 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SnapshotInteractiveMode updateWithResults last test success, trigger end of interactive mode 1`] = `"TEST RESULTS CONTENTS"`; + +exports[`SnapshotInteractiveMode updateWithResults overlay handle progress UI 1`] = ` +"TEST RESULTS CONTENTS + + +[MOCK - cursorSavePosition] +[MOCK - cursorTo(0, 0)] +undefined +[MOCK - cursorRestorePosition] +[MOCK - cursorUp] +[MOCK - eraseDown] + +Interactive Snapshot Progress + › 2 suites failed, 1 suite passed + +Watch Usage + › Press u to update failing snapshots. + › Press s to skip the current snapshot.. + › Press q to quit interactive snapshot mode. + › Press Enter to trigger a test run. +" +`; + +exports[`SnapshotInteractiveMode updateWithResults with a test failure simply update UI 1`] = ` +"TEST RESULTS CONTENTS + + +[MOCK - cursorSavePosition] +[MOCK - cursorTo(0, 0)] +undefined +[MOCK - cursorRestorePosition] +[MOCK - cursorUp] +[MOCK - eraseDown] + +Interactive Snapshot Progress + › 1 suite failed + +Watch Usage + › Press u to update failing snapshots. + › Press q to quit interactive snapshot mode. + › Press Enter to trigger a test run. +" +`; + +exports[`SnapshotInteractiveMode updateWithResults with a test success, call the next test 1`] = `"TEST RESULTS CONTENTS"`; diff --git a/packages/jest-cli/src/__tests__/watch-snapshot-interactive-test.js b/packages/jest-cli/src/__tests__/watch-snapshot-interactive-test.js new file mode 100644 index 000000000000..32cc4f4ef602 --- /dev/null +++ b/packages/jest-cli/src/__tests__/watch-snapshot-interactive-test.js @@ -0,0 +1,142 @@ +/** + * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. + * + * 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. + * + * @emails oncall+jsinfra + */ + +'use strict'; + +const chalk = require('chalk'); +const {KEYS} = require('../constants'); + +const runJestMock = jest.fn(); + +let terminalWidth; + +jest.mock('ansi-escapes', () => ({ + clearScreen: '[MOCK - clearScreen]', + cursorDown: (count = 1) => `[MOCK - cursorDown(${count})]`, + cursorHide: '[MOCK - cursorHide]', + cursorRestorePosition: '[MOCK - cursorRestorePosition]', + cursorSavePosition: '[MOCK - cursorSavePosition]', + cursorShow: '[MOCK - cursorShow]', + cursorTo: (x, y) => `[MOCK - cursorTo(${x}, ${y})]`, +})); + +jest.mock( + '../SearchSource', + () => + class { + constructor(context) { + this._context = context; + } + }, +); + +jest.doMock('chalk', () => + Object.assign(new chalk.constructor({enabled: false}), { + stripColor: str => str, + }), +); + +jest.doMock( + '../runJest', + () => + function() { + const args = Array.from(arguments); + runJestMock.apply(null, args); + + // Call the callback + args[args.length - 1]({ + numFailedTests: 1, + snapshot: { + failure: true, + }, + testResults: [ + { + snapshot: { + unmatched: 1, + }, + testFilePath: 'bob.js', + }, + ], + }); + + return Promise.resolve(); + }, +); + +const runSnapshotInteractiveMode = jest.fn(); +jest.doMock('../SnapshotInteractiveMode', () => { + return class { + constructor(pipe) { + this.run = runSnapshotInteractiveMode; + } + isActive() { + return false; + } + }; +}); + +jest.doMock('../lib/terminalUtils', () => ({ + getTerminalWidth: () => terminalWidth, +})); + +const watch = require('../watch'); + +const globalConfig = {watch: true}; + +afterEach(runJestMock.mockReset); + +describe('Watch mode flows', () => { + let pipe; + let hasteMapInstances; + let argv; + let contexts; + let stdin; + + beforeEach(() => { + terminalWidth = 80; + pipe = {write: jest.fn()}; + hasteMapInstances = [{on: () => {}}]; + argv = {}; + contexts = [{config: {}}]; + stdin = new MockStdin(); + }); + + it('Pressing "I" enters pattern mode', () => { + contexts[0].config = {rootDir: ''}; + watch(globalConfig, contexts, argv, pipe, hasteMapInstances, stdin); + + // Write a enter pattern mode + stdin.emit(KEYS.I); + expect(runSnapshotInteractiveMode).toHaveBeenCalledWith( + ['bob.js'], + expect.anything(), + ); + }); +}); + +class MockStdin { + constructor() { + this._callbacks = []; + } + + setRawMode() {} + + resume() {} + + setEncoding() {} + + on(evt, callback) { + this._callbacks.push(callback); + } + + emit(key) { + this._callbacks.forEach(cb => cb(key)); + } +} diff --git a/packages/jest-cli/src/watch.js b/packages/jest-cli/src/watch.js index 2b506915cc05..1e10f6e727af 100644 --- a/packages/jest-cli/src/watch.js +++ b/packages/jest-cli/src/watch.js @@ -143,7 +143,7 @@ const watch = ( testNamePatternPrompt.updateCachedTestResults(results.testResults); if (snapshotInteracticeMode.isActive()) { - snapshotInteracticeMode.update(results); + snapshotInteracticeMode.updateWithResults(results); return; } @@ -197,12 +197,14 @@ const watch = ( startRun({updateSnapshot: 'all'}); break; case KEYS.I: - snapshotInteracticeMode.run( - failedSnapshotTestPaths, - (path: string, jestRunnerOptions: Object) => { - updateRunnerPatternMatching('watch', '', path, jestRunnerOptions); - }, - ); + if (hasSnapshotFailure) { + snapshotInteracticeMode.run( + failedSnapshotTestPaths, + (path: string, jestRunnerOptions: Object) => { + updateRunnerPatternMatching('watch', '', path, jestRunnerOptions); + }, + ); + } break; case KEYS.A: updateRunnerPatternMatching('watchAll', '', ''); diff --git a/packages/jest-util/src/__tests__/getFailedSnapshotTests-test.js b/packages/jest-util/src/__tests__/getFailedSnapshotTests-test.js new file mode 100644 index 000000000000..a1b1b7fbfcb9 --- /dev/null +++ b/packages/jest-util/src/__tests__/getFailedSnapshotTests-test.js @@ -0,0 +1,60 @@ +const getFailedSnapshotTests = require('../getFailedSnapshotTests'); + +test('return a list of path', () => { + const targetFilename = 'somewhere.js'; + const param = { + numFailedTests: 1, + testResults: [ + { + snapshot: { + unmatched: 1, + }, + testFilePath: targetFilename, + }, + ], + }; + expect(getFailedSnapshotTests(param)).toEqual([targetFilename]); +}); + +test('handle missing snapshot object', () => { + const targetFilename = 'somewhere.js'; + const param = { + numFailedTests: 1, + testResults: [ + { + testFilePath: targetFilename, + }, + ], + }; + expect(getFailedSnapshotTests(param)).toEqual([]); +}); + +test('handle missing testResults object', () => { + const param = { + numFailedTests: 1, + }; + expect(getFailedSnapshotTests(param)).toEqual([]); +}); + +test('return empty if not failed tests', () => { + const param = { + numFailedTests: 0, + }; + expect(getFailedSnapshotTests(param)).toEqual([]); +}); + +test('return empty if not failed snapshot tests', () => { + const targetFilename = 'somewhere.js'; + const param = { + numFailedTests: 0, + testResults: [ + { + snapshot: { + unmatched: 0, + }, + testFilePath: targetFilename, + }, + ], + }; + expect(getFailedSnapshotTests(param)).toEqual([]); +}); From 916bcf22a649b102c564a106d8e10b574bdb28cf Mon Sep 17 00:00:00 2001 From: Thomas Genin Date: Sat, 24 Jun 2017 14:20:09 -0700 Subject: [PATCH 04/12] Remove unfinish test --- .../watch-snapshot-interactive-test.js | 142 ------------------ 1 file changed, 142 deletions(-) delete mode 100644 packages/jest-cli/src/__tests__/watch-snapshot-interactive-test.js diff --git a/packages/jest-cli/src/__tests__/watch-snapshot-interactive-test.js b/packages/jest-cli/src/__tests__/watch-snapshot-interactive-test.js deleted file mode 100644 index 32cc4f4ef602..000000000000 --- a/packages/jest-cli/src/__tests__/watch-snapshot-interactive-test.js +++ /dev/null @@ -1,142 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. - * - * 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. - * - * @emails oncall+jsinfra - */ - -'use strict'; - -const chalk = require('chalk'); -const {KEYS} = require('../constants'); - -const runJestMock = jest.fn(); - -let terminalWidth; - -jest.mock('ansi-escapes', () => ({ - clearScreen: '[MOCK - clearScreen]', - cursorDown: (count = 1) => `[MOCK - cursorDown(${count})]`, - cursorHide: '[MOCK - cursorHide]', - cursorRestorePosition: '[MOCK - cursorRestorePosition]', - cursorSavePosition: '[MOCK - cursorSavePosition]', - cursorShow: '[MOCK - cursorShow]', - cursorTo: (x, y) => `[MOCK - cursorTo(${x}, ${y})]`, -})); - -jest.mock( - '../SearchSource', - () => - class { - constructor(context) { - this._context = context; - } - }, -); - -jest.doMock('chalk', () => - Object.assign(new chalk.constructor({enabled: false}), { - stripColor: str => str, - }), -); - -jest.doMock( - '../runJest', - () => - function() { - const args = Array.from(arguments); - runJestMock.apply(null, args); - - // Call the callback - args[args.length - 1]({ - numFailedTests: 1, - snapshot: { - failure: true, - }, - testResults: [ - { - snapshot: { - unmatched: 1, - }, - testFilePath: 'bob.js', - }, - ], - }); - - return Promise.resolve(); - }, -); - -const runSnapshotInteractiveMode = jest.fn(); -jest.doMock('../SnapshotInteractiveMode', () => { - return class { - constructor(pipe) { - this.run = runSnapshotInteractiveMode; - } - isActive() { - return false; - } - }; -}); - -jest.doMock('../lib/terminalUtils', () => ({ - getTerminalWidth: () => terminalWidth, -})); - -const watch = require('../watch'); - -const globalConfig = {watch: true}; - -afterEach(runJestMock.mockReset); - -describe('Watch mode flows', () => { - let pipe; - let hasteMapInstances; - let argv; - let contexts; - let stdin; - - beforeEach(() => { - terminalWidth = 80; - pipe = {write: jest.fn()}; - hasteMapInstances = [{on: () => {}}]; - argv = {}; - contexts = [{config: {}}]; - stdin = new MockStdin(); - }); - - it('Pressing "I" enters pattern mode', () => { - contexts[0].config = {rootDir: ''}; - watch(globalConfig, contexts, argv, pipe, hasteMapInstances, stdin); - - // Write a enter pattern mode - stdin.emit(KEYS.I); - expect(runSnapshotInteractiveMode).toHaveBeenCalledWith( - ['bob.js'], - expect.anything(), - ); - }); -}); - -class MockStdin { - constructor() { - this._callbacks = []; - } - - setRawMode() {} - - resume() {} - - setEncoding() {} - - on(evt, callback) { - this._callbacks.push(callback); - } - - emit(key) { - this._callbacks.forEach(cb => cb(key)); - } -} From 736e666ca1ba27f2ec3fc66466170258ea4fad99 Mon Sep 17 00:00:00 2001 From: Thomas Genin Date: Sat, 5 Aug 2017 19:32:43 -0700 Subject: [PATCH 05/12] Ignore JetBrains IDE meta data folder --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 535887d2af2a..dc6126130dd4 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,7 @@ lerna-debug.log npm-debug.log npm-debug.log* yarn-error.log* + + +# JetBrains IDE +.idea/* From 32127da13957e45af651954a74f8de12ecf54307 Mon Sep 17 00:00:00 2001 From: Thomas Genin Date: Sat, 5 Aug 2017 20:34:31 -0700 Subject: [PATCH 06/12] SnapshotInteractive callback use a bool to mark snapshot update --- ...t.js => snapshot_interactive_mode.test.js} | 2 +- ...veMode.js => snapshot_interactive_mode.js} | 58 ++++++++++--------- packages/jest-cli/src/watch.js | 26 ++++++--- ...ts-test.js => get_failed_snapshot.test.js} | 2 +- 4 files changed, 53 insertions(+), 35 deletions(-) rename packages/jest-cli/src/__tests__/{SnapshotInteractiveMode-test.js => snapshot_interactive_mode.test.js} (98%) rename packages/jest-cli/src/{SnapshotInteractiveMode.js => snapshot_interactive_mode.js} (67%) rename packages/jest-util/src/__tests__/{getFailedSnapshotTests-test.js => get_failed_snapshot.test.js} (94%) diff --git a/packages/jest-cli/src/__tests__/SnapshotInteractiveMode-test.js b/packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js similarity index 98% rename from packages/jest-cli/src/__tests__/SnapshotInteractiveMode-test.js rename to packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js index 07c308d51a05..43e157119d50 100644 --- a/packages/jest-cli/src/__tests__/SnapshotInteractiveMode-test.js +++ b/packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js @@ -1,6 +1,6 @@ const chalk = require('chalk'); import {KEYS} from '../constants'; -import SnapshotInteractiveMode from '../SnapshotInteractiveMode'; +import SnapshotInteractiveMode from '../snapshot_interactive_mode'; jest.mock('../lib/terminalUtils', () => ({ getTerminalWidth: () => 80, diff --git a/packages/jest-cli/src/SnapshotInteractiveMode.js b/packages/jest-cli/src/snapshot_interactive_mode.js similarity index 67% rename from packages/jest-cli/src/SnapshotInteractiveMode.js rename to packages/jest-cli/src/snapshot_interactive_mode.js index df293c4f039b..1c97e17ae726 100644 --- a/packages/jest-cli/src/SnapshotInteractiveMode.js +++ b/packages/jest-cli/src/snapshot_interactive_mode.js @@ -1,4 +1,10 @@ /** + * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. + * + * 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 */ @@ -7,13 +13,13 @@ import type {AggregatedResult} from 'types/TestResult'; const chalk = require('chalk'); const ansiEscapes = require('ansi-escapes'); const {pluralize} = require('./reporters/utils'); -const {rightPad} = require('./lib/terminalUtils'); +const {rightPad} = require('./lib/terminal_utils'); const {KEYS} = require('./constants'); module.exports = class SnapshotInteractiveMode { _pipe: stream$Writable | tty$WriteStream; _isActive: boolean; - _updateTestRunnerConfig: (a: string, jestRunnerOptions: Object) => *; + _updateTestRunnerConfig: (path: string, shouldUpdateSnapshot: boolean) => *; _testFilePaths: Array; _countPaths: number; @@ -30,13 +36,13 @@ module.exports = class SnapshotInteractiveMode { this._pipe.write(ansiEscapes.scrollDown); this._pipe.write(ansiEscapes.scrollDown); - this._pipe.write(ansiEscapes.cursorSavePosition); - this._pipe.write(ansiEscapes.cursorTo(0, 0)); - - const title = rightPad(' -> Interactive Snapshot Update Activated <-'); - this._pipe.write(chalk.black.bold.bgYellow(title)); - - this._pipe.write(ansiEscapes.cursorRestorePosition); + // this._pipe.write(ansiEscapes.cursorSavePosition); + // this._pipe.write(ansiEscapes.cursorTo(0, 0)); + // + // const title = rightPad(' -> Interactive Snapshot Update Activated <-'); + // this._pipe.write(chalk.black.bold.bgYellow(title)); + // + // this._pipe.write(ansiEscapes.cursorRestorePosition); this._pipe.write(ansiEscapes.cursorUp(6)); this._pipe.write(ansiEscapes.eraseDown); @@ -51,17 +57,21 @@ module.exports = class SnapshotInteractiveMode { '\n' + chalk.bold('Interactive Snapshot Progress'), ' \u203A ' + stats, '\n' + chalk.bold('Watch Usage'), + chalk.dim(' \u203A Press ') + 'u' + - chalk.dim(' to update failing snapshots.'), + chalk.dim(' to update failing snapshots for this test.'), + this._testFilePaths.length > 1 ? chalk.dim(' \u203A Press ') + - 's' + - chalk.dim(' to skip the current snapshot..') + 's' + + chalk.dim(' to skip the current snapshot.') : '', + chalk.dim(' \u203A Press ') + 'q' + - chalk.dim(' to quit interactive snapshot mode.'), + chalk.dim(' to quit Interactive Snapshot Update Mode.'), + chalk.dim(' \u203A Press ') + 'Enter' + chalk.dim(' to trigger a test run.'), @@ -75,30 +85,26 @@ module.exports = class SnapshotInteractiveMode { case KEYS.S: const testFilePath = this._testFilePaths.shift(); this._testFilePaths.push(testFilePath); - this._run({}); + this._run(false); break; - case KEYS.U: - this._run({updateSnapshot: 'all'}); + this._run(true); break; - case KEYS.Q: case KEYS.ESCAPE: this.abort(); break; - case KEYS.ENTER: - this._run({}); + this._run(false); break; default: - console.log('got key event', key); break; } } abort() { this._isActive = false; - this._updateTestRunnerConfig('', {}); + this._updateTestRunnerConfig('', false); } updateWithResults(results: AggregatedResult) { @@ -113,17 +119,17 @@ module.exports = class SnapshotInteractiveMode { this.abort(); return; } - this._run({}); + this._run(false); } - _run(jestRunnerOptions: Object) { + _run(shouldUpdateSnapshot: boolean) { const testFilePath = this._testFilePaths[0]; - this._updateTestRunnerConfig(testFilePath, jestRunnerOptions); + this._updateTestRunnerConfig(testFilePath, shouldUpdateSnapshot); } run( failedSnapshotTestPaths: Array, - onConfigChange: (path: string, jestRunnerOptions: Object) => *, + onConfigChange: (path: string, shouldUpdateSnapshot: boolean) => *, ) { if (!failedSnapshotTestPaths.length) { return; @@ -133,6 +139,6 @@ module.exports = class SnapshotInteractiveMode { this._countPaths = this._testFilePaths.length; this._updateTestRunnerConfig = onConfigChange; this._isActive = true; - this._run({}); + this._run(false); } }; diff --git a/packages/jest-cli/src/watch.js b/packages/jest-cli/src/watch.js index e743bb33234f..43995f160378 100644 --- a/packages/jest-cli/src/watch.js +++ b/packages/jest-cli/src/watch.js @@ -52,7 +52,7 @@ const watch = ( const prompt = new Prompt(); const testPathPatternPrompt = new TestPathPatternPrompt(outputStream, prompt); const testNamePatternPrompt = new TestNamePatternPrompt(outputStream, prompt); - const snapshotInteracticeMode = new SnapshotInteractiveMode(pipe); + const snapshotInteracticeMode = new SnapshotInteractiveMode(outputStream); let failedSnapshotTestPaths = []; let searchSources = contexts.map(context => ({ context, @@ -197,8 +197,19 @@ const watch = ( if (hasSnapshotFailure) { snapshotInteracticeMode.run( failedSnapshotTestPaths, - (path: string, jestRunnerOptions: Object) => { - updateRunnerPatternMatching('watch', '', path, jestRunnerOptions); + (path: string, shouldUpdateSnapshot: boolean) => { + // updateRunnerPatternMatching('watch', '', path, jestRunnerOptions); + globalConfig = updateGlobalConfig(globalConfig, { + mode: 'watch', + testNamePattern: '', + testPathPattern: replacePathSepForRegex(path), + updateSnapshot: shouldUpdateSnapshot ? 'all' : 'none', + }); + startRun(globalConfig); + globalConfig = updateGlobalConfig(globalConfig, { + // updateSnapshot is not sticky after a run. + updateSnapshot: 'none', + }); }, ); } @@ -284,11 +295,12 @@ const watch = ( filePattern: string, jestRunnerOptions = {}, ) => { - updateArgv(argv, watchMode, { + globalConfig = updateGlobalConfig(globalConfig, { + mode: watchMode, testNamePattern: namePattern, testPathPattern: replacePathSepForRegex(filePattern), }); - startRun(jestRunnerOptions); + startRun(globalConfig); }; if (typeof stdin.setRawMode === 'function') { @@ -354,8 +366,8 @@ const usage = (globalConfig, snapshotFailure, delimiter = '\n') => { snapshotFailure ? chalk.dim(' \u203A Press ') + - 'i' + - chalk.dim(' to update failing snapshots interactively.') + 'i' + + chalk.dim(' to update failing snapshots interactively.') : null, chalk.dim(' \u203A Press ') + diff --git a/packages/jest-util/src/__tests__/getFailedSnapshotTests-test.js b/packages/jest-util/src/__tests__/get_failed_snapshot.test.js similarity index 94% rename from packages/jest-util/src/__tests__/getFailedSnapshotTests-test.js rename to packages/jest-util/src/__tests__/get_failed_snapshot.test.js index a1b1b7fbfcb9..3962c02ba3cf 100644 --- a/packages/jest-util/src/__tests__/getFailedSnapshotTests-test.js +++ b/packages/jest-util/src/__tests__/get_failed_snapshot.test.js @@ -1,4 +1,4 @@ -const getFailedSnapshotTests = require('../getFailedSnapshotTests'); +const getFailedSnapshotTests = require('../get_failed_snapshot_tests'); test('return a list of path', () => { const targetFilename = 'somewhere.js'; From 8068f36b212f0c446b3356cb72edf0d9239791ce Mon Sep 17 00:00:00 2001 From: Thomas Genin Date: Sat, 5 Aug 2017 21:19:35 -0700 Subject: [PATCH 07/12] Fix the Snapshot Interactive tests by using bool --- .../snapshot_interactive_mode.test.js | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js b/packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js index 43e157119d50..d8e02c1c363c 100644 --- a/packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js +++ b/packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js @@ -2,7 +2,7 @@ const chalk = require('chalk'); import {KEYS} from '../constants'; import SnapshotInteractiveMode from '../snapshot_interactive_mode'; -jest.mock('../lib/terminalUtils', () => ({ +jest.mock('../lib/terminal_utils', () => ({ getTerminalWidth: () => 80, rightPad: () => { ''; @@ -41,7 +41,7 @@ describe('SnapshotInteractiveMode', () => { const mockCallback = jest.fn(); instance.run(['first.js', 'second.js'], mockCallback); expect(instance.isActive()).toBeTruthy(); - expect(mockCallback).toBeCalledWith('first.js', {}); + expect(mockCallback).toBeCalledWith('first.js', false); }); test('call to abort', () => { @@ -50,35 +50,35 @@ describe('SnapshotInteractiveMode', () => { expect(instance.isActive()).toBeTruthy(); instance.abort(); expect(instance.isActive()).toBeFalsy(); - expect(mockCallback).toBeCalledWith('', {}); + expect(mockCallback).toBeCalledWith('', false); }); describe('key press handler', () => { test('call to skip trigger a processing of next file', () => { const mockCallback = jest.fn(); instance.run(['first.js', 'second.js'], mockCallback); - expect(mockCallback.mock.calls[0]).toEqual(['first.js', {}]); + expect(mockCallback.mock.calls[0]).toEqual(['first.js', false]); instance.put(KEYS.S); - expect(mockCallback.mock.calls[1]).toEqual(['second.js', {}]); + expect(mockCallback.mock.calls[1]).toEqual(['second.js', false]); instance.put(KEYS.S); - expect(mockCallback.mock.calls[2]).toEqual(['first.js', {}]); + expect(mockCallback.mock.calls[2]).toEqual(['first.js', false]); }); test('call to skip works with 1 file', () => { const mockCallback = jest.fn(); instance.run(['first.js'], mockCallback); - expect(mockCallback.mock.calls[0]).toEqual(['first.js', {}]); + expect(mockCallback.mock.calls[0]).toEqual(['first.js', false]); instance.put(KEYS.S); - expect(mockCallback.mock.calls[1]).toEqual(['first.js', {}]); + expect(mockCallback.mock.calls[1]).toEqual(['first.js', false]); }); test('press U trigger a snapshot update call', () => { const mockCallback = jest.fn(); instance.run(['first.js'], mockCallback); - expect(mockCallback.mock.calls[0]).toEqual(['first.js', {}]); + expect(mockCallback.mock.calls[0]).toEqual(['first.js', false]); instance.put(KEYS.U); expect(mockCallback.mock.calls[1]).toEqual([ 'first.js', - {updateSnapshot: 'all'}, + true, ]); }); @@ -94,7 +94,7 @@ describe('SnapshotInteractiveMode', () => { instance.run(['first.js'], mockCallback); instance.put(KEYS.ENTER); expect(mockCallback).toHaveBeenCalledTimes(2); - expect(mockCallback).toHaveBeenCalledWith('first.js', {}); + expect(mockCallback).toHaveBeenCalledWith('first.js', false); }); }); describe('updateWithResults', () => { @@ -113,7 +113,7 @@ describe('SnapshotInteractiveMode', () => { pipe.write('TEST RESULTS CONTENTS'); instance.updateWithResults({snapshot: {failure: false}}); expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); - expect(mockCallback.mock.calls[1]).toEqual(['second.js', {}]); + expect(mockCallback.mock.calls[1]).toEqual(['second.js', false]); }); test('overlay handle progress UI', () => { From 0c7343d9fe37b2b317f5baf396da4bf66e76521b Mon Sep 17 00:00:00 2001 From: Thomas Genin Date: Sat, 5 Aug 2017 21:22:27 -0700 Subject: [PATCH 08/12] Remove unused function, but logic to update snapshot need to be abstracted --- packages/jest-cli/src/watch.js | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/packages/jest-cli/src/watch.js b/packages/jest-cli/src/watch.js index 43995f160378..6f0689d63fc0 100644 --- a/packages/jest-cli/src/watch.js +++ b/packages/jest-cli/src/watch.js @@ -198,7 +198,6 @@ const watch = ( snapshotInteracticeMode.run( failedSnapshotTestPaths, (path: string, shouldUpdateSnapshot: boolean) => { - // updateRunnerPatternMatching('watch', '', path, jestRunnerOptions); globalConfig = updateGlobalConfig(globalConfig, { mode: 'watch', testNamePattern: '', @@ -289,20 +288,6 @@ const watch = ( outputStream.write(ansiEscapes.cursorShow); }; - const updateRunnerPatternMatching = ( - watchMode: 'watch' | 'watchAll', - namePattern: string, - filePattern: string, - jestRunnerOptions = {}, - ) => { - globalConfig = updateGlobalConfig(globalConfig, { - mode: watchMode, - testNamePattern: namePattern, - testPathPattern: replacePathSepForRegex(filePattern), - }); - startRun(globalConfig); - }; - if (typeof stdin.setRawMode === 'function') { stdin.setRawMode(true); stdin.resume(); From 8b1b70105a3db4c701425043183a4f147aa4b2bd Mon Sep 17 00:00:00 2001 From: Thomas Genin Date: Mon, 7 Aug 2017 21:14:27 -0700 Subject: [PATCH 09/12] New Snapshot file --- ... => snapshot_interactive_mode.test.js.snap} | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) rename packages/jest-cli/src/__tests__/__snapshots__/{SnapshotInteractiveMode-test.js.snap => snapshot_interactive_mode.test.js.snap} (66%) diff --git a/packages/jest-cli/src/__tests__/__snapshots__/SnapshotInteractiveMode-test.js.snap b/packages/jest-cli/src/__tests__/__snapshots__/snapshot_interactive_mode.test.js.snap similarity index 66% rename from packages/jest-cli/src/__tests__/__snapshots__/SnapshotInteractiveMode-test.js.snap rename to packages/jest-cli/src/__tests__/__snapshots__/snapshot_interactive_mode.test.js.snap index e28cc3ca7134..aad4b780d532 100644 --- a/packages/jest-cli/src/__tests__/__snapshots__/SnapshotInteractiveMode-test.js.snap +++ b/packages/jest-cli/src/__tests__/__snapshots__/snapshot_interactive_mode.test.js.snap @@ -6,10 +6,6 @@ exports[`SnapshotInteractiveMode updateWithResults overlay handle progress UI 1` "TEST RESULTS CONTENTS -[MOCK - cursorSavePosition] -[MOCK - cursorTo(0, 0)] -undefined -[MOCK - cursorRestorePosition] [MOCK - cursorUp] [MOCK - eraseDown] @@ -17,9 +13,9 @@ exports[`SnapshotInteractiveMode updateWithResults overlay handle progress UI 1` › 2 suites failed, 1 suite passed Watch Usage - › Press u to update failing snapshots. - › Press s to skip the current snapshot.. - › Press q to quit interactive snapshot mode. + › Press u to update failing snapshots for this test. + › Press s to skip the current snapshot. + › Press q to quit Interactive Snapshot Update Mode. › Press Enter to trigger a test run. " `; @@ -28,10 +24,6 @@ exports[`SnapshotInteractiveMode updateWithResults with a test failure simply up "TEST RESULTS CONTENTS -[MOCK - cursorSavePosition] -[MOCK - cursorTo(0, 0)] -undefined -[MOCK - cursorRestorePosition] [MOCK - cursorUp] [MOCK - eraseDown] @@ -39,8 +31,8 @@ exports[`SnapshotInteractiveMode updateWithResults with a test failure simply up › 1 suite failed Watch Usage - › Press u to update failing snapshots. - › Press q to quit interactive snapshot mode. + › Press u to update failing snapshots for this test. + › Press q to quit Interactive Snapshot Update Mode. › Press Enter to trigger a test run. " `; From 45e4e1fe913342788568d85b47524df54ab5f074 Mon Sep 17 00:00:00 2001 From: Thomas Genin Date: Mon, 7 Aug 2017 21:27:29 -0700 Subject: [PATCH 10/12] Fix code style of snapshot interactive test --- .../jest-cli/src/__tests__/snapshot_interactive_mode.test.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js b/packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js index d8e02c1c363c..5f63800812a6 100644 --- a/packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js +++ b/packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js @@ -76,10 +76,7 @@ describe('SnapshotInteractiveMode', () => { instance.run(['first.js'], mockCallback); expect(mockCallback.mock.calls[0]).toEqual(['first.js', false]); instance.put(KEYS.U); - expect(mockCallback.mock.calls[1]).toEqual([ - 'first.js', - true, - ]); + expect(mockCallback.mock.calls[1]).toEqual(['first.js', true]); }); test('press Q or ESC triggers an abort', () => { From f8d4c38a680355580978b50bc7462d6d2a5cbb07 Mon Sep 17 00:00:00 2001 From: Thomas Genin Date: Tue, 19 Dec 2017 21:39:19 +0100 Subject: [PATCH 11/12] Fixes after rebase --- .gitignore | 1 - .../snapshot_interactive_mode.test.js.snap | 28 +++++++++---------- .../jest-cli/src/snapshot_interactive_mode.js | 12 ++------ packages/jest-cli/src/watch.js | 3 +- .../src/__tests__/get_failed_snapshot.test.js | 2 +- .../src/get_failed_snapshot_tests.js | 2 +- packages/jest-util/src/index.js | 2 +- 7 files changed, 20 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index 23b847ae0e67..b4d6979cdfe9 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,5 @@ npm-debug.log npm-debug.log* yarn-error.log* - # JetBrains IDE .idea/* diff --git a/packages/jest-cli/src/__tests__/__snapshots__/snapshot_interactive_mode.test.js.snap b/packages/jest-cli/src/__tests__/__snapshots__/snapshot_interactive_mode.test.js.snap index aad4b780d532..6d7194f97312 100644 --- a/packages/jest-cli/src/__tests__/__snapshots__/snapshot_interactive_mode.test.js.snap +++ b/packages/jest-cli/src/__tests__/__snapshots__/snapshot_interactive_mode.test.js.snap @@ -9,14 +9,14 @@ exports[`SnapshotInteractiveMode updateWithResults overlay handle progress UI 1` [MOCK - cursorUp] [MOCK - eraseDown] -Interactive Snapshot Progress - › 2 suites failed, 1 suite passed - -Watch Usage - › Press u to update failing snapshots for this test. - › Press s to skip the current snapshot. - › Press q to quit Interactive Snapshot Update Mode. - › Press Enter to trigger a test run. +Interactive Snapshot Progress + › 2 suites failed, 1 suite passed + +Watch Usage + › Press u to update failing snapshots for this test. + › Press s to skip the current snapshot. + › Press q to quit Interactive Snapshot Update Mode. + › Press Enter to trigger a test run. " `; @@ -27,13 +27,13 @@ exports[`SnapshotInteractiveMode updateWithResults with a test failure simply up [MOCK - cursorUp] [MOCK - eraseDown] -Interactive Snapshot Progress - › 1 suite failed +Interactive Snapshot Progress + › 1 suite failed -Watch Usage - › Press u to update failing snapshots for this test. - › Press q to quit Interactive Snapshot Update Mode. - › Press Enter to trigger a test run. +Watch Usage + › Press u to update failing snapshots for this test. + › Press q to quit Interactive Snapshot Update Mode. + › Press Enter to trigger a test run. " `; diff --git a/packages/jest-cli/src/snapshot_interactive_mode.js b/packages/jest-cli/src/snapshot_interactive_mode.js index 1c97e17ae726..b5b4cff6084f 100644 --- a/packages/jest-cli/src/snapshot_interactive_mode.js +++ b/packages/jest-cli/src/snapshot_interactive_mode.js @@ -13,10 +13,9 @@ import type {AggregatedResult} from 'types/TestResult'; const chalk = require('chalk'); const ansiEscapes = require('ansi-escapes'); const {pluralize} = require('./reporters/utils'); -const {rightPad} = require('./lib/terminal_utils'); const {KEYS} = require('./constants'); -module.exports = class SnapshotInteractiveMode { +export default class SnapshotInteractiveMode { _pipe: stream$Writable | tty$WriteStream; _isActive: boolean; _updateTestRunnerConfig: (path: string, shouldUpdateSnapshot: boolean) => *; @@ -36,13 +35,6 @@ module.exports = class SnapshotInteractiveMode { this._pipe.write(ansiEscapes.scrollDown); this._pipe.write(ansiEscapes.scrollDown); - // this._pipe.write(ansiEscapes.cursorSavePosition); - // this._pipe.write(ansiEscapes.cursorTo(0, 0)); - // - // const title = rightPad(' -> Interactive Snapshot Update Activated <-'); - // this._pipe.write(chalk.black.bold.bgYellow(title)); - // - // this._pipe.write(ansiEscapes.cursorRestorePosition); this._pipe.write(ansiEscapes.cursorUp(6)); this._pipe.write(ansiEscapes.eraseDown); @@ -141,4 +133,4 @@ module.exports = class SnapshotInteractiveMode { this._isActive = true; this._run(false); } -}; +} diff --git a/packages/jest-cli/src/watch.js b/packages/jest-cli/src/watch.js index a3e562ab5c4d..99695a30dd38 100644 --- a/packages/jest-cli/src/watch.js +++ b/packages/jest-cli/src/watch.js @@ -15,10 +15,9 @@ import ansiEscapes from 'ansi-escapes'; import chalk from 'chalk'; import getChangedFilesPromise from './get_changed_files_promise'; import {replacePathSepForRegex} from 'jest-regex-util'; -import {getFailedSnapshotTests} from 'jest-util'; import HasteMap from 'jest-haste-map'; import isValidPath from './lib/is_valid_path'; -import {isInteractive} from 'jest-util'; +import {getFailedSnapshotTests, isInteractive} from 'jest-util'; import {print as preRunMessagePrint} from './pre_run_message'; import createContext from './lib/create_context'; import runJest from './run_jest'; diff --git a/packages/jest-util/src/__tests__/get_failed_snapshot.test.js b/packages/jest-util/src/__tests__/get_failed_snapshot.test.js index 3962c02ba3cf..f4afab129655 100644 --- a/packages/jest-util/src/__tests__/get_failed_snapshot.test.js +++ b/packages/jest-util/src/__tests__/get_failed_snapshot.test.js @@ -1,4 +1,4 @@ -const getFailedSnapshotTests = require('../get_failed_snapshot_tests'); +import getFailedSnapshotTests from '../get_failed_snapshot_tests'; test('return a list of path', () => { const targetFilename = 'somewhere.js'; diff --git a/packages/jest-util/src/get_failed_snapshot_tests.js b/packages/jest-util/src/get_failed_snapshot_tests.js index 39ec946a4d09..eadf09212c47 100644 --- a/packages/jest-util/src/get_failed_snapshot_tests.js +++ b/packages/jest-util/src/get_failed_snapshot_tests.js @@ -19,4 +19,4 @@ function getFailedSnapshotTests(testResults: AggregatedResult) { return failedTestPaths; } -module.exports = getFailedSnapshotTests; +export default getFailedSnapshotTests; diff --git a/packages/jest-util/src/index.js b/packages/jest-util/src/index.js index bc4435bff1e5..7d3736bdefe8 100644 --- a/packages/jest-util/src/index.js +++ b/packages/jest-util/src/index.js @@ -40,8 +40,8 @@ module.exports = { clearLine, createDirectory, formatTestResults, - getFailedSnapshotTests, getConsoleOutput, + getFailedSnapshotTests, installCommonGlobals, isInteractive, setGlobal, From c5458985f0d00180d482b1be8cbfaff3f77030f7 Mon Sep 17 00:00:00 2001 From: Miguel Jimenez Esun Date: Thu, 11 Jan 2018 14:28:39 +0000 Subject: [PATCH 12/12] Patch with @thymikee review --- .gitignore | 3 --- .../snapshot_interactive_mode.test.js.snap | 4 ---- .../src/__tests__/snapshot_interactive_mode.test.js | 9 ++++++++- packages/jest-cli/src/snapshot_interactive_mode.js | 5 +---- packages/jest-cli/src/watch.js | 12 ++++++------ .../src/__tests__/get_failed_snapshot.test.js | 7 +++++++ 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index b4d6979cdfe9..5a147c97d326 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,3 @@ lerna-debug.log npm-debug.log npm-debug.log* yarn-error.log* - -# JetBrains IDE -.idea/* diff --git a/packages/jest-cli/src/__tests__/__snapshots__/snapshot_interactive_mode.test.js.snap b/packages/jest-cli/src/__tests__/__snapshots__/snapshot_interactive_mode.test.js.snap index 6d7194f97312..9b8e2e9a04fb 100644 --- a/packages/jest-cli/src/__tests__/__snapshots__/snapshot_interactive_mode.test.js.snap +++ b/packages/jest-cli/src/__tests__/__snapshots__/snapshot_interactive_mode.test.js.snap @@ -4,8 +4,6 @@ exports[`SnapshotInteractiveMode updateWithResults last test success, trigger en exports[`SnapshotInteractiveMode updateWithResults overlay handle progress UI 1`] = ` "TEST RESULTS CONTENTS - - [MOCK - cursorUp] [MOCK - eraseDown] @@ -22,8 +20,6 @@ exports[`SnapshotInteractiveMode updateWithResults overlay handle progress UI 1` exports[`SnapshotInteractiveMode updateWithResults with a test failure simply update UI 1`] = ` "TEST RESULTS CONTENTS - - [MOCK - cursorUp] [MOCK - eraseDown] diff --git a/packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js b/packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js index 5f63800812a6..638bb8c3e7a8 100644 --- a/packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js +++ b/packages/jest-cli/src/__tests__/snapshot_interactive_mode.test.js @@ -1,4 +1,11 @@ -const chalk = require('chalk'); +/** + * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import chalk from 'chalk'; import {KEYS} from '../constants'; import SnapshotInteractiveMode from '../snapshot_interactive_mode'; diff --git a/packages/jest-cli/src/snapshot_interactive_mode.js b/packages/jest-cli/src/snapshot_interactive_mode.js index b5b4cff6084f..ce97d15cbafa 100644 --- a/packages/jest-cli/src/snapshot_interactive_mode.js +++ b/packages/jest-cli/src/snapshot_interactive_mode.js @@ -32,9 +32,6 @@ export default class SnapshotInteractiveMode { } _drawUIOverlay() { - this._pipe.write(ansiEscapes.scrollDown); - this._pipe.write(ansiEscapes.scrollDown); - this._pipe.write(ansiEscapes.cursorUp(6)); this._pipe.write(ansiEscapes.eraseDown); @@ -69,7 +66,7 @@ export default class SnapshotInteractiveMode { chalk.dim(' to trigger a test run.'), ]; - this._pipe.write(messages.filter(message => !!message).join('\n') + '\n'); + this._pipe.write(messages.filter(Boolean).join('\n') + '\n'); } put(key: string) { diff --git a/packages/jest-cli/src/watch.js b/packages/jest-cli/src/watch.js index 99695a30dd38..cae60f5bb149 100644 --- a/packages/jest-cli/src/watch.js +++ b/packages/jest-cli/src/watch.js @@ -61,7 +61,7 @@ export default function watch( const prompt = new Prompt(); const testPathPatternPrompt = new TestPathPatternPrompt(outputStream, prompt); const testNamePatternPrompt = new TestNamePatternPrompt(outputStream, prompt); - const snapshotInteracticeMode = new SnapshotInteractiveMode(outputStream); + const snapshotInteractiveMode = new SnapshotInteractiveMode(outputStream); let failedSnapshotTestPaths = []; let searchSources = contexts.map(context => ({ context, @@ -142,8 +142,8 @@ export default function watch( // Do not show any Watch Usage related stuff when running in a // non-interactive environment if (isInteractive) { - if (snapshotInteracticeMode.isActive()) { - snapshotInteracticeMode.updateWithResults(results); + if (snapshotInteractiveMode.isActive()) { + snapshotInteractiveMode.updateWithResults(results); return; } if (shouldDisplayWatchUsage) { @@ -187,8 +187,8 @@ export default function watch( return; } - if (snapshotInteracticeMode.isActive()) { - snapshotInteracticeMode.put(key); + if (snapshotInteractiveMode.isActive()) { + snapshotInteractiveMode.put(key); return; } @@ -237,7 +237,7 @@ export default function watch( break; case KEYS.I: if (hasSnapshotFailure) { - snapshotInteracticeMode.run( + snapshotInteractiveMode.run( failedSnapshotTestPaths, (path: string, shouldUpdateSnapshot: boolean) => { globalConfig = updateGlobalConfig(globalConfig, { diff --git a/packages/jest-util/src/__tests__/get_failed_snapshot.test.js b/packages/jest-util/src/__tests__/get_failed_snapshot.test.js index f4afab129655..ca9992978bb3 100644 --- a/packages/jest-util/src/__tests__/get_failed_snapshot.test.js +++ b/packages/jest-util/src/__tests__/get_failed_snapshot.test.js @@ -1,3 +1,10 @@ +/** + * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + import getFailedSnapshotTests from '../get_failed_snapshot_tests'; test('return a list of path', () => {