Skip to content

Commit 39bc086

Browse files
committed
test_runner: emit test:watch-drained event
1 parent 3a1f912 commit 39bc086

File tree

3 files changed

+33
-12
lines changed

3 files changed

+33
-12
lines changed

doc/api/test.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,6 +1539,10 @@ This event is only emitted if `--test` flag is passed.
15391539
Emitted when a running test writes to `stdout`.
15401540
This event is only emitted if `--test` flag is passed.
15411541

1542+
### Event: `'test:watch-drained'`
1543+
1544+
Emitted when no more tests are queued for execution in watch mode.
1545+
15421546
## Class: `TestContext`
15431547

15441548
<!-- YAML

lib/internal/test_runner/runner.js

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,6 @@ class FileTest extends Test {
335335
}
336336
}
337337

338-
const runningProcesses = new SafeMap();
339-
const runningSubtests = new SafeMap();
340-
341338
function runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns) {
342339
const subtest = root.createSubtest(FileTest, path, async (t) => {
343340
const args = getRunArgs({ path, inspectPort, testNamePatterns });
@@ -352,11 +349,11 @@ function runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns) {
352349
}
353350

354351
const child = spawn(process.execPath, args, { signal: t.signal, encoding: 'utf8', env, stdio });
355-
runningProcesses.set(path, child);
352+
filesWatcher?.runningProcesses.set(path, child);
353+
filesWatcher?.watcher.watchChildProcessModules(child, path);
356354

357355
let err;
358356

359-
filesWatcher?.watchChildProcessModules(child, path);
360357

361358
child.on('error', (error) => {
362359
err = error;
@@ -388,8 +385,12 @@ function runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns) {
388385
finished(child.stdout, { signal: t.signal }),
389386
]);
390387

391-
runningProcesses.delete(path);
392-
runningSubtests.delete(path);
388+
filesWatcher?.runningProcesses.delete(path);
389+
filesWatcher?.runningSubtests.delete(path);
390+
if (filesWatcher?.runningSubtests.size === 0) {
391+
root.reporter[kEmitMessage]('test:watch-drained');
392+
}
393+
393394
if (code !== 0 || signal !== null) {
394395
if (!err) {
395396
const failureType = subtest.failedSubtests ? kSubtestsFailed : kTestCodeFailure;
@@ -410,9 +411,13 @@ function runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns) {
410411
}
411412

412413
function watchFiles(testFiles, root, inspectPort, signal, testNamePatterns) {
413-
const filesWatcher = new FilesWatcher({ throttle: 500, mode: 'filter' });
414-
filesWatcher.on('changed', ({ owners }) => {
415-
filesWatcher.unfilterFilesOwnedBy(owners);
414+
const runningProcesses = new SafeMap();
415+
const runningSubtests = new SafeMap();
416+
const watcher = new FilesWatcher({ throttle: 500, mode: 'filter' });
417+
const filesWatcher = { __proto__: null, watcher, runningProcesses, runningSubtests };
418+
419+
watcher.on('changed', ({ owners }) => {
420+
watcher.unfilterFilesOwnedBy(owners);
416421
PromisePrototypeThen(SafePromiseAllReturnVoid(testFiles, async (file) => {
417422
if (!owners.has(file)) {
418423
return;
@@ -433,9 +438,10 @@ function watchFiles(testFiles, root, inspectPort, signal, testNamePatterns) {
433438
}));
434439
});
435440
signal?.addEventListener('abort', () => {
436-
filesWatcher.clear();
441+
watcher.clear();
437442
root.postRun();
438443
}, { __proto__: null, once: true });
444+
439445
return filesWatcher;
440446
}
441447

@@ -485,7 +491,7 @@ function run(options) {
485491
root.harness.bootstrapComplete = true;
486492
return SafePromiseAllSettledReturnVoid(testFiles, (path) => {
487493
const subtest = runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns);
488-
runningSubtests.set(path, subtest);
494+
filesWatcher?.runningSubtests.set(path, subtest);
489495
return subtest;
490496
});
491497
};

test/parallel/test-runner-run.mjs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,15 @@ describe('require(\'node:test\').run', { concurrency: true }, () => {
132132
.toArray();
133133
assert.deepStrictEqual(result, ['this should pass']);
134134
});
135+
136+
it('should emit "test:watch-drained" event on watch mode', async () => {
137+
const controller = new AbortController();
138+
await run({ files: [join(testFixtures, 'test/random.cjs')], watch: true, signal: controller.signal })
139+
.on('data', function({ type }) {
140+
console.log(type);
141+
if (type === 'test:watch-drained') {
142+
controller.abort();
143+
}
144+
});
145+
});
135146
});

0 commit comments

Comments
 (0)