@@ -291,14 +291,14 @@ public void CanLimitMaxItemsRendered(bool useAppContext)
291291 // we only render 10 items due to the MaxItemCount setting
292292 var scrollArea = Browser . Exists ( By . Id ( "virtualize-scroll-area" ) ) ;
293293 var getItems = ( ) => scrollArea . FindElements ( By . ClassName ( "my-item" ) ) ;
294- Browser . Equal ( 10 , ( ) => getItems ( ) . Count ) ;
294+ Browser . Equal ( 16 , ( ) => getItems ( ) . Count ) ;
295295 Browser . Equal ( "Id: 0; Name: Thing 0" , ( ) => getItems ( ) . First ( ) . Text ) ;
296296
297297 // Scrolling still works and loads new data, though there's no guarantee about
298298 // exactly how many items will show up at any one time
299299 Browser . ExecuteJavaScript ( "document.getElementById('virtualize-scroll-area').scrollTop = 300;" ) ;
300300 Browser . NotEqual ( "Id: 0; Name: Thing 0" , ( ) => getItems ( ) . First ( ) . Text ) ;
301- Browser . True ( ( ) => getItems ( ) . Count > 3 && getItems ( ) . Count <= 10 ) ;
301+ Browser . True ( ( ) => getItems ( ) . Count > 3 && getItems ( ) . Count <= 16 ) ;
302302 }
303303
304304 [ Fact ]
@@ -573,6 +573,101 @@ public void EmptyContentRendered_Async()
573573 int GetPlaceholderCount ( ) => Browser . FindElements ( By . Id ( "async-placeholder" ) ) . Count ;
574574 }
575575
576+ [ Fact ]
577+ public void CanElevateEffectiveMaxItemCount_WhenOverscanExceedsMax ( )
578+ {
579+ Browser . MountTestComponent < VirtualizationLargeOverscan > ( ) ;
580+ var container = Browser . Exists ( By . Id ( "virtualize-large-overscan" ) ) ;
581+ // Ensure we have an initial contiguous batch and the elevated effective max has kicked in (>= OverscanCount)
582+ var indices = GetVisibleItemIndices ( ) ;
583+ Browser . True ( ( ) => indices . Count >= 200 ) ;
584+
585+ // Give focus so PageDown works
586+ container . Click ( ) ;
587+
588+ var js = ( IJavaScriptExecutor ) Browser ;
589+ var lastMaxIndex = - 1 ;
590+ var lastScrollTop = - 1L ;
591+
592+ // Check if we've reached (or effectively reached) the bottom
593+ var scrollHeight = ( long ) js . ExecuteScript ( "return arguments[0].scrollHeight" , container ) ;
594+ var clientHeight = ( long ) js . ExecuteScript ( "return arguments[0].clientHeight" , container ) ;
595+ var scrollTop = ( long ) js . ExecuteScript ( "return arguments[0].scrollTop" , container ) ;
596+ while ( scrollTop + clientHeight < scrollHeight )
597+ {
598+ // Validate contiguity on the current page
599+ Browser . True ( ( ) => IsCurrentViewContiguous ( indices ) ) ;
600+
601+ // Track progress in indices
602+ var currentMax = indices . Max ( ) ;
603+ Assert . True ( currentMax >= lastMaxIndex , $ "Unexpected backward movement: previous max { lastMaxIndex } , current max { currentMax } .") ;
604+ lastMaxIndex = currentMax ;
605+
606+ // Send PageDown
607+ container . SendKeys ( Keys . PageDown ) ;
608+
609+ // Wait for scrollTop to change (progress) to avoid infinite loop
610+ var prevScrollTop = scrollTop ;
611+ Browser . True ( ( ) =>
612+ {
613+ var st = ( long ) js . ExecuteScript ( "return arguments[0].scrollTop" , container ) ;
614+ if ( st > prevScrollTop )
615+ {
616+ lastScrollTop = st ;
617+ return true ;
618+ }
619+ return false ;
620+ } ) ;
621+ scrollHeight = ( long ) js . ExecuteScript ( "return arguments[0].scrollHeight" , container ) ;
622+ clientHeight = ( long ) js . ExecuteScript ( "return arguments[0].clientHeight" , container ) ;
623+ scrollTop = ( long ) js . ExecuteScript ( "return arguments[0].scrollTop" , container ) ;
624+ }
625+
626+ // Final contiguous assertion at bottom
627+ Browser . True ( ( ) => IsCurrentViewContiguous ( ) ) ;
628+
629+ // Helper: check visible items contiguous with no holes
630+ bool IsCurrentViewContiguous ( List < int > existingIndices = null )
631+ {
632+ var indices = existingIndices ?? GetVisibleItemIndices ( ) ;
633+ if ( indices . Count == 0 )
634+ {
635+ return false ;
636+ }
637+
638+ if ( indices [ ^ 1 ] - indices [ 0 ] != indices . Count - 1 )
639+ {
640+ return false ;
641+ }
642+ for ( var i = 1 ; i < indices . Count ; i ++ )
643+ {
644+ if ( indices [ i ] - indices [ i - 1 ] != 1 )
645+ {
646+ return false ;
647+ }
648+ }
649+ return true ;
650+ }
651+
652+ List < int > GetVisibleItemIndices ( )
653+ {
654+ var elements = container . FindElements ( By . CssSelector ( ".large-overscan-item" ) ) ;
655+ var list = new List < int > ( elements . Count ) ;
656+ foreach ( var el in elements )
657+ {
658+ var text = el . Text ;
659+ if ( text . StartsWith ( "Item " , StringComparison . Ordinal ) )
660+ {
661+ if ( int . TryParse ( text . AsSpan ( 5 ) , NumberStyles . Integer , CultureInfo . InvariantCulture , out var value ) )
662+ {
663+ list . Add ( value ) ;
664+ }
665+ }
666+ }
667+ return list ;
668+ }
669+ }
670+
576671 private string [ ] GetPeopleNames ( IWebElement container )
577672 {
578673 var peopleElements = container . FindElements ( By . CssSelector ( ".person span" ) ) ;
0 commit comments