[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

test: hold each watcher probe state longer than a poll interval

Vladimir Sheremet (Jul 27, 2026, 3:09 PM +0200) 007f50dc bfa35002

+24 -6
+24 -6
test/test-utils/index.ts
··· 44 44 45 45 const process_ = process 46 46 47 + // Polling interval of the file watcher in spawned watch-mode instances. The 48 + // watcher-ready probe derives its timing from it: each probe state must 49 + // outlive a full poll cycle, or the poller can keep sampling the state that 50 + // matches its baseline and never observe a difference. 51 + const WATCH_POLL_INTERVAL = 100 52 + 47 53 export function createConsole({ tty, std }: { tty?: boolean; std?: 'inherit' } = {}) { 48 54 const stdout = new Writable({ 49 55 write(chunk, __, callback) { ··· 239 245 // misses change events, so enforce polling for consistency 240 246 // https://github.com/vitejs/vite/blob/b723a753ced0667470e72b4853ecda27b17f546a/playground/vitestSetup.ts#L211 241 247 usePolling: true, 242 - interval: 100, 248 + interval: WATCH_POLL_INTERVAL, 243 249 ...viteConfig.server?.watch, 244 250 }, 245 251 ...viteConfig?.server, ··· 336 342 // verify end-to-end: keep cycling a probe file in the root until the watcher 337 343 // reports it. The probe is recreated rather than rewritten because a creation 338 344 // folded into the initial scan of the file AND its directory leaves nothing to 339 - // rescan; deleting and recreating it bumps the directory mtime every cycle, so 340 - // a live directory poller always sees a difference, and any probe event 341 - // (`add`, `change` or `unlink`) proves delivery. 345 + // rescan; alternating present/absent guarantees the current state differs from 346 + // whichever state the poller's baseline captured, and any probe event (`add`, 347 + // `change` or `unlink`) proves delivery. Each state is held for multiple poll 348 + // intervals: on a loaded runner, a cycle as fast as the poll interval aliases 349 + // with it — every rescan can land when the probe is back in the state matching 350 + // the poller's baseline, and no event ever fires. 342 351 // 343 352 // The scan can also surface writes made by the PREVIOUS test (an `afterEach` 344 353 // restoring a fixture right before this instance started) as fresh change ··· 392 401 } 393 402 watcher.on('all', onWatcherEvent) 394 403 try { 404 + const holdProbeState = async () => { 405 + const stateEnd = Date.now() + WATCH_POLL_INTERVAL * 2.5 406 + while (Date.now() < stateEnd) { 407 + if (probeSeen) { 408 + return 409 + } 410 + await new Promise(resolve => setTimeout(resolve, 25)) 411 + } 412 + } 395 413 while (true) { 396 414 if (probeSeen) { 397 415 break ··· 403 421 ) 404 422 } 405 423 fs.writeFileSync(probe, `${Date.now()}`, 'utf-8') 406 - await new Promise(resolve => setTimeout(resolve, 50)) 424 + await holdProbeState() 407 425 if (probeSeen) { 408 426 break 409 427 } 410 428 fs.rmSync(probe, { force: true }) 411 - await new Promise(resolve => setTimeout(resolve, 50)) 429 + await holdProbeState() 412 430 } 413 431 414 432 while (Date.now() - lastEventAt < 200 && Date.now() < deadline) {