Reputation: 6157
I have a ListView.builder with a ScrollController as controller:
_buildListView(state) => ListView.builder(
itemBuilder: (_, int index) => _draw(index, state),
itemCount: state.count
controller: _scrollController,
);
I add a listener to the controller:
View() {
_scrollController.addListener(_onScroll);
}
I would like to test the _onScroll function:
void _onScroll() {
final maxScroll = _scrollController.position.maxScrollExtent;
final currentScroll = _scrollController.position.pixels;
if (maxScroll - currentScroll <= _scrollThreshold) {
_bloc.dispatch(Fetch());
}
}
But I don't know how can I test it. This is what I tried so far:
testWidgets('Should test the scroll',
(WidgetTester tester) async {
await tester.pumpWidget(generateApp());
await tester.pump();
await tester.drag(find.byType(ListView), const Offset(0.0, -300));
await tester.pump();
...
)}
but it doesn't call at all that function.
Upvotes: 26
Views: 26593
Reputation: 441
For my case I tried both scrollUntilVisible
and dragUntilVisible
, but none worked. (maybe because of the nested scrollable widget). This worked for me for scrolling to the bottom of the list:
await tester.drag(
find.byType(ListTile).first,
const Offset(0, -100),
);
Remember to run await tester.pumpAndSettle()
after that.
Upvotes: 0
Reputation: 34180
Scrolling can be tested using dragUntilVisible
, which scrolls the widget till it gets visible on screen, just make sure the right delta is added for moving it vertically or horizontally.
final expectedWidget = find.byText("Find me!");
await tester.dragUntilVisible(
expectedWidget, // what you want to find
find.byType(ListView),
// widget you want to scroll
const Offset(0, 500) // delta to move
);
Upvotes: 6
Reputation: 2345
As an alternative it's also possible to search for the ListView widget itself and retrieve its scroll controller to manipulate it directly:
final listView = tester.widget<ListView>(find.byType(ListView));
final ctrl = listView.controller;
ctrl.jumpTo(ctrl.offset + 300);
await tester.pumpAndSettle(duration);
Upvotes: 3
Reputation: 1441
for those using the new flutter_test
lib, we also have the dragUntilVisible
method:
await tester.dragUntilVisible(
find.text('Earn mana!'), // what you want to find
find.byKey(ValueKey('OnboardingCarousel')), // widget you want to scroll
const Offset(-250, 0), // delta to move
);
Upvotes: 25
Reputation: 928
I highly recommend you to pay attention in the "Cartesian plane" of your screen/dragging movement.
Let me explain:
2.1) Therefore: (The command Offset uses Cartesian 'directions') - lets see: a) Left Dragging: Offset(-500.0, 0.0) b) Right Dragging: Offset(+500.0, 0.0) c) Up Dragging: Offset(0.0, +500.0) d) Down Dragging: Offset(0.0, -500.0)
Upvotes: 2
Reputation: 3414
If you pass the key parameter to the builder:
ListView.builder(key: Key('ListViewKey'),...);
Then finding by key:
await tester.drag(find.byKey(Key('ListViewKey')), const Offset(0.0, -300));
await tester.pump();
Will work.
Upvotes: 13
Reputation: 10861
You can create a TestGesture in your tests and perform a scroll that way.
final gesture = await tester.startGesture(Offset(0, 300)); //Position of the scrollview
await gesture.moveBy(Offset(0, -300)); //How much to scroll by
await tester.pump();
Upvotes: 16