Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract watch mode #2362

Merged
merged 17 commits into from Jan 8, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 5 additions & 3 deletions packages/jest-cli/src/__tests__/TestRunner-test.js
Expand Up @@ -14,7 +14,6 @@ const TestRunner = require('../TestRunner');
const TestWatcher = require('../TestWatcher');
const SummaryReporter = require('../reporters/SummaryReporter');

let worker;
let workerFarmMock;

jest.mock('worker-farm', () => {
Expand Down Expand Up @@ -56,9 +55,10 @@ describe('_createInBandTestRun()', () => {
).then(() => {
expect(workerFarmMock.mock.calls).toEqual([
[{config, path: './file-test.js', rawModuleMap}, jasmine.any(Function)],
// eslint-disable-next-line max-len
[{config, path: './file2-test.js', rawModuleMap}, jasmine.any(Function)],
]);
})
});
});

test('does not inject the rawModuleMap in non watch mode', () => {
Expand All @@ -73,9 +73,11 @@ describe('_createInBandTestRun()', () => {
() => {},
).then(() => {
expect(workerFarmMock.mock.calls).toEqual([
/* eslint-disable max-len */
[{config, path: './file-test.js', rawModuleMap: null}, jasmine.any(Function)],
[{config, path: './file2-test.js', rawModuleMap: null}, jasmine.any(Function)],
/* eslint-enable max-len */
]);
})
});
});
});
158 changes: 158 additions & 0 deletions packages/jest-cli/src/__tests__/watch-test.js
@@ -0,0 +1,158 @@
/**
* 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 TestWatcher = require('../TestWatcher');
const {KEYS} = require('../constants');

const runJestMock = jest.fn();

jest.mock('jest-util', () => ({clearLine: () => {}}));
jest.doMock('chalk', () => new chalk.constructor({enabled: false}));
jest.doMock('../constants', () => ({CLEAR: '', KEYS}));
jest.doMock('../runJest', () => (...args) => {
runJestMock(...args);

// Call the callback
args[args.length - 1]({snapshot: {}});

return Promise.resolve();
});

const watch = require('../watch');

const USAGE_MESSAGE = `
Watch Usage
› Press o to only run tests related to changed files.
› Press p to filter by a filename regex pattern.
› Press q to quit watch mode.
› Press Enter to trigger a test run.`;

afterEach(runJestMock.mockReset);

describe('Watch mode flows', () => {
let pipe;
let hasteMap;
let argv;
let hasteContext;
let config;
let stdin;

beforeEach(() => {
pipe = {write: jest.fn()};
hasteMap = {on: () => {}};
argv = {};
hasteContext = {};
config = {};
stdin = new MockStdin();
});

it('Runs Jest once by default and shows usage', () => {
watch(config, pipe, argv, hasteMap, hasteContext, stdin);
expect(runJestMock).toBeCalledWith(hasteContext, config, argv, pipe,
new TestWatcher({isWatchMode: true}), jasmine.any(Function));
expect(pipe.write).toBeCalledWith(USAGE_MESSAGE);
});

it('Pressing "o" runs test in "only changed files" mode', () => {
watch(config, pipe, argv, hasteMap, hasteContext, stdin);
runJestMock.mockReset();

stdin.emit(KEYS.O);

expect(runJestMock).toBeCalled();
expect(argv).toEqual({
'_': '',
onlyChanged: true,
watch: true,
watchAll: false,
});
});

it('Pressing "a" runs test in "watch all" mode', () => {
watch(config, pipe, argv, hasteMap, hasteContext, stdin);
runJestMock.mockReset();

stdin.emit(KEYS.A);

expect(runJestMock).toBeCalled();
expect(argv).toEqual({
'_': '',
onlyChanged: false,
watch: false,
watchAll: true,
});
});

it('Pressing "P" enters pattern mode', () => {
watch(config, pipe, argv, hasteMap, hasteContext, stdin);

// Write a enter pattern mode
stdin.emit(KEYS.P);
expect(pipe.write).toBeCalledWith(' pattern › ');

// Write a pattern
stdin.emit(KEYS.P);
stdin.emit(KEYS.O);
stdin.emit(KEYS.A);
expect(pipe.write).toBeCalledWith(' pattern › poa');

//Runs Jest again
runJestMock.mockReset();
stdin.emit(KEYS.ENTER);
expect(runJestMock).toBeCalled();

//Argv is updated with the current pattern
expect(argv).toEqual({
'_': ['poa'],
onlyChanged: false,
watch: true,
watchAll: false,
});
});

it('Pressing "ENTER" reruns the tests', () => {
watch(config, pipe, argv, hasteMap, hasteContext, stdin);
expect(runJestMock).toHaveBeenCalledTimes(1);
stdin.emit(KEYS.ENTER);
expect(runJestMock).toHaveBeenCalledTimes(2);
});

it('Pressing "u" reruns the tests in "update snapshot" mode', () => {
watch(config, pipe, argv, hasteMap, hasteContext, stdin);
runJestMock.mockReset();

stdin.emit(KEYS.U);

expect(runJestMock.mock.calls[0][1]).toEqual({updateSnapshot: true});
});
});

class MockStdin {
constructor() {
this._callbacks = [];
}

setRawMode() {}

resume() {}

setEncoding() {}

on(evt, callback) {
this._callbacks.push(callback);
}

emit(key) {
this._callbacks.forEach(cb => cb(key));
}
}
33 changes: 33 additions & 0 deletions packages/jest-cli/src/constants.js
@@ -0,0 +1,33 @@
/**
* 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
*/

'use strict';

const CLEAR = process.platform === 'win32' ? '\x1Bc' : '\x1B[2J\x1B[3J\x1B[H';

const KEYS = {
A: '61',
ARROW_DOWN: '1b5b42',
ARROW_LEFT: '1b5b44',
ARROW_RIGHT: '1b5b43',
ARROW_UP: '1b5b41',
BACKSPACE: process.platform === 'win32' ? '08' : '7f',
CONTROL_C: '03',
CONTROL_D: '04',
ENTER: '0d',
ESCAPE: '1b',
O: '6f',
P: '70',
Q: '71',
QUESTION_MARK: '3f',
U: '75',
};

module.exports = {CLEAR, KEYS};
36 changes: 9 additions & 27 deletions packages/jest-cli/src/watch.js
Expand Up @@ -21,33 +21,15 @@ const preRunMessage = require('./preRunMessage');
const runJest = require('./runJest');
const setWatchMode = require('./lib/setWatchMode');
const TestWatcher = require('./TestWatcher');

const CLEAR = process.platform === 'win32' ? '\x1Bc' : '\x1B[2J\x1B[3J\x1B[H';
const KEYS = {
A: '61',
ARROW_DOWN: '1b5b42',
ARROW_LEFT: '1b5b44',
ARROW_RIGHT: '1b5b43',
ARROW_UP: '1b5b41',
BACKSPACE: process.platform === 'win32' ? '08' : '7f',
CONTROL_C: '03',
CONTROL_D: '04',
ENTER: '0d',
ESCAPE: '1b',
O: '6f',
P: '70',
Q: '71',
QUESTION_MARK: '3f',
U: '75',
};

const {KEYS, CLEAR} = require('./constants');

const watch = (
config: Config,
pipe: stream$Writable | tty$WriteStream,
argv: Object,
hasteMap: HasteMap,
hasteContext: HasteContext,
stdin?: stream$Readable | tty$ReadStream = process.stdin
) => {
setWatchMode(argv, argv.watch ? 'watch' : 'watchAll', {
pattern: argv._,
Expand Down Expand Up @@ -93,7 +75,7 @@ const watch = (
// and prevent test runs from the previous run.
testWatcher = new TestWatcher({isWatchMode: true});
if (displayHelp) {
console.log(usage(argv, hasSnapshotFailure));
pipe.write(usage(argv, hasSnapshotFailure));
Copy link
Contributor Author

@rogeliog rogeliog Jan 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cpojer I changed this and 7909aeb#diff-d8a3d0a3a8b42ab87b18835ad8f7cb46L177 to use pipe.write instead of console.log for testability purposes, but I'm unsure if this has any impact in on how things are printed out that I'm unaware of... I'll keep investigating tomorrow

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fine. Unsure why we used console.log here in the first place.

displayHelp = !process.env.JEST_HIDE_USAGE;
}
},
Expand Down Expand Up @@ -174,17 +156,17 @@ const watch = (
break;
case KEYS.QUESTION_MARK:
if (process.env.JEST_HIDE_USAGE) {
console.log(usage(argv, hasSnapshotFailure));
pipe.write(usage(argv, hasSnapshotFailure));
}
break;
}
};

if (typeof process.stdin.setRawMode === 'function') {
process.stdin.setRawMode(true);
process.stdin.resume();
process.stdin.setEncoding('hex');
process.stdin.on('data', onKeypress);
if (typeof stdin.setRawMode === 'function') {
stdin.setRawMode(true);
stdin.resume();
stdin.setEncoding('hex');
stdin.on('data', onKeypress);
}

startRun();
Expand Down