Skip to content

Commit

Permalink
Require opt-in to AVA 5's watcher, remove chokidar from dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
novemberborn committed Jun 29, 2023
1 parent 8f521bb commit 344ff33
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 58 deletions.
17 changes: 15 additions & 2 deletions docs/recipes/watch-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ Translations: [Français](https://github.com/avajs/ava-docs/blob/main/fr_FR/docs

AVA comes with an intelligent watch mode. It watches for files to change and runs just those tests that are affected.

AVA 6 is introducing a new watch mode that relies on recurse file watching in Node.js. To use the old watch mode, set the `watcher` configuration to `ava5+chokidar` and install [`chokidar`] alongside AVA:

`ava.config.mjs`:
```js
export default {
watcher: 'ava5+chokidar'
}
```

## Running tests with watch mode enabled

You can enable watch mode using the `--watch` or `-w` flags:
Expand All @@ -16,7 +25,9 @@ Please note that integrated debugging and the TAP reporter are unavailable when

## Requirements

AVA uses [`chokidar`] as the file watcher. Note that even if you see warnings about optional dependencies failing during install, it will still work fine. Please refer to the *[Install Troubleshooting]* section of `chokidar` documentation for how to resolve the installation problems with chokidar.
AVA 5 uses [`chokidar`] as the file watcher. Note that even if you see warnings about optional dependencies failing during install, it will still work fine. Please refer to the *[Install Troubleshooting]* section of `chokidar` documentation for how to resolve the installation problems with chokidar.

The same applies with AVA 6 when using the `ava5+chokidar` watcher. However you'll need to install `chokidar` separately.

## Ignoring changes

Expand All @@ -30,7 +41,9 @@ If your tests write to disk they may trigger the watcher to rerun your tests. Co

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.

Dependency tracking works for required modules. Custom extensions and transpilers are supported, provided you [added them in your `package.json` or `ava.config.*` file][config], and not from inside your test file. Files accessed using the `fs` module are not tracked.
AVA 5 (and the `ava5+chokidar` watcher in AVA 6) spies on `require()` calls to track dependencies. Custom extensions and transpilers are supported, provided you [added them in your `package.json` or `ava.config.*` file][config], and not from inside your test file.

Files accessed using the `fs` module are not tracked.

## Watch mode and the `.only` modifier

Expand Down
9 changes: 7 additions & 2 deletions lib/watcher.js → lib/ava5-watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,16 @@ export default class Watcher {
trackTestDependencies(api) {
api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type !== 'dependencies') {
let dependencies;
if (evt.type === 'dependencies') {
dependencies = evt.dependencies;
} else if (evt.type === 'accessed-snapshots') {
dependencies = [evt.filename];
} else {
return;
}

const dependencies = evt.dependencies.filter(filePath => {
dependencies = dependencies.filter(filePath => {
const {isIgnoredByWatcher} = classify(filePath, this.globs);
return !isIgnoredByWatcher;
});
Expand Down
29 changes: 19 additions & 10 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import pkg from './pkg.cjs';
import providerManager from './provider-manager.js';
import DefaultReporter from './reporters/default.js';
import TapReporter from './reporters/tap.js';
import Watcher from './watcher.js';

function exit(message) {
console.error(`\n ${chalk.red(figures.cross)} ${message}`);
Expand Down Expand Up @@ -415,6 +414,7 @@ export default async function loadCli() { // eslint-disable-line complexity
concurrency: combined.concurrency || 0,
workerThreads: combined.workerThreads !== false,
debug,
enableAva5DependencyTracking: argv.watch && conf.watcher === 'ava5+chokidar',
environmentVariables,
experiments,
extensions,
Expand Down Expand Up @@ -476,15 +476,24 @@ export default async function loadCli() { // eslint-disable-line complexity
});

if (argv.watch) {
const watcher = new Watcher({
api,
filter,
globs,
projectDir,
providers,
reporter,
});
watcher.observeStdin(process.stdin);
if (Object.hasOwn(conf, 'watcher')) {
if (conf.watcher === 'ava5+chokidar') {
const {default: Watcher} = await import('./ava5-watcher.js');
const watcher = new Watcher({
api,
filter,
globs,
projectDir,
providers,
reporter,
});
watcher.observeStdin(process.stdin);
} else {
exit('The "watcher" option must be set to "ava5+chokidar"');
}
} else {
exit('TODO');
}
} else {
let debugWithoutSpecificFile = false;
api.on('run', plan => {
Expand Down
2 changes: 1 addition & 1 deletion lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export default class Runner extends Emittery {
updating: this.updateSnapshots,
});
if (snapshots.snapPath !== undefined) {
this.emit('dependency', snapshots.snapPath);
this.emit('accessed-snapshots', snapshots.snapPath);
}

this._snapshots = snapshots;
Expand Down
File renamed without changes.
17 changes: 12 additions & 5 deletions lib/worker/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import providerManager from '../provider-manager.js';
import Runner from '../runner.js';
import serializeError from '../serialize-error.js';

// TODO: Delete along with ava5+chokidar watcher.
import dependencyTracking from './ava5-dependency-tracker.js';
import channel from './channel.cjs';
import dependencyTracking from './dependency-tracker.js';
import lineNumberSelection from './line-numbers.js';
import {set as setOptions} from './options.cjs';
import {flags, refs, sharedWorkerTeardowns} from './state.cjs';
Expand Down Expand Up @@ -99,7 +100,11 @@ const run = async options => {
runner.interrupt();
});

runner.on('dependency', dependencyTracking.track);
runner.on('accessed-snapshots', filename => channel.send({type: 'accessed-snapshots', filename}));
if (options.enableAva5DependencyTracking) {
runner.on('dependency', dependencyTracking.track);
}

runner.on('stateChange', state => channel.send(state));

runner.on('error', error => {
Expand Down Expand Up @@ -229,9 +234,11 @@ const run = async options => {
}
}

// Install dependency tracker after the require configuration has been evaluated
// to make sure we also track dependencies with custom require hooks
dependencyTracking.install(require.extensions, testPath);
if (options.enableAva5DependencyTracking) {
// Install dependency tracker after the require configuration has been evaluated
// to make sure we also track dependencies with custom require hooks
dependencyTracking.install(require.extensions, testPath);
}

if (options.debug && options.debug.port !== undefined && options.debug.host !== undefined) {
// If an inspector was active when the main process started, and is
Expand Down
13 changes: 11 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@
"callsites": "^4.0.0",
"cbor": "^8.1.0",
"chalk": "^5.2.0",
"chokidar": "^3.5.3",
"chunkd": "^2.0.1",
"ci-info": "^3.8.0",
"ci-parallel-vars": "^1.0.1",
Expand Down Expand Up @@ -142,11 +141,15 @@
"zen-observable": "^0.10.0"
},
"peerDependencies": {
"@ava/typescript": "*"
"@ava/typescript": "*",
"chokidar": "^3.5.3"
},
"peerDependenciesMeta": {
"@ava/typescript": {
"optional": true
},
"chokidar": {
"optional": true
}
},
"volta": {
Expand Down
34 changes: 0 additions & 34 deletions test-tap/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -418,40 +418,6 @@ for (const opt of options) {
});
});

test(`emits dependencies for test files - workerThreads: ${opt.workerThreads}`, async t => {
t.plan(8);

const api = await apiCreator({
...opt,
files: ['test-tap/fixture/with-dependencies/*test*.cjs'],
require: [path.resolve('test-tap/fixture/with-dependencies/require-custom.cjs')],
});

const testFiles = new Set([
path.resolve('test-tap/fixture/with-dependencies/no-tests.cjs'),
path.resolve('test-tap/fixture/with-dependencies/test.cjs'),
path.resolve('test-tap/fixture/with-dependencies/test-failure.cjs'),
path.resolve('test-tap/fixture/with-dependencies/test-uncaught-exception.cjs'),
]);

const sourceFiles = [
path.resolve('test-tap/fixture/with-dependencies/dep-1.js'),
path.resolve('test-tap/fixture/with-dependencies/dep-2.js'),
path.resolve('test-tap/fixture/with-dependencies/dep-3.custom'),
];

api.on('run', plan => {
plan.status.on('stateChange', evt => {
if (evt.type === 'dependencies') {
t.ok(testFiles.has(evt.testFile));
t.strictSame(evt.dependencies.filter(dep => !dep.endsWith('.snap')).slice(-3), sourceFiles);
}
});
});

return api.run();
});

test(`verify test count - workerThreads: ${opt.workerThreads}`, async t => {
t.plan(4);

Expand Down

0 comments on commit 344ff33

Please sign in to comment.