@@ -225,6 +225,47 @@ void main() {
225225 expect (find.text ('Load More' ), findsNothing);
226226 },
227227 );
228+
229+ testWidgets (
230+ 'Automatically fetches the next page when scrolling within '
231+ 'loadMoreThreshold of the end' ,
232+ (tester) async {
233+ var callCount = 0 ;
234+
235+ await tester.pumpWidget (
236+ buildTestableWidget (
237+ ScrollInfinity <String >(
238+ maxItems: 5 ,
239+ loadData: (page) {
240+ callCount++ ;
241+ return mockLoadData (
242+ page,
243+ totalItems: 15 ,
244+ maxItemsPerPage: 5 ,
245+ );
246+ },
247+ itemBuilder: (item, index) {
248+ return SizedBox (height: 300 , child: Text (item));
249+ },
250+ ),
251+ ),
252+ );
253+
254+ // First page fills (and overflows) the viewport, so the
255+ // fill-the-screen loop stops after one fetch.
256+ await tester.pumpAndSettle ();
257+ expect (callCount, 1 );
258+ expect (find.text ('Item 5' ), findsNothing);
259+
260+ // Dragging near the bottom must trigger `_onScroll` and fetch
261+ // the next page automatically (no manual "Load More" tap).
262+ await tester.drag (find.byType (ListView ), const Offset (0 , - 1400 ));
263+ await tester.pumpAndSettle ();
264+
265+ expect (callCount, 2 );
266+ expect (find.text ('Item 5' ), findsOneWidget);
267+ },
268+ );
228269 });
229270
230271 /// Tests related to error states and retry logic.
@@ -1027,6 +1068,46 @@ void main() {
10271068 expect (controller.hasError, isFalse);
10281069 },
10291070 );
1071+
1072+ testWidgets (
1073+ 'Detaches the old controller and attaches the new one when the '
1074+ 'controller property changes' ,
1075+ (tester) async {
1076+ final controllerA = ScrollInfinityController ();
1077+ final controllerB = ScrollInfinityController ();
1078+
1079+ Widget buildWith (ScrollInfinityController controller) {
1080+ return buildTestableWidget (
1081+ ScrollInfinity <String >(
1082+ maxItems: 5 ,
1083+ controller: controller,
1084+ loadData: (page) {
1085+ return mockLoadData (page, totalItems: 5 , maxItemsPerPage: 5 );
1086+ },
1087+ itemBuilder: (item, index) => Text (item),
1088+ ),
1089+ );
1090+ }
1091+
1092+ await tester.pumpWidget (buildWith (controllerA));
1093+ await tester.pumpAndSettle ();
1094+ expect (controllerA.isLoading, isFalse);
1095+
1096+ await tester.pumpWidget (buildWith (controllerB));
1097+ await tester.pumpAndSettle ();
1098+
1099+ // The old controller is detached: it must report inert defaults
1100+ // instead of forwarding to the (now different) widget state.
1101+ expect (controllerA.isLoading, isFalse);
1102+ expect (controllerA.hasError, isFalse);
1103+
1104+ // The new controller is attached and drives the live state.
1105+ controllerB.refresh ();
1106+ await tester.pump ();
1107+ expect (controllerB.isLoading, isTrue);
1108+ await tester.pumpAndSettle ();
1109+ },
1110+ );
10301111 });
10311112
10321113 /// Tests for the `enablePullToRefresh` property.
@@ -1162,6 +1243,54 @@ void main() {
11621243 throwsAssertionError,
11631244 );
11641245 });
1246+
1247+ test ('initialPageIndex cannot be negative' , () {
1248+ expect (
1249+ () => ScrollInfinity <String >(
1250+ maxItems: 5 ,
1251+ initialPageIndex: - 1 ,
1252+ loadData: (page) async => [],
1253+ itemBuilder: (item, index) => Text (item),
1254+ ),
1255+ throwsAssertionError,
1256+ );
1257+ });
1258+
1259+ test ('interval must be greater than zero' , () {
1260+ expect (
1261+ () => ScrollInfinity <String ?>(
1262+ maxItems: 5 ,
1263+ interval: 0 ,
1264+ loadData: (page) async => [],
1265+ itemBuilder: (item, index) => Text (item ?? '' ),
1266+ ),
1267+ throwsAssertionError,
1268+ );
1269+ });
1270+
1271+ test ('interval requires a nullable generic type T' , () {
1272+ expect (
1273+ () => ScrollInfinity <String >(
1274+ maxItems: 5 ,
1275+ interval: 2 ,
1276+ loadData: (page) async => [],
1277+ itemBuilder: (item, index) => Text (item),
1278+ ),
1279+ throwsAssertionError,
1280+ );
1281+ });
1282+
1283+ test ('maxRetries cannot be negative' , () {
1284+ expect (
1285+ () => ScrollInfinity <String >(
1286+ maxItems: 5 ,
1287+ maxRetries: - 1 ,
1288+ loadData: (page) async => [],
1289+ itemBuilder: (item, index) => Text (item),
1290+ ),
1291+ throwsAssertionError,
1292+ );
1293+ });
11651294 });
11661295 });
11671296}
0 commit comments