diff --git a/packages/jest-cli/src/jest.js b/packages/jest-cli/src/jest.js index fa6b9ddfc093..5600b3ed3620 100644 --- a/packages/jest-cli/src/jest.js +++ b/packages/jest-cli/src/jest.js @@ -34,6 +34,12 @@ const CLEAR = '\x1B[2J\x1B[H'; const VERSION = require('../package.json').version; const WATCHER_DEBOUNCE = 200; const WATCHMAN_BIN = 'watchman'; +const KEYS = { + CONTROL_C: '03', + CONTROL_D: '04', + ENTER: '0d', + U: '75', +}; function getMaxWorkers(argv) { if (argv.runInBand) { @@ -154,37 +160,69 @@ function runCLI(argv: Object, root: Path, onComplete: () => void) { if (argv.watch || argv.watchAll) { argv.onlyChanged = !argv.watchAll; - return new Promise(resolve => { - getWatcher(config, root, watcher => { - let timer; - let isRunning; - const startRun = () => { - isRunning = true; - runJest(config, argv, pipe, () => isRunning = false) - .then( - resolve, - error => console.error(chalk.red(error)), - ); - }; - - pipe.write(CLEAR); - startRun(); - - watcher.on('all', (_, filePath) => { - pipe.write(CLEAR); - filePath = path.join(root, filePath); - const isValidPath = - config.testPathDirs.some(dir => filePath.startsWith(dir)); - if (!isRunning && isValidPath) { - if (timer) { - clearTimeout(timer); - timer = null; - } - timer = setTimeout(startRun, WATCHER_DEBOUNCE); - } - }); - }); + let isRunning: ?boolean; + let timer: ?int; + + const startRun = (overrideConfig: Object = {}) => { + if (isRunning) { + return; + } + + pipe.write(CLEAR); + isRunning = true; + runJest( + Object.freeze(Object.assign({}, config, overrideConfig)), + argv, + pipe, + () => { + isRunning = false + }, + ).then( + () => {}, + error => console.error(chalk.red(error)), + ); + }; + + const onKeypress = (key: string) => { + switch (key) { + case KEYS.CONTROL_C: + process.exit(0); + break; + case KEYS.CONTROL_D: + process.exit(0); + break; + case KEYS.ENTER: + startRun(); + break; + case KEYS.U: + startRun({updateSnapshot: true}); + break; + } + }; + + const onFileChange = (_, filePath: string) => { + filePath = path.join(root, filePath); + const isValidPath = + config.testPathDirs.some(dir => filePath.startsWith(dir)); + + if (!isValidPath) { + return; + } + if (timer) { + clearTimeout(timer); + timer = null; + } + timer = setTimeout(startRun, WATCHER_DEBOUNCE); + }; + + process.stdin.setRawMode(true); + process.stdin.resume(); + process.stdin.setEncoding('hex'); + process.stdin.on('data', onKeypress); + getWatcher(config, root, watcher => { + watcher.on('all', onFileChange); }); + startRun(); } else { return runJest(config, argv, pipe, onComplete); } diff --git a/packages/jest-cli/src/reporters/SummaryReporter.js b/packages/jest-cli/src/reporters/SummaryReporter.js index 45c7dbbb7095..47b301f9435e 100644 --- a/packages/jest-cli/src/reporters/SummaryReporter.js +++ b/packages/jest-cli/src/reporters/SummaryReporter.js @@ -62,7 +62,7 @@ class SummareReporter extends BaseReporter { } this._printSummary(aggregatedResults, config); - this._printSnapshotSummary(snapshots); + this._printSnapshotSummary(snapshots, config); if (totalTestSuites) { results += `${PASS_COLOR(`${pluralize('test', passedTests)} passed`)} (` + @@ -73,7 +73,7 @@ class SummareReporter extends BaseReporter { } } - _printSnapshotSummary(snapshots: SnapshotSummary) { + _printSnapshotSummary(snapshots: SnapshotSummary, config: Config) { if ( snapshots.added || snapshots.filesRemoved || @@ -81,10 +81,15 @@ class SummareReporter extends BaseReporter { snapshots.unmatched || snapshots.updated ) { + let updateCommand; const event = process.env.npm_lifecycle_event; - const updateCommand = - (!event ? 're-' : '') + 'run with `' + - (event ? 'npm ' + event + ' -- ' : '') + '-u`'; + if (config.watch) { + updateCommand = 'press "u"'; + } else if (event) { + updateCommand = `run with \`npm ${event} -- -u\``; + } else { + updateCommand = 're-run with `-u`'; + } this.log('\n' + SNAPSHOT_SUMMARY('Snapshot Summary')); if (snapshots.added) { diff --git a/packages/jest-config/src/defaults.js b/packages/jest-config/src/defaults.js index a3c2757c1e02..afc9f3355402 100644 --- a/packages/jest-config/src/defaults.js +++ b/packages/jest-config/src/defaults.js @@ -49,4 +49,5 @@ module.exports = ({ testURL: 'about:blank', useStderr: false, verbose: false, + watch: false, }: DefaultConfig); diff --git a/packages/jest-config/src/setFromArgv.js b/packages/jest-config/src/setFromArgv.js index 12a633ea5a79..76d8aba8465c 100644 --- a/packages/jest-config/src/setFromArgv.js +++ b/packages/jest-config/src/setFromArgv.js @@ -64,6 +64,11 @@ function setFromArgv(config, argv) { if (argv.updateSnapshot) { config.updateSnapshot = argv.updateSnapshot; } + + if (argv.watch || argv.watchAll) { + config.watch = true; + } + config.noStackTrace = argv.noStackTrace; config.testcheckOptions = { diff --git a/packages/jest-snapshot/src/SnapshotFile.js b/packages/jest-snapshot/src/SnapshotFile.js index 658a73ea156b..10d1382168a2 100644 --- a/packages/jest-snapshot/src/SnapshotFile.js +++ b/packages/jest-snapshot/src/SnapshotFile.js @@ -62,6 +62,7 @@ class SnapshotFile { this._content = Object.create(null); if (this.fileExists(filename)) { + delete require.cache[require.resolve(filename)]; try { /* eslint-disable no-useless-call */ Object.assign(this._content, require.call(null, filename)); diff --git a/types/Config.js b/types/Config.js index a068b757efa2..efe4446b2c54 100644 --- a/types/Config.js +++ b/types/Config.js @@ -44,6 +44,7 @@ type BaseConfig = { testURL: string, useStderr: boolean, verbose: boolean, + watch: boolean, }; export type DefaultConfig = BaseConfig & {