Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions doc/api/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -3933,6 +3933,18 @@ Emitted when no more tests are queued for execution in watch mode.

### Event: `'test:watch:restarted'`

<!-- YAML
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/64457
description: Added the `file` property to the event data.
-->

* `data` {Object}
* `file` {string|undefined} The path of the file whose change triggered the
restart. This value is `undefined` when the triggering file cannot be
determined.

Emitted when one or more tests are restarted due to a file change in watch mode.

## `getTestContext()`
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/test_runner/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ function watchFiles(testFiles, opts) {
}

// Watch for changes in current filtered files
const onChanged = ({ owners, eventType }) => {
const onChanged = ({ owners, eventType, trigger }) => {
if (!opts.hasFiles && (eventType === 'rename' || eventType === 'change')) {
const updatedTestFiles = createTestFileList(opts.globPatterns, opts.cwd);
const newFileName = ArrayPrototypeFind(updatedTestFiles, (x) => !ArrayPrototypeIncludes(testFiles, x));
Expand All @@ -653,7 +653,7 @@ function watchFiles(testFiles, opts) {
// Reset the root start time to recalculate the duration
// of the run
opts.root.clearExecutionTime();
opts.root.reporter[kEmitMessage]('test:watch:restarted');
opts.root.reporter[kEmitMessage]('test:watch:restarted', { __proto__: null, file: trigger });

// Restart test files
if (opts.isolation === 'none') {
Expand Down
47 changes: 47 additions & 0 deletions test/test-runner/test-run-watch-restarted-file.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Test run({ watch: true }) reports the triggering file path in the
// test:watch:restarted event data.
import * as common from '../common/index.mjs';
import { run } from 'node:test';
import assert from 'node:assert';
import { writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { once } from 'node:events';
import tmpdir from '../common/tmpdir.js';
import { refreshForTestRunnerWatch, skipIfNoWatch, fixtureContent } from '../common/watch.js';

skipIfNoWatch();
refreshForTestRunnerWatch();

const changedFile = join(tmpdir.path, 'test.js');

let alreadyDrained = false;
const restartedFiles = [];
const onRestarted = common.mustCall((file) => {
restartedFiles.push(file);
}, 1);

const controller = new AbortController();
const stream = run({
cwd: tmpdir.path,
watch: true,
signal: controller.signal,
}).on('data', function({ type, data }) {
if (type === 'test:watch:restarted') {
onRestarted(data.file);
}
if (type === 'test:watch:drained') {
if (alreadyDrained) {
controller.abort();
}
alreadyDrained = true;
}
});

await once(stream, 'test:watch:drained');

writeFileSync(changedFile, fixtureContent['test.js']);

// eslint-disable-next-line no-unused-vars
for await (const _ of stream);

assert.deepStrictEqual(restartedFiles, [changedFile]);