Flutter: how to test the scroll

7,993

Solution 1

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();

Solution 2

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
);

Solution 3

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.

Solution 4

I highly recommend you to pay attention in the "Cartesian plane" of your screen/dragging movement.

Let me explain:

  1. You should use: await tester.drag(keyCartItemProduct1, Offset(-500.0, 0.0));
  2. However, your "Offset" Command, must obey the same "Cartesian direction" than your Dragging.

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)

Solution 5

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);
Share:
7,993
Little Monkey
Author by

Little Monkey

I'm just a little monkey!

Updated on December 11, 2022

Comments

  • Little Monkey
    Little Monkey over 1 year

    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.

  • Little Monkey
    Little Monkey almost 5 years
    Should I use only these lines or do more? Because only like this doesn't work
  • Wheel Builder
    Wheel Builder over 4 years
    Need to close parenthesis on the first line, but otherwise works!
  • daveoncode
    daveoncode about 4 years
    I'm trying to use this snippet in order to test a PageView scroll, but it seems is not working: gesture = await tester.startGesture(Offset(500, 500)); await gesture.moveBy(Offset(-100, 0));
  • Muhammad Faiq
    Muhammad Faiq over 2 years
    Thank you, worked perfectly for me!
  • luvzfootball
    luvzfootball about 2 years
    I had to add await gesture.up(); before the pump call for the scrolling to work.