@@ -296,6 +296,90 @@ describe('Poll', () => {
296296 }
297297 expect ( ticker . join ( ' ' ) ) . to . equal ( expected ) ;
298298 } ) ;
299+
300+ it ( 'should not drop rapid schedule calls' , async ( ) => {
301+ poll = new Poll < number > ( {
302+ auto : false ,
303+ factory : ( ) => Promise . resolve ( 0 ) ,
304+ frequency : { interval : Poll . NEVER } ,
305+ name : '@lumino/polling:Poll#[Symbol.asyncIterator]-4'
306+ } ) ;
307+ void poll . start ( ) ;
308+ await poll . tick ;
309+
310+ const payloads = [ 1 , 2 , 3 , 4 , 5 ] ;
311+ const collected : number [ ] = [ ] ;
312+ const consumption = ( async ( ) => {
313+ for await ( const state of poll ) {
314+ if (
315+ state . phase === 'resolved' &&
316+ typeof state . payload === 'number' &&
317+ state . payload > 0
318+ ) {
319+ collected . push ( state . payload as number ) ;
320+ }
321+ if ( collected . length === payloads . length ) {
322+ break ;
323+ }
324+ }
325+ } ) ( ) ;
326+
327+ // Rapidly schedule 5 payloads synchronously.
328+ for ( const payload of payloads ) {
329+ void poll . schedule ( { payload, phase : 'resolved' } ) ;
330+ }
331+
332+ await consumption ;
333+ expect ( collected ) . to . deep . equal ( payloads ) ;
334+ } ) ;
335+
336+ it ( 'should stop yielding after disposal' , async ( ) => {
337+ poll = new Poll ( {
338+ auto : false ,
339+ factory : ( ) => Promise . resolve ( ) ,
340+ frequency : { interval : Poll . NEVER } ,
341+ name : '@lumino/polling:Poll#[Symbol.asyncIterator]-5'
342+ } ) ;
343+ void poll . start ( ) ;
344+ await poll . tick ;
345+
346+ // Schedule several ticks then dispose immediately.
347+ void poll . schedule ( { payload : 'a' , phase : 'resolved' } ) ;
348+ void poll . schedule ( { payload : 'b' , phase : 'resolved' } ) ;
349+ void poll . schedule ( { payload : 'c' , phase : 'resolved' } ) ;
350+ poll . dispose ( ) ;
351+
352+ const collected : string [ ] = [ ] ;
353+ for await ( const state of poll ) {
354+ collected . push ( state . phase ) ;
355+ }
356+ // Iterator exits immediately — no states yielded from a disposed poll.
357+ expect ( collected ) . to . deep . equal ( [ ] ) ;
358+ } ) ;
359+
360+ it ( 'should work identically for one-tick-at-a-time polling' , async ( ) => {
361+ const total = 5 ;
362+ let i = 0 ;
363+ poll = new Poll ( {
364+ auto : false ,
365+ factory : async ( ) => ++ i ,
366+ frequency : { interval : Poll . IMMEDIATE } ,
367+ name : '@lumino/polling:Poll#[Symbol.asyncIterator]-6'
368+ } ) ;
369+ const ticker : IPoll . Phase < any > [ ] = [ ] ;
370+ void poll . start ( ) ;
371+ for await ( const state of poll ) {
372+ ticker . push ( state . phase ) ;
373+ if ( i >= total ) {
374+ poll . dispose ( ) ;
375+ break ;
376+ }
377+ }
378+ // Should see started, then resolved for each factory call.
379+ expect ( ticker [ 0 ] ) . to . equal ( 'started' ) ;
380+ expect ( ticker . slice ( 1 ) . every ( p => p === 'resolved' ) ) . to . equal ( true ) ;
381+ expect ( ticker . length ) . to . be . greaterThan ( 1 ) ;
382+ } ) ;
299383 } ) ;
300384
301385 describe ( '#tick' , ( ) => {
0 commit comments