From d1c2643a8a893a8bc7633fbac00a65bc1fa520a3 Mon Sep 17 00:00:00 2001 From: inoway46 Date: Fri, 6 Nov 2026 17:36:21 +0900 Subject: [PATCH] test: deflake test-watch-mode-files_watcher Some test cases made a single change right after creating a watcher. On macOS, libuv starts the FSEvents stream asynchronously, so that change could be missed and the test hung until it timed out. Keep making the change until the watcher reports it, as the other cases in the file already do. Refs: https://github.com/nodejs/reliability/issues/1715 Refs: https://github.com/nodejs/reliability/issues/1644 Signed-off-by: inoway46 --- test/parallel/test-watch-mode-files_watcher.mjs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/test/parallel/test-watch-mode-files_watcher.mjs b/test/parallel/test-watch-mode-files_watcher.mjs index 10e078286e07..f5cc630f8be1 100644 --- a/test/parallel/test-watch-mode-files_watcher.mjs +++ b/test/parallel/test-watch-mode-files_watcher.mjs @@ -37,6 +37,9 @@ describe('watch mode file watcher', () => { afterEach(() => watcher.clear()); let counter = 0; + // A newly created watcher might not report changes right away (e.g. on + // macOS the FSEvents stream is started asynchronously), so a single write + // can be missed. Keep writing until a change is reported. function writeAndWaitForChanges(watcher, file) { return new Promise((resolve) => { const interval = setInterval(() => writeFileSync(file, `write ${counter++}`), 100); @@ -93,16 +96,23 @@ describe('watch mode file watcher', () => { ['--watch', file1], { stdio: ['ignore', 'pipe', 'ignore'] }); let completeCount = 0; + let appendInterval; for await (const line of createInterface(child.stdout)) { if (!line.startsWith('Completed running')) { continue; } completeCount++; if (completeCount === 1) { + // The watcher of the child might not report changes yet, so keep + // changing the file until it is reloaded. The interval is longer than + // the default debounce of watch mode so the restart is not deferred. appendFileSync(file1, '\n // append 1'); + appendInterval = setInterval(() => appendFileSync(file1, '\n // append'), + common.platformTimeout(1000)); } // The file is reloaded due to file watching if (completeCount === 2) { + clearInterval(appendInterval); child.kill(); } } @@ -135,6 +145,7 @@ describe('watch mode file watcher', () => { watcher.filterFile(file); files.push(file); } + await writeAndWaitForChanges(watcher, files[0]); files.forEach((file) => writeFileSync(file, '1')); files.forEach((file) => writeFileSync(file, '2')); @@ -183,10 +194,7 @@ describe('watch mode file watcher', () => { const file = tmpdir.resolve('file5'); watcher.watchPath(tmpdir.path); - const changed = once(watcher, 'changed'); - await setTimeout(common.platformTimeout(100)); // avoid throttling - writeFileSync(file, 'changed'); - await changed; + await writeAndWaitForChanges(watcher, file); assert.strictEqual(changesCount, 1); });