Skip to content

Commit cac933e

Browse files
committed
Merge pull request #607 from sindresorhus/document-watch
Document watch mode
2 parents 1868204 + 81b7f1e commit cac933e

File tree

5 files changed

+187
-74
lines changed

5 files changed

+187
-74
lines changed

cli.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,8 @@ var cli = meow([
5454
' --verbose, -v Enable verbose output',
5555
' --no-cache Disable the transpiler cache',
5656
' --match, -m Only run tests with matching title (Can be repeated)',
57-
// Leave --watch and --sources undocumented until they're stable enough
58-
// ' --watch, -w Re-run tests when tests and source files change',
59-
// ' --source Pattern to match source files so tests can be re-run (Can be repeated)',
57+
' --watch, -w Re-run tests when tests and source files change',
58+
' --source, -S Pattern to match source files so tests can be re-run (Can be repeated)',
6059
'',
6160
'Examples',
6261
' ava',
@@ -88,8 +87,9 @@ var cli = meow([
8887
v: 'verbose',
8988
r: 'require',
9089
s: 'serial',
90+
m: 'match',
9191
w: 'watch',
92-
m: 'match'
92+
S: 'source'
9393
}
9494
});
9595

docs/recipes/watch-mode.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Watch mode
2+
3+
AVA comes with an intelligent watch mode. It watches for files to change and runs just those tests that are affected.
4+
5+
## Running tests with watch mode enabled
6+
7+
You can enable watch mode using the `--watch` or `-w` flags. If you have installed AVA globally:
8+
9+
```console
10+
$ ava --watch
11+
```
12+
13+
If you've configured it in your `package.json` like this:
14+
15+
```json
16+
{
17+
"scripts": {
18+
"test": "ava"
19+
}
20+
}
21+
```
22+
23+
You can run:
24+
25+
```console
26+
$ npm test -- --watch
27+
```
28+
29+
You could also set up a special script:
30+
31+
```json
32+
{
33+
"scripts": {
34+
"test": "ava",
35+
"test:watch": "ava --watch"
36+
}
37+
}
38+
```
39+
40+
And then use:
41+
42+
```console
43+
$ npm run test:watch
44+
```
45+
46+
## Requirements
47+
48+
AVA uses [`chokidar`] as the file watcher. It's configured as an optional dependency since `chokidar` sometimes can't be installed. Watch mode is not available if `chokidar` fails to install, instead you'll see a message like:
49+
50+
> The optional dependency chokidar failed to install and is required for --watch. Chokidar is likely not supported on your platform.
51+
52+
Please refer to the [`chokidar` documentation][`chokidar`] for how to resolve this problem.
53+
54+
## Source files and test files
55+
56+
In AVA there's a distinction between *source files* and *test files*. As you can imagine the *test files* contain your tests. *Source files* are all other files that are needed for the tests to run, be it your source code or test fixtures.
57+
58+
By default AVA watches for changes to the test files, `package.json`, and any other `.js` files. It'll ignore files in [certain directories](https://github.com/novemberborn/ignore-by-default/blob/master/index.js) as provided by the [`ignore-by-default`] package.
59+
60+
You can configure patterns for the source files using the [`--source` CLI flag] or in the `ava` section of your `package.json` file. Note that if you specify a negative pattern the directories from [`ignore-by-default`] will no longer be ignored, so you may want to repeat these in your config.
61+
62+
If your tests write to disk they may trigger the watcher to rerun your tests. If this occurs you will need to use the `--source` flag.
63+
64+
## Dependency tracking
65+
66+
AVA tracks which source files your test files depend on. If you change such a dependency only the test file that depends on it will be rerun. AVA will rerun all tests if it cannot determine which test file depends on the changed source file.
67+
68+
Dependency tracking works for required modules. Custom extensions and transpilers are supported, provided you loaded them using the [`--require` CLI flag] and not from inside your test file. Files accessed using the `fs` module are not tracked.
69+
70+
## Manually rerunning all tests
71+
72+
You can quickly rerun all tests by typing <kbd>r</kbd> on the console, followed by <kbd>Enter</kbd>.
73+
74+
## Debugging
75+
76+
Sometimes watch mode does something surprising like rerunning all tests when you thought only a single test would be run. To see its reasoning you can enable a debug mode:
77+
78+
```console
79+
$ DEBUG=ava:watcher npm test -- --watch
80+
```
81+
82+
On Windows use:
83+
84+
```console
85+
$ set DEBUG=ava:watcher
86+
$ npm test -- --watch
87+
```
88+
89+
## Help us make watch mode better
90+
91+
Watch mode is relatively new and there might be some rough edges. Please [report](https://github.com/sindresorhus/ava/issues) any issues you encounter. Thanks!
92+
93+
[`chokidar`]: https://github.com/paulmillr/chokidar
94+
[`ignore-by-default`]: https://github.com/novemberborn/ignore-by-default
95+
[`--require` CLI flag]: https://github.com/sindresorhus/ava#cli
96+
[`--source` CLI flag]: https://github.com/sindresorhus/ava#cli

lib/watcher.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ Watcher.prototype.observeStdin = function (stdin) {
120120
stdin.setEncoding('utf8');
121121
stdin.on('data', function (data) {
122122
data = data.trim().toLowerCase();
123-
if (data !== 'rs') {
123+
if (data !== 'r' && data !== 'rs') {
124124
return;
125125
}
126126

readme.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@ test('bar', async t => {
117117
$ npm test
118118
```
119119

120+
### Watch it
121+
122+
```console
123+
$ npm test -- --watch
124+
```
125+
126+
AVA comes with an intelligent watch mode. [Learn more in its recipe](docs/recipes/watch-mode.md).
127+
120128
## CLI
121129

122130
```console
@@ -134,6 +142,8 @@ $ ava --help
134142
--verbose, -v Enable verbose output
135143
--no-cache Disable the transpiler cache
136144
--match, -m Only run tests with matching title (Can be repeated)',
145+
--watch, -w Re-run tests when tests and source files change
146+
--source, -S Pattern to match source files so tests can be re-run (Can be repeated)
137147

138148
Examples
139149
ava
@@ -164,6 +174,10 @@ All of the CLI options can be configured in the `ava` section of your `package.j
164174
"my-test-folder/*.js",
165175
"!**/not-this-file.js"
166176
],
177+
"source": [
178+
"**/*.{js,jsx}",
179+
"!dist/**/*"
180+
],
167181
"match": [
168182
"*oo",
169183
"!foo"
@@ -880,6 +894,7 @@ It's the [Andromeda galaxy](https://simple.wikipedia.org/wiki/Andromeda_galaxy).
880894
## Recipes
881895

882896
- [Code coverage](docs/recipes/code-coverage.md)
897+
- [Watch mode](docs/recipes/watch-mode.md)
883898
- [Endpoint testing](docs/recipes/endpoint-testing.md)
884899
- [When to use `t.plan()`](docs/recipes/when-to-use-plan.md)
885900
- [Browser testing](docs/recipes/browser-testing.md)

test/watcher.js

Lines changed: 71 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -508,91 +508,93 @@ group('chokidar is installed', function (beforeEach, test, group) {
508508
});
509509
});
510510

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

516-
stdin.write('rs\n');
517-
return delay().then(function () {
518-
t.ok(api.run.calledTwice);
517+
stdin.write(input + '\n');
518+
return delay().then(function () {
519+
t.ok(api.run.calledTwice);
519520

520-
stdin.write('\trs \n');
521-
return delay();
522-
}).then(function () {
523-
t.ok(api.run.calledThrice);
521+
stdin.write('\t' + input + ' \n');
522+
return delay();
523+
}).then(function () {
524+
t.ok(api.run.calledThrice);
525+
});
524526
});
525-
});
526527

527-
test('entering "rs" on stdin cancels any debouncing', function (t) {
528-
t.plan(7);
529-
api.run.returns(Promise.resolve());
530-
start().observeStdin(stdin);
528+
test('entering "' + input + '" on stdin cancels any debouncing', function (t) {
529+
t.plan(7);
530+
api.run.returns(Promise.resolve());
531+
start().observeStdin(stdin);
531532

532-
var before = clock.now;
533-
var done;
534-
api.run.returns(new Promise(function (resolve) {
535-
done = resolve;
536-
}));
533+
var before = clock.now;
534+
var done;
535+
api.run.returns(new Promise(function (resolve) {
536+
done = resolve;
537+
}));
537538

538-
add();
539-
stdin.write('rs\n');
540-
return delay().then(function () {
541-
// Processing "rs" caused a new run.
542-
t.ok(api.run.calledTwice);
539+
add();
540+
stdin.write(input + '\n');
541+
return delay().then(function () {
542+
// Processing "rs" caused a new run.
543+
t.ok(api.run.calledTwice);
543544

544-
// Try to advance the clock. This is *after* "rs" was processed. The
545-
// debounce timeout should have been canceled, so the clock can't have
546-
// advanced.
547-
clock.next();
548-
t.is(before, clock.now);
545+
// Try to advance the clock. This is *after* input was processed. The
546+
// debounce timeout should have been canceled, so the clock can't have
547+
// advanced.
548+
clock.next();
549+
t.is(before, clock.now);
549550

550-
add();
551-
// Advance clock *before* "rs" is received. Note that the previous run
552-
// hasn't finished yet.
553-
clock.next();
554-
stdin.write('rs\n');
551+
add();
552+
// Advance clock *before* input is received. Note that the previous run
553+
// hasn't finished yet.
554+
clock.next();
555+
stdin.write(input + '\n');
555556

556-
return delay();
557-
}).then(function () {
558-
// No new runs yet.
559-
t.ok(api.run.calledTwice);
560-
// Though the clock has advanced.
561-
t.is(clock.now - before, 10);
562-
before = clock.now;
557+
return delay();
558+
}).then(function () {
559+
// No new runs yet.
560+
t.ok(api.run.calledTwice);
561+
// Though the clock has advanced.
562+
t.is(clock.now - before, 10);
563+
before = clock.now;
563564

564-
var previous = done;
565-
api.run.returns(new Promise(function (resolve) {
566-
done = resolve;
567-
}));
565+
var previous = done;
566+
api.run.returns(new Promise(function (resolve) {
567+
done = resolve;
568+
}));
568569

569-
// Finish the previous run.
570-
previous();
570+
// Finish the previous run.
571+
previous();
571572

572-
return delay();
573-
}).then(function () {
574-
// There's only one new run.
575-
t.ok(api.run.calledThrice);
573+
return delay();
574+
}).then(function () {
575+
// There's only one new run.
576+
t.ok(api.run.calledThrice);
576577

577-
stdin.write('rs\n');
578-
return delay();
579-
}).then(function () {
580-
add();
578+
stdin.write(input + '\n');
579+
return delay();
580+
}).then(function () {
581+
add();
581582

582-
// Finish the previous run. This should cause a new run due to the "rs"
583-
// input.
584-
done();
583+
// Finish the previous run. This should cause a new run due to the
584+
// input.
585+
done();
585586

586-
return delay();
587-
}).then(function () {
588-
// Again there's only one new run.
589-
t.is(api.run.callCount, 4);
587+
return delay();
588+
}).then(function () {
589+
// Again there's only one new run.
590+
t.is(api.run.callCount, 4);
590591

591-
// Try to advance the clock. This is *after* "rs" was processed. The
592-
// debounce timeout should have been canceled, so the clock can't have
593-
// advanced.
594-
clock.next();
595-
t.is(before, clock.now);
592+
// Try to advance the clock. This is *after* input was processed. The
593+
// debounce timeout should have been canceled, so the clock can't have
594+
// advanced.
595+
clock.next();
596+
t.is(before, clock.now);
597+
});
596598
});
597599
});
598600

0 commit comments

Comments
 (0)