Flutter:如何测试滚动功能

21

我有一个带有 ScrollController 的 ListView.builder,如下所示:

  _buildListView(state) => ListView.builder(
        itemBuilder: (_, int index) => _draw(index, state),
        itemCount: state.count
        controller: _scrollController,
      );

我向控制器添加了一个监听器:

  View() {
    _scrollController.addListener(_onScroll);
  }

我想测试_onScroll函数:

 void _onScroll() {
    final maxScroll = _scrollController.position.maxScrollExtent;
    final currentScroll = _scrollController.position.pixels;
    if (maxScroll - currentScroll <= _scrollThreshold) {
      _bloc.dispatch(Fetch());
    }
  }

但是我不知道如何测试它。目前为止,这是我尝试过的:

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

)}

但它根本没有调用那个函数。

7个回答

21

如果您正在使用新的flutter_test库,我们也有dragUntilVisible方法:

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

这对我来说在iOS模拟器和实体iPhone上都有效。 - SM Abu Taher Asif

15
你可以在测试中创建一个TestGesture并以这种方式进行滚动。
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();

3
我应该只使用这些代码行还是需要更多呢?因为仅仅这样是不起作用的。 - Little Monkey
第一行需要闭合括号,但除此之外都可以正常工作! - Wheel Builder
我正在尝试使用这段代码片段来测试PageView滚动,但似乎它没有起作用:gesture = await tester.startGesture(Offset(500, 500)); await gesture.moveBy(Offset(-100, 0)); - daveoncode
2
我必须在泵操作之前添加 await gesture.up(); 以使滚动工作。 - luvzfootball
这个解决方案在iOS模拟器上对我有效,但在实体iPhone上不起作用。对于实体iPhone,我需要按照这个解决方案进行操作:https://dev59.com/RFMI5IYBdhLWcg3waqs4#67990754 - SM Abu Taher Asif

10
如果您将key参数传递给构建器:
ListView.builder(key: Key('ListViewKey'),...);

然后通过关键字查找:

await tester.drag(find.byKey(Key('ListViewKey')), const Offset(0.0, -300));
await tester.pump();

可以工作。


5

可以使用dragUntilVisible测试滚动,它会滚动小部件直到在屏幕上可见,只需确保添加正确的增量以垂直或水平移动它。

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

3
作为另一种选择,也可以搜索ListView小部件本身并检索其滚动控制器以直接操作它:
final listView = tester.widget<ListView>(find.byType(ListView));
final ctrl = listView.controller;
ctrl.jumpTo(ctrl.offset + 300);
await tester.pumpAndSettle(duration);

2

我强烈建议您关注屏幕/拖动移动的"笛卡尔平面"。

让我解释一下:

  1. 您应该使用: await tester.drag(keyCartItemProduct1, Offset(-500.0, 0.0));
  2. 然而,您的"Offset"命令必须遵守与拖动相同的"笛卡尔方向"。

2.1) 因此:(命令Offset使用笛卡尔方向)- 让我们看看: a) 向左拖动:Offset(-500.0, 0.0) b) 向右拖动:Offset(+500.0, 0.0) c) 向上拖动:Offset(0.0, +500.0) d) 向下拖动:Offset(0.0, -500.0)


0

对于我的情况,我尝试了scrollUntilVisibledragUntilVisible,但都没有起作用(可能是因为嵌套的可滚动小部件)。这对我来说适用于滚动到列表底部:

await tester.drag(
  find.byType(ListTile).first,
  const Offset(0, -100),
);

记得在此之后运行await tester.pumpAndSettle()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接