Skip to content

Commit

Permalink
Minor changes to watch mode
Browse files Browse the repository at this point in the history
* Remove undocumented ability to start watch mode via the config. Require the CLI flag instead
* Watch mode is no longer 'relatively new'
* Add ava.config.mjs to default watcher ignore patterns
* Ignore changes to failed-tests file in watcher

Logger cleanup:

* Remove obsolete clearLogOnNextRun option
* Track firstRun for reporter
  • Loading branch information
novemberborn committed Jul 2, 2023
1 parent 4dc385b commit 94bb361
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 101 deletions.
4 changes: 0 additions & 4 deletions docs/recipes/watch-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ Sometimes watch mode does something surprising like rerunning all tests when you
$ DEBUG=ava:watcher npx ava --watch
```

## Help us make watch mode better

Watch mode is relatively new and there might be some rough edges. Please [report](https://github.com/avajs/ava/issues) any issues you encounter. Thanks!

[`chokidar`]: https://github.com/paulmillr/chokidar
[Install Troubleshooting]: https://github.com/paulmillr/chokidar#install-troubleshooting
[`ignore-by-default`]: https://github.com/novemberborn/ignore-by-default
Expand Down
6 changes: 3 additions & 3 deletions lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,15 +197,14 @@ export default class Api extends Emittery {

await this.emit('run', {
bailWithoutReporting: debugWithoutSpecificFile,
clearLogOnNextRun: runtimeOptions.clearLogOnNextRun === true,
debug: Boolean(this.options.debug),
failFastEnabled: failFast,
filePathPrefix: getFilePathPrefix(selectedFiles),
files: selectedFiles,
matching: apiOptions.match.length > 0,
previousFailures: runtimeOptions.previousFailures || 0,
runOnlyExclusive: runtimeOptions.runOnlyExclusive === true,
runVector: runtimeOptions.runVector || 0,
firstRun: runtimeOptions.firstRun ?? true,
status: runStatus,
});

Expand Down Expand Up @@ -303,7 +302,8 @@ export default class Api extends Emittery {

// Allow shared workers to clean up before the run ends.
await Promise.all(deregisteredSharedWorkers);
scheduler.storeFailedTestFiles(runStatus, this.options.cacheEnabled === false ? null : this._createCacheDir());
const files = scheduler.storeFailedTestFiles(runStatus, this.options.cacheEnabled === false ? null : this._createCacheDir());
runStatus.emitStateChange({type: 'touched-files', files});
} catch (error) {
if (error && error.name === 'AggregateError') {
for (const error_ of error.errors) {
Expand Down
10 changes: 7 additions & 3 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,10 @@ export default async function loadCli() { // eslint-disable-line complexity
exit('’sortTestFiles’ must be a comparator function.');
}

if (Object.hasOwn(conf, 'watch')) {
exit('’watch’ must not be configured, use the --watch CLI flag instead.');
}

if (!combined.tap && Object.keys(experiments).length > 0) {
console.log(chalk.magenta(` ${figures.warning} Experiments are enabled. These are unsupported and may change or be removed at any time.`));
}
Expand Down Expand Up @@ -432,7 +436,7 @@ export default async function loadCli() { // eslint-disable-line complexity
workerArgv: argv['--'],
});

const reporter = combined.tap && !combined.watch && debug === null ? new TapReporter({
const reporter = combined.tap && !argv.watch && debug === null ? new TapReporter({
extensions: globs.extensions,
projectDir,
reportStream: process.stdout,
Expand All @@ -442,7 +446,7 @@ export default async function loadCli() { // eslint-disable-line complexity
projectDir,
reportStream: process.stdout,
stdStream: process.stderr,
watching: combined.watch,
watching: argv.watch,
});

api.on('run', plan => {
Expand All @@ -464,7 +468,7 @@ export default async function loadCli() { // eslint-disable-line complexity
});
});

if (combined.watch) {
if (argv.watch) {
const watcher = new Watcher({
api,
filter,
Expand Down
1 change: 1 addition & 0 deletions lib/globs.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const defaultIgnoredByWatcherPatterns = [
'**/*.snap.md', // No need to rerun tests when the Markdown files change.
'ava.config.js', // Config is not reloaded so avoid rerunning tests when it changes.
'ava.config.cjs', // Config is not reloaded so avoid rerunning tests when it changes.
'ava.config.mjs', // Config is not reloaded so avoid rerunning tests when it changes.
];

const buildExtensionPattern = extensions => extensions.length === 1 ? extensions[0] : `{${extensions.join(',')}}`;
Expand Down
2 changes: 1 addition & 1 deletion lib/reporters/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export default class Reporter {
this.consumeStateChange(evt);
});

if (this.watching && plan.runVector > 1) {
if (this.watching && !plan.firstRun) {
this.lineWriter.write(chalk.gray.dim('\u2500'.repeat(this.lineWriter.columns)) + os.EOL);
}

Expand Down
15 changes: 14 additions & 1 deletion lib/scheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,22 @@ const scheduler = {
return;
}

const filename = path.join(cacheDir, FILENAME);
// Given that we're writing to a cache directory, consider this file
// temporary.
const temporaryFiles = [filename];
try {
writeFileAtomic.sync(path.join(cacheDir, FILENAME), JSON.stringify(runStatus.getFailedTestFiles()));
writeFileAtomic.sync(filename, JSON.stringify(runStatus.getFailedTestFiles()), {
tmpfileCreated(tmpfile) {
temporaryFiles.push(tmpfile);
},
});
} catch {}

return {
changedFiles: [],
temporaryFiles,
};
},

// Order test-files, so that files with failing tests come first
Expand Down
24 changes: 2 additions & 22 deletions lib/watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ export default class Watcher {
constructor({api, filter = [], globs, projectDir, providers, reporter}) {
this.debouncer = new Debouncer(this);

this.clearLogOnNextRun = true;
this.runVector = 0;
this.previousFiles = [];
this.globs = {cwd: projectDir, ...globs};
Expand All @@ -98,11 +97,6 @@ export default class Watcher {

this.providers = providers;
this.run = (specificFiles = [], updateSnapshots = false) => {
const clearLogOnNextRun = this.clearLogOnNextRun && this.runVector > 0;
if (this.runVector > 0) {
this.clearLogOnNextRun = true;
}

this.runVector++;

let runOnlyExclusive = false;
Expand Down Expand Up @@ -135,28 +129,15 @@ export default class Watcher {
files: specificFiles,
filter,
runtimeOptions: {
clearLogOnNextRun,
previousFailures: this.sumPreviousFailures(this.runVector),
runOnlyExclusive,
runVector: this.runVector,
firstRun: this.runVector === 1,
updateSnapshots: updateSnapshots === true,
},
})
.then(runStatus => {
.then(() => {
reporter.endRun();
reporter.lineWriter.writeLine(END_MESSAGE);

if (this.clearLogOnNextRun && (
runStatus.stats.failedHooks > 0
|| runStatus.stats.failedTests > 0
|| runStatus.stats.failedWorkers > 0
|| runStatus.stats.internalErrors > 0
|| runStatus.stats.timeouts > 0
|| runStatus.stats.uncaughtExceptions > 0
|| runStatus.stats.unhandledRejections > 0
)) {
this.clearLogOnNextRun = false;
}
})
.catch(rethrowAsync);
};
Expand Down Expand Up @@ -372,7 +353,6 @@ export default class Watcher {
// Cancel the debouncer again, it might have restarted while waiting for
// the busy promise to fulfil
this.debouncer.cancel();
this.clearLogOnNextRun = false;
if (data === 'u') {
this.updatePreviousSnapshots();
} else {
Expand Down
6 changes: 3 additions & 3 deletions test-tap/helper/report.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,12 @@ const run = async (type, reporter, {match = [], filter} = {}) => {
}

// Mimick watch mode
return api.run({files, filter, runtimeOptions: {clearLogOnNextRun: false, previousFailures: 0, runVector: 1}}).then(() => {
return api.run({files, filter, runtimeOptions: {previousFailures: 0, firstRun: true}}).then(() => {
reporter.endRun();
return api.run({files, filter, runtimeOptions: {clearLogOnNextRun: true, previousFailures: 2, runVector: 2}});
return api.run({files, filter, runtimeOptions: {previousFailures: 2, firstRun: false}});
}).then(() => {
reporter.endRun();
return api.run({files, filter, runtimeOptions: {clearLogOnNextRun: false, previousFailures: 0, runVector: 3}});
return api.run({files, filter, runtimeOptions: {previousFailures: 0, firstRun: false}});
}).then(() => {
reporter.endRun();
});
Expand Down
Loading

0 comments on commit 94bb361

Please sign in to comment.