Skip to content

Commit

Permalink
Merge pull request avajs#658 from sindresorhus/rerun-watch
Browse files Browse the repository at this point in the history
Rerun tests using "r" key in watch mode
  • Loading branch information
Vadim Demedes committed Mar 20, 2016
2 parents 13077e2 + 5f109b6 commit ad02c32
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 77 deletions.
2 changes: 1 addition & 1 deletion docs/recipes/watch-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Dependency tracking works for required modules. Custom extensions and transpiler

## Manually rerunning all tests

You can quickly rerun all tests by typing <kbd>r</kbd> on the console, followed by <kbd>Enter</kbd>.
You can quickly rerun all tests by typing <kbd>r</kbd> on the console.

## Debugging

Expand Down
15 changes: 12 additions & 3 deletions lib/watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var union = require('array-union');
var uniq = require('array-uniq');
var defaultIgnore = require('ignore-by-default').directories();
var multimatch = require('multimatch');
var keypress = require('keypress');
var nodePath = require('path');
var slash = require('slash');

Expand Down Expand Up @@ -149,11 +150,19 @@ Watcher.prototype.cleanUnlinkedTests = function (unlinkedTests) {
Watcher.prototype.observeStdin = function (stdin) {
var self = this;

if (stdin.isTTY) {
keypress(stdin);
stdin.setRawMode(true);
}

stdin.resume();
stdin.setEncoding('utf8');
stdin.on('data', function (data) {
data = data.trim().toLowerCase();
if (data !== 'r' && data !== 'rs') {
stdin.on('keypress', function (char, key) {
if (key.ctrl && key.name === 'c') {
process.exit(2);
}

if (char !== 'r') {
return;
}

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
"is-obj": "^1.0.0",
"is-observable": "^0.1.0",
"is-promise": "^2.1.0",
"keypress": "^0.2.1",
"last-line-stream": "^1.0.0",
"loud-rejection": "^1.2.0",
"matcher": "^0.1.1",
Expand Down
147 changes: 74 additions & 73 deletions test/watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ group('chokidar is installed', function (beforeEach, test, group) {

stdin = new PassThrough();
stdin.pause();
stdin.on('data', function (data) {
stdin.emit('keypress', data, {});
});
});

var start = function (sources) {
Expand Down Expand Up @@ -511,102 +514,100 @@ group('chokidar is installed', function (beforeEach, test, group) {
});
});

["r", "rs"].forEach(function (input) {
test('reruns initial tests when "' + input + '" is entered on stdin', function (t) {
t.plan(2);
api.run.returns(Promise.resolve());
start().observeStdin(stdin);
test('reruns initial tests when "r" is entered on stdin', function (t) {
t.plan(2);
api.run.returns(Promise.resolve());
start().observeStdin(stdin);

stdin.write(input + '\n');
return delay().then(function () {
t.ok(api.run.calledTwice);
stdin.write('r');
return delay().then(function () {
t.ok(api.run.calledTwice);

stdin.write('\t' + input + ' \n');
return delay();
}).then(function () {
t.ok(api.run.calledThrice);
});
stdin.write('r');
return delay();
}).then(function () {
t.ok(api.run.calledThrice);
});
});

test('entering "' + input + '" on stdin cancels any debouncing', function (t) {
t.plan(7);
api.run.returns(Promise.resolve());
start().observeStdin(stdin);
test('entering "r" on stdin cancels any debouncing', function (t) {
t.plan(7);
api.run.returns(Promise.resolve());
start().observeStdin(stdin);

var before = clock.now;
var done;
api.run.returns(new Promise(function (resolve) {
done = resolve;
}));
var before = clock.now;
var done;
api.run.returns(new Promise(function (resolve) {
done = resolve;
}));

add();
stdin.write(input + '\n');
return delay().then(function () {
// Processing "rs" caused a new run.
t.ok(api.run.calledTwice);
add();
stdin.write('r');
return delay().then(function () {
// Processing "r" caused a new run.
t.ok(api.run.calledTwice);

// Try to advance the clock. This is *after* input was processed. The
// debounce timeout should have been canceled, so the clock can't have
// advanced.
clock.next();
t.is(before, clock.now);
// Try to advance the clock. This is *after* input was processed. The
// debounce timeout should have been canceled, so the clock can't have
// advanced.
clock.next();
t.is(before, clock.now);

add();
// Advance clock *before* input is received. Note that the previous run
// hasn't finished yet.
clock.next();
stdin.write(input + '\n');
add();
// Advance clock *before* input is received. Note that the previous run
// hasn't finished yet.
clock.next();
stdin.write('r');

return delay();
}).then(function () {
// No new runs yet.
t.ok(api.run.calledTwice);
// Though the clock has advanced.
t.is(clock.now - before, 10);
before = clock.now;
return delay();
}).then(function () {
// No new runs yet.
t.ok(api.run.calledTwice);
// Though the clock has advanced.
t.is(clock.now - before, 10);
before = clock.now;

var previous = done;
api.run.returns(new Promise(function (resolve) {
done = resolve;
}));
var previous = done;
api.run.returns(new Promise(function (resolve) {
done = resolve;
}));

// Finish the previous run.
previous();
// Finish the previous run.
previous();

return delay();
}).then(function () {
// There's only one new run.
t.ok(api.run.calledThrice);
return delay();
}).then(function () {
// There's only one new run.
t.ok(api.run.calledThrice);

stdin.write(input + '\n');
return delay();
}).then(function () {
add();
stdin.write('r');
return delay();
}).then(function () {
add();

// Finish the previous run. This should cause a new run due to the
// input.
done();
// Finish the previous run. This should cause a new run due to the
// input.
done();

return delay();
}).then(function () {
// Again there's only one new run.
t.is(api.run.callCount, 4);
return delay();
}).then(function () {
// Again there's only one new run.
t.is(api.run.callCount, 4);

// Try to advance the clock. This is *after* input was processed. The
// debounce timeout should have been canceled, so the clock can't have
// advanced.
clock.next();
t.is(before, clock.now);
});
// Try to advance the clock. This is *after* input was processed. The
// debounce timeout should have been canceled, so the clock can't have
// advanced.
clock.next();
t.is(before, clock.now);
});
});

test('does nothing if anything other than "rs" is entered on stdin', function (t) {
test('does nothing if anything other than "r" is entered on stdin', function (t) {
t.plan(2);
api.run.returns(Promise.resolve());
start().observeStdin(stdin);

stdin.write('foo\n');
stdin.write('foo');
return debounce().then(function () {
t.ok(logger.reset.calledOnce);
t.ok(api.run.calledOnce);
Expand Down

0 comments on commit ad02c32

Please sign in to comment.