From ebcb19274f229f03168c631a157d5ded4e89d2eb Mon Sep 17 00:00:00 2001 From: Rogelio Guzman Date: Tue, 18 Apr 2017 10:19:21 -0700 Subject: [PATCH 1/6] Bring back filter by test name --- .../jest-cli/src/__tests__/__snapshots__/watch-test.js.snap | 1 + packages/jest-cli/src/watch.js | 3 +++ 2 files changed, 4 insertions(+) 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 3d92473bbce8..7d7874e50262 100644 --- a/packages/jest-cli/src/__tests__/__snapshots__/watch-test.js.snap +++ b/packages/jest-cli/src/__tests__/__snapshots__/watch-test.js.snap @@ -6,6 +6,7 @@ Array [ Watch Usage › Press o to only run tests related to changed files. › 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/watch.js b/packages/jest-cli/src/watch.js index 5a03c56d9606..bdaf06be5582 100644 --- a/packages/jest-cli/src/watch.js +++ b/packages/jest-cli/src/watch.js @@ -256,6 +256,9 @@ const usage = (argv, snapshotFailure, delimiter = '\n') => { chalk.dim(' \u203A Press ') + 'p' + chalk.dim(' to filter by a filename regex pattern.'), + chalk.dim(' \u203A Press ') + + 't' + + chalk.dim(' to filter by a test name regex pattern.'), chalk.dim(' \u203A Press ') + 'q' + chalk.dim(' to quit watch mode.'), chalk.dim(' \u203A Press ') + 'Enter' + From 242e4624e57d5ff914b8d18e25203650f54dea50 Mon Sep 17 00:00:00 2001 From: Rogelio Guzman Date: Wed, 19 Apr 2017 13:21:30 -0700 Subject: [PATCH 2/6] Add Active Filters UI --- .../jest-cli/src/TestNamePatternPrompt.js | 7 +- .../jest-cli/src/TestPathPatternPrompt.js | 7 +- packages/jest-cli/src/constants.js | 1 + packages/jest-cli/src/watch.js | 72 ++++++++++++++----- 4 files changed, 67 insertions(+), 20 deletions(-) diff --git a/packages/jest-cli/src/TestNamePatternPrompt.js b/packages/jest-cli/src/TestNamePatternPrompt.js index add060156fec..437bc6a5865a 100644 --- a/packages/jest-cli/src/TestNamePatternPrompt.js +++ b/packages/jest-cli/src/TestNamePatternPrompt.js @@ -22,7 +22,7 @@ const formatTestNameByPattern = require('./lib/formatTestNameByPattern'); const pluralizeTest = (total: number) => (total === 1 ? 'test' : 'tests'); const usage = () => - `\n ${chalk.bold('Pattern Mode Usage')}\n` + + `\n${chalk.bold('Pattern Mode Usage')}\n` + ` ${chalk.dim('\u203A Press')} Esc ${chalk.dim('to exit pattern mode.')}\n` + ` ${chalk.dim('\u203A Press')} Enter ` + `${chalk.dim('to apply pattern to all tests.')}\n` + @@ -40,9 +40,12 @@ module.exports = class TestNamePatternPrompt { this._prompt = prompt; } - run(onSuccess: Function, onCancel: Function) { + run(onSuccess: Function, onCancel: Function, options) { this._pipe.write(ansiEscapes.cursorHide); this._pipe.write(ansiEscapes.clearScreen); + if (options && options.header) { + this._pipe.write(options.header); + } this._pipe.write(usage()); this._pipe.write(ansiEscapes.cursorShow); diff --git a/packages/jest-cli/src/TestPathPatternPrompt.js b/packages/jest-cli/src/TestPathPatternPrompt.js index dd1197cc6c44..bd6362510255 100644 --- a/packages/jest-cli/src/TestPathPatternPrompt.js +++ b/packages/jest-cli/src/TestPathPatternPrompt.js @@ -30,7 +30,7 @@ type SearchSources = Array<{| const pluralizeFile = (total: number) => (total === 1 ? 'file' : 'files'); const usage = () => - `\n ${chalk.bold('Pattern Mode Usage')}\n` + + `\n${chalk.bold('Pattern Mode Usage')}\n` + ` ${chalk.dim('\u203A Press')} Esc ${chalk.dim('to exit pattern mode.')}\n` + ` ${chalk.dim('\u203A Press')} Enter ` + `${chalk.dim('to apply pattern to all filenames.')}\n` + @@ -48,9 +48,12 @@ module.exports = class TestPathPatternPrompt { this._prompt = prompt; } - run(onSuccess: Function, onCancel: Function) { + run(onSuccess: Function, onCancel: Function, options) { this._pipe.write(ansiEscapes.cursorHide); this._pipe.write(ansiEscapes.clearScreen); + if (options && options.header) { + this._pipe.write(options.header); + } this._pipe.write(usage()); this._pipe.write(ansiEscapes.cursorShow); diff --git a/packages/jest-cli/src/constants.js b/packages/jest-cli/src/constants.js index b7e24bd42c93..92c28d1c0c3b 100644 --- a/packages/jest-cli/src/constants.js +++ b/packages/jest-cli/src/constants.js @@ -21,6 +21,7 @@ const KEYS = { ARROW_RIGHT: '1b5b43', ARROW_UP: '1b5b41', BACKSPACE: isWindows ? '08' : '7f', + C: '63', CONTROL_C: '03', CONTROL_D: '04', ENTER: '0d', diff --git a/packages/jest-cli/src/watch.js b/packages/jest-cli/src/watch.js index bdaf06be5582..8055b8316dca 100644 --- a/packages/jest-cli/src/watch.js +++ b/packages/jest-cli/src/watch.js @@ -176,6 +176,13 @@ const watch = ( }); startRun(); break; + case KEYS.C: + setState(argv, 'watch', { + testNamePattern: '', + testPathPattern: '', + }); + startRun(); + break; case KEYS.O: setState(argv, 'watch', { testNamePattern: '', @@ -184,24 +191,32 @@ const watch = ( startRun(); break; case KEYS.P: - testPathPatternPrompt.run(testPathPattern => { - setState(argv, 'watch', { - testNamePattern: '', - testPathPattern, - }); + testPathPatternPrompt.run( + testPathPattern => { + setState(argv, 'watch', { + testNamePattern: '', + testPathPattern, + }); - startRun(); - }, onCancelPatternPrompt); + startRun(); + }, + onCancelPatternPrompt, + {header: activeFilters(argv) + '\n'} + ); break; case KEYS.T: - testNamePatternPrompt.run(testNamePattern => { - setState(argv, 'watch', { - testNamePattern, - testPathPattern: '', - }); + testNamePatternPrompt.run( + testNamePattern => { + setState(argv, 'watch', { + testNamePattern, + testPathPattern: argv.testPathPattern, + }); - startRun(); - }, onCancelPatternPrompt); + startRun(); + }, + onCancelPatternPrompt, + {header: activeFilters(argv) + '\n'} + ); break; case KEYS.QUESTION_MARK: break; @@ -235,9 +250,34 @@ const watch = ( return Promise.resolve(); }; +const activeFilters = (argv, delimiter = '\n') => { + const {testNamePattern, testPathPattern} = argv; + if (testNamePattern || testPathPattern) { + const filters = [ + testPathPattern + ? chalk.dim('filename ') + chalk.yellow('/' + testPathPattern + '/') + : null, + testNamePattern + ? chalk.dim('filename ') + chalk.yellow('/' + testPathPattern + '/') + : null, + ].filter(f => !!f).join(', '); + + const messages = [ + '\n' + chalk.bold('Active Filters: ') + filters, + ]; + + return messages.filter(message => !!message).join(delimiter); + } + + return ''; +}; + const usage = (argv, snapshotFailure, delimiter = '\n') => { - /* eslint-disable max-len */ const messages = [ + activeFilters(argv), + (argv.testPathPattern || argv.testNamePattern) + ? chalk.dim(' \u203A Press ') + 'c' + chalk.dim(' to clear filters.') + : null, '\n' + chalk.bold('Watch Usage'), argv.watch ? chalk.dim(' \u203A Press ') + 'a' + chalk.dim(' to run all tests.') @@ -264,7 +304,7 @@ const usage = (argv, snapshotFailure, delimiter = '\n') => { 'Enter' + chalk.dim(' to trigger a test run.'), ]; - /* eslint-enable max-len */ + return messages.filter(message => !!message).join(delimiter) + '\n'; }; From b299c6013a0ac7de12e4b46844b89e99ab6fa073 Mon Sep 17 00:00:00 2001 From: Rogelio Guzman Date: Wed, 19 Apr 2017 13:42:54 -0700 Subject: [PATCH 3/6] Add tests --- .../watch-filename-pattern-mode-test.js.snap | 149 ++++++++++++ .../watch-filename-pattern-mode-test.js | 222 ++++++++++++------ packages/jest-cli/src/watch.js | 178 +++++++------- 3 files changed, 393 insertions(+), 156 deletions(-) diff --git a/packages/jest-cli/src/__tests__/__snapshots__/watch-filename-pattern-mode-test.js.snap b/packages/jest-cli/src/__tests__/__snapshots__/watch-filename-pattern-mode-test.js.snap index 21d9a952f76a..ed9402f99827 100644 --- a/packages/jest-cli/src/__tests__/__snapshots__/watch-filename-pattern-mode-test.js.snap +++ b/packages/jest-cli/src/__tests__/__snapshots__/watch-filename-pattern-mode-test.js.snap @@ -208,6 +208,30 @@ exports[`Watch mode flows Pressing "P" enters pattern mode 8`] = ` [MOCK - cursorRestorePosition]" `; +exports[`Watch mode flows Pressing "c" clears the filters 1`] = ` +"[MOCK - cursorHide] +[MOCK - clearScreen] + + + +Pattern Mode Usage + › Press Esc to exit pattern mode. + › Press Enter to apply pattern to all filenames. + + +[MOCK - cursorShow] + + + + pattern › +[MOCK - cursorSavePosition] + + + Start typing to filter by a filename regex pattern. +[MOCK - cursorTo(11, 5)] +[MOCK - cursorRestorePosition]" +`; + exports[`Watch mode flows Results in pattern mode get truncated appropriately 1`] = ` " @@ -312,3 +336,128 @@ exports[`Watch mode flows Results in pattern mode get truncated appropriately 3` [MOCK - cursorTo(12, 5)] [MOCK - cursorRestorePosition]" `; + +exports[`Watch mode flows Shows the appropiate header when both filters are active 1`] = ` +"[MOCK - cursorHide] +[MOCK - clearScreen] + +Active Filters: filename /p.*10/, test name /test/ + + +Pattern Mode Usage + › Press Esc to exit pattern mode. + › Press Enter to apply pattern to all tests. + + +[MOCK - cursorShow] + + + + pattern › +[MOCK - cursorSavePosition] + + + Start typing to filter by a test name regex pattern. +[MOCK - cursorTo(11, 5)] +[MOCK - cursorRestorePosition]" +`; + +exports[`Watch mode flows Shows the appropiate header when the filename filter is active 1`] = ` +"[MOCK - cursorHide] +[MOCK - clearScreen] + +Active Filters: filename /p.*10/ + + +Pattern Mode Usage + › Press Esc to exit pattern mode. + › Press Enter to apply pattern to all filenames. + + +[MOCK - cursorShow] + + + + pattern › +[MOCK - cursorSavePosition] + + + Start typing to filter by a filename regex pattern. +[MOCK - cursorTo(11, 5)] +[MOCK - cursorRestorePosition]" +`; + +exports[`Watch mode flows Shows the appropiate header when the filename filter is active 2`] = ` +"[MOCK - cursorHide] +[MOCK - clearScreen] + +Active Filters: filename /p/ + + +Pattern Mode Usage + › Press Esc to exit pattern mode. + › Press Enter to apply pattern to all filenames. + + +[MOCK - cursorShow] + + + + pattern › +[MOCK - cursorSavePosition] + + + Start typing to filter by a filename regex pattern. +[MOCK - cursorTo(11, 5)] +[MOCK - cursorRestorePosition]" +`; + +exports[`Watch mode flows Shows the appropiate header when the test name filter is active 1`] = ` +"[MOCK - cursorHide] +[MOCK - clearScreen] + +Active Filters: test name /test/ + + +Pattern Mode Usage + › Press Esc to exit pattern mode. + › Press Enter to apply pattern to all tests. + + +[MOCK - cursorShow] + + + + pattern › +[MOCK - cursorSavePosition] + + + Start typing to filter by a test name regex pattern. +[MOCK - cursorTo(11, 5)] +[MOCK - cursorRestorePosition]" +`; + +exports[`Watch mode flows Shows the appropiate header when the test name filter is active 2`] = ` +"[MOCK - cursorHide] +[MOCK - clearScreen] + +Active Filters: test name /t/ + + +Pattern Mode Usage + › Press Esc to exit pattern mode. + › Press Enter to apply pattern to all tests. + + +[MOCK - cursorShow] + + + + pattern › +[MOCK - cursorSavePosition] + + + Start typing to filter by a test name regex pattern. +[MOCK - cursorTo(11, 5)] +[MOCK - cursorRestorePosition]" +`; diff --git a/packages/jest-cli/src/__tests__/watch-filename-pattern-mode-test.js b/packages/jest-cli/src/__tests__/watch-filename-pattern-mode-test.js index ea9b732bd34a..5cdd91f83b4b 100644 --- a/packages/jest-cli/src/__tests__/watch-filename-pattern-mode-test.js +++ b/packages/jest-cli/src/__tests__/watch-filename-pattern-mode-test.js @@ -8,87 +8,89 @@ * @emails oncall+jsinfra */ -'use strict'; +"use strict"; -const chalk = require('chalk'); -const {KEYS} = require('../constants'); +const chalk = require("chalk"); +const { KEYS } = require("../constants"); const runJestMock = jest.fn(); let terminalWidth; -jest.mock('ansi-escapes', () => ({ - clearScreen: '[MOCK - clearScreen]', +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})]`, + 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; - } - - findMatchingTests(pattern) { - const paths = [ - './path/to/file1-test.js', - './path/to/file2-test.js', - './path/to/file3-test.js', - './path/to/file4-test.js', - './path/to/file5-test.js', - './path/to/file6-test.js', - './path/to/file7-test.js', - './path/to/file8-test.js', - './path/to/file9-test.js', - './path/to/file10-test.js', - './path/to/file11-test.js', - ].filter(path => path.match(pattern)); - - return { - tests: paths.map(path => ({ - context: this._context, - duration: null, - path, - })), - }; + "../SearchSource", + () => + class { + constructor(context) { + this._context = context; + } + + findMatchingTests(pattern) { + const paths = [ + "./path/to/file1-test.js", + "./path/to/file2-test.js", + "./path/to/file3-test.js", + "./path/to/file4-test.js", + "./path/to/file5-test.js", + "./path/to/file6-test.js", + "./path/to/file7-test.js", + "./path/to/file8-test.js", + "./path/to/file9-test.js", + "./path/to/file10-test.js", + "./path/to/file11-test.js" + ].filter(path => path.match(pattern)); + + return { + tests: paths.map(path => ({ + context: this._context, + duration: null, + path + })) + }; + } } - }, ); -jest.doMock('chalk', () => - Object.assign(new chalk.constructor({enabled: false}), { - stripColor: str => str, - }), -); +jest.doMock("chalk", () => + Object.assign(new chalk.constructor({ enabled: false }), { + stripColor: str => str + })); jest.doMock( - '../runJest', + "../runJest", () => function() { const args = Array.from(arguments); runJestMock.apply(null, args); // Call the callback - args[args.length - 1]({snapshot: {}}); + args[args.length - 1]({ snapshot: {} }); return Promise.resolve(); - }, + } ); -jest.doMock('../lib/terminalUtils', () => ({ - getTerminalWidth: () => terminalWidth, +jest.doMock("../lib/terminalUtils", () => ({ + getTerminalWidth: () => terminalWidth })); -const watch = require('../watch'); +const watch = require("../watch"); + +const toHex = char => Number(char.charCodeAt(0)).toString(16); afterEach(runJestMock.mockReset); -describe('Watch mode flows', () => { +describe("Watch mode flows", () => { let pipe; let hasteMapInstances; let argv; @@ -97,35 +99,33 @@ describe('Watch mode flows', () => { beforeEach(() => { terminalWidth = 80; - pipe = {write: jest.fn()}; - hasteMapInstances = [{on: () => {}}]; + pipe = { write: jest.fn() }; + hasteMapInstances = [{ on: () => {} }]; argv = {}; - contexts = [{config: {}}]; + contexts = [{ config: {} }]; stdin = new MockStdin(); }); it('Pressing "P" enters pattern mode', () => { - contexts[0].config = {rootDir: ''}; + contexts[0].config = { rootDir: "" }; watch(contexts, argv, pipe, hasteMapInstances, stdin); // Write a enter pattern mode stdin.emit(KEYS.P); - expect(pipe.write).toBeCalledWith(' pattern › '); + expect(pipe.write).toBeCalledWith(" pattern › "); const assertPattern = hex => { pipe.write.mockReset(); stdin.emit(hex); - expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); + expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); }; - const toHex = char => Number(char.charCodeAt(0)).toString(16); - // Write a pattern - ['p', '.', '*', '1', '0'].map(toHex).forEach(assertPattern); + ["p", ".", "*", "1", "0"].map(toHex).forEach(assertPattern); [KEYS.BACKSPACE, KEYS.BACKSPACE].forEach(assertPattern); - ['3'].map(toHex).forEach(assertPattern); + ["3"].map(toHex).forEach(assertPattern); // Runs Jest again runJestMock.mockReset(); @@ -135,14 +135,14 @@ describe('Watch mode flows', () => { // Argv is updated with the current pattern expect(argv).toEqual({ onlyChanged: false, - testPathPattern: 'p.*3', + testPathPattern: "p.*3", watch: true, - watchAll: false, + watchAll: false }); }); - it('Results in pattern mode get truncated appropriately', () => { - contexts[0].config = {rootDir: ''}; + it("Results in pattern mode get truncated appropriately", () => { + contexts[0].config = { rootDir: "" }; watch(contexts, argv, pipe, hasteMapInstances, stdin); stdin.emit(KEYS.P); @@ -152,9 +152,99 @@ describe('Watch mode flows', () => { stdin.emit(KEYS.BACKSPACE); pipe.write.mockReset(); stdin.emit(KEYS.A); - expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); + expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); }); }); + + it("Shows the appropiate header when the filename filter is active", () => { + contexts[0].config = { rootDir: "" }; + watch(contexts, argv, pipe, hasteMapInstances, stdin); + + stdin.emit(KEYS.P); + + ["p", ".", "*", "1", "0"] + .map(toHex) + .concat(KEYS.ENTER) + .forEach(key => stdin.emit(key)); + + pipe.write.mockReset(); + stdin.emit(KEYS.P); + expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); + + ["p"].map(toHex).concat(KEYS.ENTER).forEach(key => stdin.emit(key)); + + pipe.write.mockReset(); + stdin.emit(KEYS.P); + expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); + }); + + it("Shows the appropiate header when the test name filter is active", () => { + contexts[0].config = { rootDir: "" }; + watch(contexts, argv, pipe, hasteMapInstances, stdin); + + stdin.emit(KEYS.T); + + ["t", "e", "s", "t"] + .map(toHex) + .concat(KEYS.ENTER) + .forEach(key => stdin.emit(key)); + + pipe.write.mockReset(); + stdin.emit(KEYS.T); + expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); + + ["t"].map(toHex).concat(KEYS.ENTER).forEach(key => stdin.emit(key)); + + pipe.write.mockReset(); + stdin.emit(KEYS.T); + expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); + }); + + it("Shows the appropiate header when both filters are active", () => { + contexts[0].config = { rootDir: "" }; + watch(contexts, argv, pipe, hasteMapInstances, stdin); + + stdin.emit(KEYS.P); + + ["p", ".", "*", "1", "0"] + .map(toHex) + .concat(KEYS.ENTER) + .forEach(key => stdin.emit(key)); + + stdin.emit(KEYS.T); + ["t", "e", "s", "t"] + .map(toHex) + .concat(KEYS.ENTER) + .forEach(key => stdin.emit(key)); + + pipe.write.mockReset(); + stdin.emit(KEYS.T); + expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); + }); + + it('Pressing "c" clears the filters', () => { + contexts[0].config = { rootDir: "" }; + watch(contexts, argv, pipe, hasteMapInstances, stdin); + + stdin.emit(KEYS.P); + + ["p", ".", "*", "1", "0"] + .map(toHex) + .concat(KEYS.ENTER) + .forEach(key => stdin.emit(key)); + + stdin.emit(KEYS.T); + ["t", "e", "s", "t"] + .map(toHex) + .concat(KEYS.ENTER) + .forEach(key => stdin.emit(key)); + + stdin.emit(KEYS.C); + + pipe.write.mockReset(); + stdin.emit(KEYS.P); + expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); + }); }); class MockStdin { diff --git a/packages/jest-cli/src/watch.js b/packages/jest-cli/src/watch.js index 8055b8316dca..8456a875ced5 100644 --- a/packages/jest-cli/src/watch.js +++ b/packages/jest-cli/src/watch.js @@ -7,26 +7,26 @@ * * @flow */ -'use strict'; +"use strict"; -import type {Context} from 'types/Context'; +import type { Context } from "types/Context"; -const ansiEscapes = require('ansi-escapes'); -const chalk = require('chalk'); -const createContext = require('./lib/createContext'); -const HasteMap = require('jest-haste-map'); -const isCI = require('is-ci'); +const ansiEscapes = require("ansi-escapes"); +const chalk = require("chalk"); +const createContext = require("./lib/createContext"); +const HasteMap = require("jest-haste-map"); +const isCI = require("is-ci"); const isInteractive = process.stdout.isTTY && !isCI; -const isValidPath = require('./lib/isValidPath'); -const preRunMessage = require('./preRunMessage'); -const runJest = require('./runJest'); -const setState = require('./lib/setState'); -const SearchSource = require('./SearchSource'); -const TestWatcher = require('./TestWatcher'); -const Prompt = require('./lib/Prompt'); -const TestPathPatternPrompt = require('./TestPathPatternPrompt'); -const TestNamePatternPrompt = require('./TestNamePatternPrompt'); -const {KEYS, CLEAR} = require('./constants'); +const isValidPath = require("./lib/isValidPath"); +const preRunMessage = require("./preRunMessage"); +const runJest = require("./runJest"); +const setState = require("./lib/setState"); +const SearchSource = require("./SearchSource"); +const TestWatcher = require("./TestWatcher"); +const Prompt = require("./lib/Prompt"); +const TestPathPatternPrompt = require("./TestPathPatternPrompt"); +const TestNamePatternPrompt = require("./TestNamePatternPrompt"); +const { KEYS, CLEAR } = require("./constants"); let hasExitListener = false; @@ -35,12 +35,12 @@ const watch = ( argv: Object, pipe: stream$Writable | tty$WriteStream, hasteMapInstances: Array, - stdin?: stream$Readable | tty$ReadStream = process.stdin, + stdin?: stream$Readable | tty$ReadStream = process.stdin ) => { - setState(argv, argv.watch ? 'watch' : 'watchAll', { + setState(argv, argv.watch ? "watch" : "watchAll", { testNamePattern: argv.testNamePattern, testPathPattern: argv.testPathPattern || - (Array.isArray(argv._) ? argv._.join('|') : ''), + (Array.isArray(argv._) ? argv._.join("|") : "") }); const prompt = new Prompt(); @@ -48,7 +48,7 @@ const watch = ( const testNamePatternPrompt = new TestNamePatternPrompt(pipe, prompt); let searchSources = contexts.map(context => ({ context, - searchSource: new SearchSource(context), + searchSource: new SearchSource(context) })); let hasSnapshotFailure = false; let isRunning = false; @@ -59,8 +59,8 @@ const watch = ( testPathPatternPrompt.updateSearchSources(searchSources); hasteMapInstances.forEach((hasteMapInstance, index) => { - hasteMapInstance.on('change', ({eventsQueue, hasteFS, moduleMap}) => { - const validPaths = eventsQueue.filter(({filePath}) => { + hasteMapInstance.on("change", ({ eventsQueue, hasteFS, moduleMap }) => { + const validPaths = eventsQueue.filter(({ filePath }) => { return isValidPath(contexts[index].config, filePath); }); @@ -69,14 +69,14 @@ const watch = ( contexts[index].config, { hasteFS, - moduleMap, - }, + moduleMap + } )); prompt.abort(); searchSources = searchSources.slice(); searchSources[index] = { context, - searchSource: new SearchSource(context), + searchSource: new SearchSource(context) }; testPathPatternPrompt.updateSearchSources(searchSources); startRun(); @@ -86,7 +86,7 @@ const watch = ( if (!hasExitListener) { hasExitListener = true; - process.on('exit', () => { + process.on("exit", () => { if (prompt.isEntering()) { pipe.write(ansiEscapes.cursorDown()); pipe.write(ansiEscapes.eraseDown); @@ -99,7 +99,7 @@ const watch = ( return null; } - testWatcher = new TestWatcher({isWatchMode: true}); + testWatcher = new TestWatcher({ isWatchMode: true }); isInteractive && pipe.write(CLEAR); preRunMessage.print(pipe); isRunning = true; @@ -110,11 +110,11 @@ const watch = ( Object.assign( { testNamePattern: argv.testNamePattern, - testPathPattern: argv.testPathPattern, + testPathPattern: argv.testPathPattern }, context.config, - overrideConfig, - ), + overrideConfig + ) ); }); return runJest(contexts, argv, pipe, testWatcher, startRun, results => { @@ -123,7 +123,7 @@ const watch = ( // 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}); + testWatcher = new TestWatcher({ isWatchMode: true }); if (shouldDisplayWatchUsage) { pipe.write(usage(argv, hasSnapshotFailure)); shouldDisplayWatchUsage = false; // hide Watch Usage after first run @@ -155,7 +155,7 @@ const watch = ( testWatcher && [KEYS.Q, KEYS.ENTER, KEYS.A, KEYS.O, KEYS.P, KEYS.T].indexOf(key) !== -1 ) { - testWatcher.setState({interrupted: true}); + testWatcher.setState({ interrupted: true }); return; } @@ -167,55 +167,55 @@ const watch = ( startRun(); break; case KEYS.U: - startRun({updateSnapshot: true}); + startRun({ updateSnapshot: true }); break; case KEYS.A: - setState(argv, 'watchAll', { - testNamePattern: '', - testPathPattern: '', + setState(argv, "watchAll", { + testNamePattern: "", + testPathPattern: "" }); startRun(); break; case KEYS.C: - setState(argv, 'watch', { - testNamePattern: '', - testPathPattern: '', + setState(argv, "watch", { + testNamePattern: "", + testPathPattern: "" }); startRun(); break; case KEYS.O: - setState(argv, 'watch', { - testNamePattern: '', - testPathPattern: '', + setState(argv, "watch", { + testNamePattern: "", + testPathPattern: "" }); startRun(); break; case KEYS.P: testPathPatternPrompt.run( testPathPattern => { - setState(argv, 'watch', { - testNamePattern: '', - testPathPattern, + setState(argv, "watch", { + testNamePattern: "", + testPathPattern }); startRun(); }, onCancelPatternPrompt, - {header: activeFilters(argv) + '\n'} + { header: activeFilters(argv) + "\n" } ); break; case KEYS.T: testNamePatternPrompt.run( testNamePattern => { - setState(argv, 'watch', { + setState(argv, "watch", { testNamePattern, - testPathPattern: argv.testPathPattern, + testPathPattern: argv.testPathPattern }); startRun(); }, onCancelPatternPrompt, - {header: activeFilters(argv) + '\n'} + { header: activeFilters(argv) + "\n" } ); break; case KEYS.QUESTION_MARK: @@ -239,80 +239,78 @@ const watch = ( pipe.write(ansiEscapes.cursorShow); }; - if (typeof stdin.setRawMode === 'function') { + if (typeof stdin.setRawMode === "function") { stdin.setRawMode(true); stdin.resume(); - stdin.setEncoding('hex'); - stdin.on('data', onKeypress); + stdin.setEncoding("hex"); + stdin.on("data", onKeypress); } startRun(); return Promise.resolve(); }; -const activeFilters = (argv, delimiter = '\n') => { - const {testNamePattern, testPathPattern} = argv; +const activeFilters = (argv, delimiter = "\n") => { + const { testNamePattern, testPathPattern } = argv; if (testNamePattern || testPathPattern) { const filters = [ testPathPattern - ? chalk.dim('filename ') + chalk.yellow('/' + testPathPattern + '/') + ? chalk.dim("filename ") + chalk.yellow("/" + testPathPattern + "/") : null, testNamePattern - ? chalk.dim('filename ') + chalk.yellow('/' + testPathPattern + '/') - : null, - ].filter(f => !!f).join(', '); + ? chalk.dim("test name ") + chalk.yellow("/" + testNamePattern + "/") + : null + ] + .filter(f => !!f) + .join(", "); - const messages = [ - '\n' + chalk.bold('Active Filters: ') + filters, - ]; + const messages = ["\n" + chalk.bold("Active Filters: ") + filters]; return messages.filter(message => !!message).join(delimiter); } - return ''; + return ""; }; -const usage = (argv, snapshotFailure, delimiter = '\n') => { +const usage = (argv, snapshotFailure, delimiter = "\n") => { const messages = [ activeFilters(argv), - (argv.testPathPattern || argv.testNamePattern) - ? chalk.dim(' \u203A Press ') + 'c' + chalk.dim(' to clear filters.') + argv.testPathPattern || argv.testNamePattern + ? chalk.dim(" \u203A Press ") + "c" + chalk.dim(" to clear filters.") : null, - '\n' + chalk.bold('Watch Usage'), + "\n" + chalk.bold("Watch Usage"), argv.watch - ? chalk.dim(' \u203A Press ') + 'a' + chalk.dim(' to run all tests.') + ? chalk.dim(" \u203A Press ") + "a" + chalk.dim(" to run all tests.") : null, (argv.watchAll || argv.testPathPattern || argv.testNamePattern) && !argv.noSCM - ? chalk.dim(' \u203A Press ') + - 'o' + - chalk.dim(' to only run tests related to changed files.') + ? chalk.dim(" \u203A Press ") + + "o" + + chalk.dim(" to only run tests related to changed files.") : null, snapshotFailure - ? chalk.dim(' \u203A Press ') + - 'u' + - chalk.dim(' to update failing snapshots.') + ? chalk.dim(" \u203A Press ") + + "u" + + chalk.dim(" to update failing snapshots.") : null, - chalk.dim(' \u203A Press ') + - 'p' + - chalk.dim(' to filter by a filename regex pattern.'), - chalk.dim(' \u203A Press ') + - 't' + - chalk.dim(' to filter by a test name regex pattern.'), - chalk.dim(' \u203A Press ') + 'q' + chalk.dim(' to quit watch mode.'), - chalk.dim(' \u203A Press ') + - 'Enter' + - chalk.dim(' to trigger a test run.'), + chalk.dim(" \u203A Press ") + + "p" + + chalk.dim(" to filter by a filename regex pattern."), + chalk.dim(" \u203A Press ") + + "t" + + chalk.dim(" to filter by a test name regex pattern."), + chalk.dim(" \u203A Press ") + "q" + chalk.dim(" to quit watch mode."), + chalk.dim(" \u203A Press ") + "Enter" + chalk.dim(" to trigger a test run.") ]; - return messages.filter(message => !!message).join(delimiter) + '\n'; + return messages.filter(message => !!message).join(delimiter) + "\n"; }; const showToggleUsagePrompt = () => - '\n' + - chalk.bold('Watch Usage: ') + - chalk.dim('Press ') + - 'w' + - chalk.dim(' to show more.'); + "\n" + + chalk.bold("Watch Usage: ") + + chalk.dim("Press ") + + "w" + + chalk.dim(" to show more."); module.exports = watch; From 34bdbf22643d440e9459203e91ca9d3d52cc3994 Mon Sep 17 00:00:00 2001 From: Rogelio Guzman Date: Thu, 20 Apr 2017 12:29:27 -0700 Subject: [PATCH 4/6] Add appropritate flow types --- packages/jest-cli/src/TestNamePatternPrompt.js | 4 ++-- packages/jest-cli/src/TestPathPatternPrompt.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/jest-cli/src/TestNamePatternPrompt.js b/packages/jest-cli/src/TestNamePatternPrompt.js index 437bc6a5865a..9e2064d6fb13 100644 --- a/packages/jest-cli/src/TestNamePatternPrompt.js +++ b/packages/jest-cli/src/TestNamePatternPrompt.js @@ -40,11 +40,11 @@ module.exports = class TestNamePatternPrompt { this._prompt = prompt; } - run(onSuccess: Function, onCancel: Function, options) { + run(onSuccess: Function, onCancel: Function, options?: { header: string }) { this._pipe.write(ansiEscapes.cursorHide); this._pipe.write(ansiEscapes.clearScreen); if (options && options.header) { - this._pipe.write(options.header); + this._pipe.write(options.header); } this._pipe.write(usage()); this._pipe.write(ansiEscapes.cursorShow); diff --git a/packages/jest-cli/src/TestPathPatternPrompt.js b/packages/jest-cli/src/TestPathPatternPrompt.js index bd6362510255..567811aca97f 100644 --- a/packages/jest-cli/src/TestPathPatternPrompt.js +++ b/packages/jest-cli/src/TestPathPatternPrompt.js @@ -48,11 +48,11 @@ module.exports = class TestPathPatternPrompt { this._prompt = prompt; } - run(onSuccess: Function, onCancel: Function, options) { + run(onSuccess: Function, onCancel: Function, options?: { header: string }) { this._pipe.write(ansiEscapes.cursorHide); this._pipe.write(ansiEscapes.clearScreen); if (options && options.header) { - this._pipe.write(options.header); + this._pipe.write(options.header); } this._pipe.write(usage()); this._pipe.write(ansiEscapes.cursorShow); From 78266f6032b5a1d935002f52e9b4166353fd9a9c Mon Sep 17 00:00:00 2001 From: Rogelio Guzman Date: Fri, 21 Apr 2017 12:42:18 -0700 Subject: [PATCH 5/6] Run prettier --- .../jest-cli/src/TestNamePatternPrompt.js | 7 +- .../jest-cli/src/TestPathPatternPrompt.js | 7 +- .../watch-filename-pattern-mode-test.js | 138 +++++++------- packages/jest-cli/src/watch.js | 172 +++++++++--------- 4 files changed, 162 insertions(+), 162 deletions(-) diff --git a/packages/jest-cli/src/TestNamePatternPrompt.js b/packages/jest-cli/src/TestNamePatternPrompt.js index 9e2064d6fb13..8087131bc6f1 100644 --- a/packages/jest-cli/src/TestNamePatternPrompt.js +++ b/packages/jest-cli/src/TestNamePatternPrompt.js @@ -19,7 +19,7 @@ const stringLength = require('string-length'); const Prompt = require('./lib/Prompt'); const formatTestNameByPattern = require('./lib/formatTestNameByPattern'); -const pluralizeTest = (total: number) => (total === 1 ? 'test' : 'tests'); +const pluralizeTest = (total: number) => total === 1 ? 'test' : 'tests'; const usage = () => `\n${chalk.bold('Pattern Mode Usage')}\n` + @@ -40,7 +40,7 @@ module.exports = class TestNamePatternPrompt { this._prompt = prompt; } - run(onSuccess: Function, onCancel: Function, options?: { header: string }) { + run(onSuccess: Function, onCancel: Function, options?: {header: string}) { this._pipe.write(ansiEscapes.cursorHide); this._pipe.write(ansiEscapes.clearScreen); if (options && options.header) { @@ -124,8 +124,7 @@ module.exports = class TestNamePatternPrompt { if (regex.test(title)) { matchedTests.push(title); } - }), - ); + })); return matchedTests; } diff --git a/packages/jest-cli/src/TestPathPatternPrompt.js b/packages/jest-cli/src/TestPathPatternPrompt.js index 567811aca97f..42ac52fb5a43 100644 --- a/packages/jest-cli/src/TestPathPatternPrompt.js +++ b/packages/jest-cli/src/TestPathPatternPrompt.js @@ -27,7 +27,7 @@ type SearchSources = Array<{| searchSource: SearchSource, |}>; -const pluralizeFile = (total: number) => (total === 1 ? 'file' : 'files'); +const pluralizeFile = (total: number) => total === 1 ? 'file' : 'files'; const usage = () => `\n${chalk.bold('Pattern Mode Usage')}\n` + @@ -48,7 +48,7 @@ module.exports = class TestPathPatternPrompt { this._prompt = prompt; } - run(onSuccess: Function, onCancel: Function, options?: { header: string }) { + run(onSuccess: Function, onCancel: Function, options?: {header: string}) { this._pipe.write(ansiEscapes.cursorHide); this._pipe.write(ansiEscapes.clearScreen); if (options && options.header) { @@ -112,8 +112,7 @@ module.exports = class TestPathPatternPrompt { return highlight(path, filePath, pattern, context.config.rootDir); }) .forEach(filePath => - this._pipe.write(`\n ${chalk.dim('\u203A')} ${filePath}`), - ); + this._pipe.write(`\n ${chalk.dim('\u203A')} ${filePath}`)); if (total > max) { const more = total - max; diff --git a/packages/jest-cli/src/__tests__/watch-filename-pattern-mode-test.js b/packages/jest-cli/src/__tests__/watch-filename-pattern-mode-test.js index 5cdd91f83b4b..ca1dbd1fdd0b 100644 --- a/packages/jest-cli/src/__tests__/watch-filename-pattern-mode-test.js +++ b/packages/jest-cli/src/__tests__/watch-filename-pattern-mode-test.js @@ -8,27 +8,27 @@ * @emails oncall+jsinfra */ -"use strict"; +'use strict'; -const chalk = require("chalk"); -const { KEYS } = require("../constants"); +const chalk = require('chalk'); +const {KEYS} = require('../constants'); const runJestMock = jest.fn(); let terminalWidth; -jest.mock("ansi-escapes", () => ({ - clearScreen: "[MOCK - clearScreen]", +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})]` + cursorHide: '[MOCK - cursorHide]', + cursorRestorePosition: '[MOCK - cursorRestorePosition]', + cursorSavePosition: '[MOCK - cursorSavePosition]', + cursorShow: '[MOCK - cursorShow]', + cursorTo: (x, y) => `[MOCK - cursorTo(${x}, ${y})]`, })); jest.mock( - "../SearchSource", + '../SearchSource', () => class { constructor(context) { @@ -37,60 +37,60 @@ jest.mock( findMatchingTests(pattern) { const paths = [ - "./path/to/file1-test.js", - "./path/to/file2-test.js", - "./path/to/file3-test.js", - "./path/to/file4-test.js", - "./path/to/file5-test.js", - "./path/to/file6-test.js", - "./path/to/file7-test.js", - "./path/to/file8-test.js", - "./path/to/file9-test.js", - "./path/to/file10-test.js", - "./path/to/file11-test.js" + './path/to/file1-test.js', + './path/to/file2-test.js', + './path/to/file3-test.js', + './path/to/file4-test.js', + './path/to/file5-test.js', + './path/to/file6-test.js', + './path/to/file7-test.js', + './path/to/file8-test.js', + './path/to/file9-test.js', + './path/to/file10-test.js', + './path/to/file11-test.js', ].filter(path => path.match(pattern)); return { tests: paths.map(path => ({ context: this._context, duration: null, - path - })) + path, + })), }; } - } + }, ); -jest.doMock("chalk", () => - Object.assign(new chalk.constructor({ enabled: false }), { - stripColor: str => str +jest.doMock('chalk', () => + Object.assign(new chalk.constructor({enabled: false}), { + stripColor: str => str, })); jest.doMock( - "../runJest", + '../runJest', () => function() { const args = Array.from(arguments); runJestMock.apply(null, args); // Call the callback - args[args.length - 1]({ snapshot: {} }); + args[args.length - 1]({snapshot: {}}); return Promise.resolve(); - } + }, ); -jest.doMock("../lib/terminalUtils", () => ({ - getTerminalWidth: () => terminalWidth +jest.doMock('../lib/terminalUtils', () => ({ + getTerminalWidth: () => terminalWidth, })); -const watch = require("../watch"); +const watch = require('../watch'); const toHex = char => Number(char.charCodeAt(0)).toString(16); afterEach(runJestMock.mockReset); -describe("Watch mode flows", () => { +describe('Watch mode flows', () => { let pipe; let hasteMapInstances; let argv; @@ -99,33 +99,33 @@ describe("Watch mode flows", () => { beforeEach(() => { terminalWidth = 80; - pipe = { write: jest.fn() }; - hasteMapInstances = [{ on: () => {} }]; + pipe = {write: jest.fn()}; + hasteMapInstances = [{on: () => {}}]; argv = {}; - contexts = [{ config: {} }]; + contexts = [{config: {}}]; stdin = new MockStdin(); }); it('Pressing "P" enters pattern mode', () => { - contexts[0].config = { rootDir: "" }; + contexts[0].config = {rootDir: ''}; watch(contexts, argv, pipe, hasteMapInstances, stdin); // Write a enter pattern mode stdin.emit(KEYS.P); - expect(pipe.write).toBeCalledWith(" pattern › "); + expect(pipe.write).toBeCalledWith(' pattern › '); const assertPattern = hex => { pipe.write.mockReset(); stdin.emit(hex); - expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); + expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); }; // Write a pattern - ["p", ".", "*", "1", "0"].map(toHex).forEach(assertPattern); + ['p', '.', '*', '1', '0'].map(toHex).forEach(assertPattern); [KEYS.BACKSPACE, KEYS.BACKSPACE].forEach(assertPattern); - ["3"].map(toHex).forEach(assertPattern); + ['3'].map(toHex).forEach(assertPattern); // Runs Jest again runJestMock.mockReset(); @@ -135,14 +135,14 @@ describe("Watch mode flows", () => { // Argv is updated with the current pattern expect(argv).toEqual({ onlyChanged: false, - testPathPattern: "p.*3", + testPathPattern: 'p.*3', watch: true, - watchAll: false + watchAll: false, }); }); - it("Results in pattern mode get truncated appropriately", () => { - contexts[0].config = { rootDir: "" }; + it('Results in pattern mode get truncated appropriately', () => { + contexts[0].config = {rootDir: ''}; watch(contexts, argv, pipe, hasteMapInstances, stdin); stdin.emit(KEYS.P); @@ -152,89 +152,89 @@ describe("Watch mode flows", () => { stdin.emit(KEYS.BACKSPACE); pipe.write.mockReset(); stdin.emit(KEYS.A); - expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); + expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); }); }); - it("Shows the appropiate header when the filename filter is active", () => { - contexts[0].config = { rootDir: "" }; + it('Shows the appropiate header when the filename filter is active', () => { + contexts[0].config = {rootDir: ''}; watch(contexts, argv, pipe, hasteMapInstances, stdin); stdin.emit(KEYS.P); - ["p", ".", "*", "1", "0"] + ['p', '.', '*', '1', '0'] .map(toHex) .concat(KEYS.ENTER) .forEach(key => stdin.emit(key)); pipe.write.mockReset(); stdin.emit(KEYS.P); - expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); + expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); - ["p"].map(toHex).concat(KEYS.ENTER).forEach(key => stdin.emit(key)); + ['p'].map(toHex).concat(KEYS.ENTER).forEach(key => stdin.emit(key)); pipe.write.mockReset(); stdin.emit(KEYS.P); - expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); + expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); }); - it("Shows the appropiate header when the test name filter is active", () => { - contexts[0].config = { rootDir: "" }; + it('Shows the appropiate header when the test name filter is active', () => { + contexts[0].config = {rootDir: ''}; watch(contexts, argv, pipe, hasteMapInstances, stdin); stdin.emit(KEYS.T); - ["t", "e", "s", "t"] + ['t', 'e', 's', 't'] .map(toHex) .concat(KEYS.ENTER) .forEach(key => stdin.emit(key)); pipe.write.mockReset(); stdin.emit(KEYS.T); - expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); + expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); - ["t"].map(toHex).concat(KEYS.ENTER).forEach(key => stdin.emit(key)); + ['t'].map(toHex).concat(KEYS.ENTER).forEach(key => stdin.emit(key)); pipe.write.mockReset(); stdin.emit(KEYS.T); - expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); + expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); }); - it("Shows the appropiate header when both filters are active", () => { - contexts[0].config = { rootDir: "" }; + it('Shows the appropiate header when both filters are active', () => { + contexts[0].config = {rootDir: ''}; watch(contexts, argv, pipe, hasteMapInstances, stdin); stdin.emit(KEYS.P); - ["p", ".", "*", "1", "0"] + ['p', '.', '*', '1', '0'] .map(toHex) .concat(KEYS.ENTER) .forEach(key => stdin.emit(key)); stdin.emit(KEYS.T); - ["t", "e", "s", "t"] + ['t', 'e', 's', 't'] .map(toHex) .concat(KEYS.ENTER) .forEach(key => stdin.emit(key)); pipe.write.mockReset(); stdin.emit(KEYS.T); - expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); + expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); }); it('Pressing "c" clears the filters', () => { - contexts[0].config = { rootDir: "" }; + contexts[0].config = {rootDir: ''}; watch(contexts, argv, pipe, hasteMapInstances, stdin); stdin.emit(KEYS.P); - ["p", ".", "*", "1", "0"] + ['p', '.', '*', '1', '0'] .map(toHex) .concat(KEYS.ENTER) .forEach(key => stdin.emit(key)); stdin.emit(KEYS.T); - ["t", "e", "s", "t"] + ['t', 'e', 's', 't'] .map(toHex) .concat(KEYS.ENTER) .forEach(key => stdin.emit(key)); @@ -243,7 +243,7 @@ describe("Watch mode flows", () => { pipe.write.mockReset(); stdin.emit(KEYS.P); - expect(pipe.write.mock.calls.join("\n")).toMatchSnapshot(); + expect(pipe.write.mock.calls.join('\n')).toMatchSnapshot(); }); }); diff --git a/packages/jest-cli/src/watch.js b/packages/jest-cli/src/watch.js index 8456a875ced5..dff2c06f8690 100644 --- a/packages/jest-cli/src/watch.js +++ b/packages/jest-cli/src/watch.js @@ -7,26 +7,26 @@ * * @flow */ -"use strict"; +'use strict'; -import type { Context } from "types/Context"; +import type {Context} from 'types/Context'; -const ansiEscapes = require("ansi-escapes"); -const chalk = require("chalk"); -const createContext = require("./lib/createContext"); -const HasteMap = require("jest-haste-map"); -const isCI = require("is-ci"); +const ansiEscapes = require('ansi-escapes'); +const chalk = require('chalk'); +const createContext = require('./lib/createContext'); +const HasteMap = require('jest-haste-map'); +const isCI = require('is-ci'); const isInteractive = process.stdout.isTTY && !isCI; -const isValidPath = require("./lib/isValidPath"); -const preRunMessage = require("./preRunMessage"); -const runJest = require("./runJest"); -const setState = require("./lib/setState"); -const SearchSource = require("./SearchSource"); -const TestWatcher = require("./TestWatcher"); -const Prompt = require("./lib/Prompt"); -const TestPathPatternPrompt = require("./TestPathPatternPrompt"); -const TestNamePatternPrompt = require("./TestNamePatternPrompt"); -const { KEYS, CLEAR } = require("./constants"); +const isValidPath = require('./lib/isValidPath'); +const preRunMessage = require('./preRunMessage'); +const runJest = require('./runJest'); +const setState = require('./lib/setState'); +const SearchSource = require('./SearchSource'); +const TestWatcher = require('./TestWatcher'); +const Prompt = require('./lib/Prompt'); +const TestPathPatternPrompt = require('./TestPathPatternPrompt'); +const TestNamePatternPrompt = require('./TestNamePatternPrompt'); +const {KEYS, CLEAR} = require('./constants'); let hasExitListener = false; @@ -35,12 +35,12 @@ const watch = ( argv: Object, pipe: stream$Writable | tty$WriteStream, hasteMapInstances: Array, - stdin?: stream$Readable | tty$ReadStream = process.stdin + stdin?: stream$Readable | tty$ReadStream = process.stdin, ) => { - setState(argv, argv.watch ? "watch" : "watchAll", { + setState(argv, argv.watch ? 'watch' : 'watchAll', { testNamePattern: argv.testNamePattern, testPathPattern: argv.testPathPattern || - (Array.isArray(argv._) ? argv._.join("|") : "") + (Array.isArray(argv._) ? argv._.join('|') : ''), }); const prompt = new Prompt(); @@ -48,7 +48,7 @@ const watch = ( const testNamePatternPrompt = new TestNamePatternPrompt(pipe, prompt); let searchSources = contexts.map(context => ({ context, - searchSource: new SearchSource(context) + searchSource: new SearchSource(context), })); let hasSnapshotFailure = false; let isRunning = false; @@ -59,8 +59,8 @@ const watch = ( testPathPatternPrompt.updateSearchSources(searchSources); hasteMapInstances.forEach((hasteMapInstance, index) => { - hasteMapInstance.on("change", ({ eventsQueue, hasteFS, moduleMap }) => { - const validPaths = eventsQueue.filter(({ filePath }) => { + hasteMapInstance.on('change', ({eventsQueue, hasteFS, moduleMap}) => { + const validPaths = eventsQueue.filter(({filePath}) => { return isValidPath(contexts[index].config, filePath); }); @@ -69,14 +69,14 @@ const watch = ( contexts[index].config, { hasteFS, - moduleMap - } + moduleMap, + }, )); prompt.abort(); searchSources = searchSources.slice(); searchSources[index] = { context, - searchSource: new SearchSource(context) + searchSource: new SearchSource(context), }; testPathPatternPrompt.updateSearchSources(searchSources); startRun(); @@ -86,7 +86,7 @@ const watch = ( if (!hasExitListener) { hasExitListener = true; - process.on("exit", () => { + process.on('exit', () => { if (prompt.isEntering()) { pipe.write(ansiEscapes.cursorDown()); pipe.write(ansiEscapes.eraseDown); @@ -99,7 +99,7 @@ const watch = ( return null; } - testWatcher = new TestWatcher({ isWatchMode: true }); + testWatcher = new TestWatcher({isWatchMode: true}); isInteractive && pipe.write(CLEAR); preRunMessage.print(pipe); isRunning = true; @@ -110,11 +110,11 @@ const watch = ( Object.assign( { testNamePattern: argv.testNamePattern, - testPathPattern: argv.testPathPattern + testPathPattern: argv.testPathPattern, }, context.config, - overrideConfig - ) + overrideConfig, + ), ); }); return runJest(contexts, argv, pipe, testWatcher, startRun, results => { @@ -123,7 +123,7 @@ const watch = ( // 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 }); + testWatcher = new TestWatcher({isWatchMode: true}); if (shouldDisplayWatchUsage) { pipe.write(usage(argv, hasSnapshotFailure)); shouldDisplayWatchUsage = false; // hide Watch Usage after first run @@ -155,7 +155,7 @@ const watch = ( testWatcher && [KEYS.Q, KEYS.ENTER, KEYS.A, KEYS.O, KEYS.P, KEYS.T].indexOf(key) !== -1 ) { - testWatcher.setState({ interrupted: true }); + testWatcher.setState({interrupted: true}); return; } @@ -167,55 +167,55 @@ const watch = ( startRun(); break; case KEYS.U: - startRun({ updateSnapshot: true }); + startRun({updateSnapshot: true}); break; case KEYS.A: - setState(argv, "watchAll", { - testNamePattern: "", - testPathPattern: "" + setState(argv, 'watchAll', { + testNamePattern: '', + testPathPattern: '', }); startRun(); break; case KEYS.C: - setState(argv, "watch", { - testNamePattern: "", - testPathPattern: "" + setState(argv, 'watch', { + testNamePattern: '', + testPathPattern: '', }); startRun(); break; case KEYS.O: - setState(argv, "watch", { - testNamePattern: "", - testPathPattern: "" + setState(argv, 'watch', { + testNamePattern: '', + testPathPattern: '', }); startRun(); break; case KEYS.P: testPathPatternPrompt.run( testPathPattern => { - setState(argv, "watch", { - testNamePattern: "", - testPathPattern + setState(argv, 'watch', { + testNamePattern: '', + testPathPattern, }); startRun(); }, onCancelPatternPrompt, - { header: activeFilters(argv) + "\n" } + {header: activeFilters(argv) + '\n'}, ); break; case KEYS.T: testNamePatternPrompt.run( testNamePattern => { - setState(argv, "watch", { + setState(argv, 'watch', { testNamePattern, - testPathPattern: argv.testPathPattern + testPathPattern: argv.testPathPattern, }); startRun(); }, onCancelPatternPrompt, - { header: activeFilters(argv) + "\n" } + {header: activeFilters(argv) + '\n'}, ); break; case KEYS.QUESTION_MARK: @@ -239,78 +239,80 @@ const watch = ( pipe.write(ansiEscapes.cursorShow); }; - if (typeof stdin.setRawMode === "function") { + if (typeof stdin.setRawMode === 'function') { stdin.setRawMode(true); stdin.resume(); - stdin.setEncoding("hex"); - stdin.on("data", onKeypress); + stdin.setEncoding('hex'); + stdin.on('data', onKeypress); } startRun(); return Promise.resolve(); }; -const activeFilters = (argv, delimiter = "\n") => { - const { testNamePattern, testPathPattern } = argv; +const activeFilters = (argv, delimiter = '\n') => { + const {testNamePattern, testPathPattern} = argv; if (testNamePattern || testPathPattern) { const filters = [ testPathPattern - ? chalk.dim("filename ") + chalk.yellow("/" + testPathPattern + "/") + ? chalk.dim('filename ') + chalk.yellow('/' + testPathPattern + '/') : null, testNamePattern - ? chalk.dim("test name ") + chalk.yellow("/" + testNamePattern + "/") - : null + ? chalk.dim('test name ') + chalk.yellow('/' + testNamePattern + '/') + : null, ] .filter(f => !!f) - .join(", "); + .join(', '); - const messages = ["\n" + chalk.bold("Active Filters: ") + filters]; + const messages = ['\n' + chalk.bold('Active Filters: ') + filters]; return messages.filter(message => !!message).join(delimiter); } - return ""; + return ''; }; -const usage = (argv, snapshotFailure, delimiter = "\n") => { +const usage = (argv, snapshotFailure, delimiter = '\n') => { const messages = [ activeFilters(argv), argv.testPathPattern || argv.testNamePattern - ? chalk.dim(" \u203A Press ") + "c" + chalk.dim(" to clear filters.") + ? chalk.dim(' \u203A Press ') + 'c' + chalk.dim(' to clear filters.') : null, - "\n" + chalk.bold("Watch Usage"), + '\n' + chalk.bold('Watch Usage'), argv.watch - ? chalk.dim(" \u203A Press ") + "a" + chalk.dim(" to run all tests.") + ? chalk.dim(' \u203A Press ') + 'a' + chalk.dim(' to run all tests.') : null, (argv.watchAll || argv.testPathPattern || argv.testNamePattern) && !argv.noSCM - ? chalk.dim(" \u203A Press ") + - "o" + - chalk.dim(" to only run tests related to changed files.") + ? chalk.dim(' \u203A Press ') + + 'o' + + chalk.dim(' to only run tests related to changed files.') : null, snapshotFailure - ? chalk.dim(" \u203A Press ") + - "u" + - chalk.dim(" to update failing snapshots.") + ? chalk.dim(' \u203A Press ') + + 'u' + + chalk.dim(' to update failing snapshots.') : null, - chalk.dim(" \u203A Press ") + - "p" + - chalk.dim(" to filter by a filename regex pattern."), - chalk.dim(" \u203A Press ") + - "t" + - chalk.dim(" to filter by a test name regex pattern."), - chalk.dim(" \u203A Press ") + "q" + chalk.dim(" to quit watch mode."), - chalk.dim(" \u203A Press ") + "Enter" + chalk.dim(" to trigger a test run.") + chalk.dim(' \u203A Press ') + + 'p' + + chalk.dim(' to filter by a filename regex pattern.'), + chalk.dim(' \u203A Press ') + + 't' + + chalk.dim(' to filter by a test name regex pattern.'), + chalk.dim(' \u203A Press ') + 'q' + chalk.dim(' to quit watch mode.'), + chalk.dim(' \u203A Press ') + + 'Enter' + + chalk.dim(' to trigger a test run.'), ]; - return messages.filter(message => !!message).join(delimiter) + "\n"; + return messages.filter(message => !!message).join(delimiter) + '\n'; }; const showToggleUsagePrompt = () => - "\n" + - chalk.bold("Watch Usage: ") + - chalk.dim("Press ") + - "w" + - chalk.dim(" to show more."); + '\n' + + chalk.bold('Watch Usage: ') + + chalk.dim('Press ') + + 'w' + + chalk.dim(' to show more.'); module.exports = watch; From 67fb5b8debd7d07753dfc9527200d6f124b7525a Mon Sep 17 00:00:00 2001 From: Rogelio Guzman Date: Thu, 27 Apr 2017 10:17:20 -0700 Subject: [PATCH 6/6] Fix tests --- .../src/__tests__/watch-filename-pattern-mode-test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/jest-cli/src/__tests__/watch-filename-pattern-mode-test.js b/packages/jest-cli/src/__tests__/watch-filename-pattern-mode-test.js index cfdb822749c5..0709d9ca444e 100644 --- a/packages/jest-cli/src/__tests__/watch-filename-pattern-mode-test.js +++ b/packages/jest-cli/src/__tests__/watch-filename-pattern-mode-test.js @@ -161,7 +161,7 @@ describe('Watch mode flows', () => { it('Shows the appropiate header when the filename filter is active', () => { contexts[0].config = {rootDir: ''}; - watch(contexts, argv, pipe, hasteMapInstances, stdin); + watch(globalConfig, contexts, argv, pipe, hasteMapInstances, stdin); stdin.emit(KEYS.P); @@ -183,7 +183,7 @@ describe('Watch mode flows', () => { it('Shows the appropiate header when the test name filter is active', () => { contexts[0].config = {rootDir: ''}; - watch(contexts, argv, pipe, hasteMapInstances, stdin); + watch(globalConfig, contexts, argv, pipe, hasteMapInstances, stdin); stdin.emit(KEYS.T); @@ -205,7 +205,7 @@ describe('Watch mode flows', () => { it('Shows the appropiate header when both filters are active', () => { contexts[0].config = {rootDir: ''}; - watch(contexts, argv, pipe, hasteMapInstances, stdin); + watch(globalConfig, contexts, argv, pipe, hasteMapInstances, stdin); stdin.emit(KEYS.P); @@ -227,7 +227,7 @@ describe('Watch mode flows', () => { it('Pressing "c" clears the filters', () => { contexts[0].config = {rootDir: ''}; - watch(contexts, argv, pipe, hasteMapInstances, stdin); + watch(globalConfig, contexts, argv, pipe, hasteMapInstances, stdin); stdin.emit(KEYS.P);