@@ -10,19 +10,22 @@ import portsMap from "../ports-map.js";
1010
1111const port = portsMap [ "static-watch-output-path" ] ;
1212
13- // Long enough that a watcher which does report the write has reported it: the
14- // control below rewrites a file beside the output directory and is seen well
15- // inside this window, so an empty list after it means the write was ignored
16- // rather than merely slow.
17- const SETTLE_MS = 3000 ;
18-
19- const settle = ( ) =>
13+ // The ignored file is rewritten this many times, this far apart, so that the
14+ // window spans several seconds. A single write could land while chokidar is
15+ // still discovering the nested directory and be lost; a stream of them cannot
16+ // all be.
17+ const REWRITES = 12 ;
18+ const REWRITE_INTERVAL_MS = 250 ;
19+
20+ const sleep = ( ms ) =>
2021 new Promise ( ( resolve ) => {
21- setTimeout ( resolve , SETTLE_MS ) ;
22+ setTimeout ( resolve , ms ) ;
2223 } ) ;
2324
24- // Rewrites `file` until the watcher reports it, so the caller knows the initial
25- // scan is over and later writes cannot be silently dropped.
25+ // Rewrites `file` until the watcher reports it, which establishes that the
26+ // watcher is live. It does not establish that every nested path has been
27+ // discovered, so it is only the starting gun — the assertions below do not
28+ // rest on it alone.
2629const waitUntilWatching = async ( reloads , file , timeout = 20000 ) => {
2730 const started = Date . now ( ) ;
2831
@@ -32,9 +35,7 @@ const waitUntilWatching = async (reloads, file, timeout = 20000) => {
3235 }
3336
3437 await fsPromises . writeFile ( file , `warm-up ${ Date . now ( ) } ` ) ;
35- await new Promise ( ( resolve ) => {
36- setTimeout ( resolve , 250 ) ;
37- } ) ;
38+ await sleep ( REWRITE_INTERVAL_MS ) ;
3839 }
3940} ;
4041
@@ -117,10 +118,9 @@ describe("static watching and output.path", () => {
117118 await server . start ( ) ;
118119
119120 // chokidar drops events raised before its initial scan finishes, so a write
120- // sent too early is simply lost and the absence of a reload would prove
121- // nothing. Rewriting the control file until the watcher answers establishes
122- // that it is live, which neither `getWatched()` nor a late `ready` listener
123- // can: the first fills in during the scan, the second has already fired.
121+ // sent too early is simply lost. `ready` cannot be awaited from here — the
122+ // watcher is created inside `start()` and may already have emitted it — so
123+ // the control file is rewritten until the watcher answers.
124124 await waitUntilWatching ( reloads , outsideOutput ) ;
125125 reloads . length = 0 ;
126126 } ) ;
@@ -130,11 +130,28 @@ describe("static watching and output.path", () => {
130130 fs . rmSync ( tempDirectory , { recursive : true , force : true } ) ;
131131 } ) ;
132132
133+ it ( "should not watch the output directory at all" , ( ) => {
134+ // the strongest form of the assertion, and the only one that does not
135+ // depend on event timing: chokidar lists what it decided to watch, so a
136+ // predicate that failed to exclude the output directory shows up here even
137+ // if no write ever raced with the scan
138+ const watched = server . staticWatchers . flatMap ( ( watcher ) =>
139+ Object . keys ( watcher . getWatched ( ) ) ,
140+ ) ;
141+
142+ expect ( watched ) . toContain ( tempDirectory ) ;
143+ expect ( watched ) . not . toContain ( outputPath ) ;
144+ } ) ;
145+
133146 it ( "should not reload when a file inside output.path is rewritten" , async ( ) => {
134147 // the compilation already reaches the client through the middleware, so a
135- // reload here only fires because the build wrote its own output
136- await fsPromises . writeFile ( insideOutput , "emitted again" ) ;
137- await settle ( ) ;
148+ // reload here only fires because the build wrote its own output. Rewriting
149+ // throughout the window rather than once means a single write lost to the
150+ // initial scan cannot hide a broken predicate.
151+ for ( let index = 0 ; index < REWRITES ; index ++ ) {
152+ await fsPromises . writeFile ( insideOutput , `emitted ${ index } ` ) ;
153+ await sleep ( REWRITE_INTERVAL_MS ) ;
154+ }
138155
139156 expect ( reloads ) . toHaveLength ( 0 ) ;
140157 } ) ;
0 commit comments