Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find off-screen ListView child in widget tests?

When displaying multiple children in a ListView, if a child is off-screen it can't be found by a widget test. Here's a full example:

main.dart

import 'package:flutter/material.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: Scaffold(body: Test()));
  }
}

class Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        Container(
          height: 600,
          color: Colors.red,
        ),
        Text("Find me!"),
      ],
    );
  }
}

main_test.dart

import 'package:flutter_app/main.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets("Find text", (WidgetTester tester) async {
    final testableWidget = App();

    await tester.pumpWidget(testableWidget);

    expect(find.text("Find me!"), findsOneWidget);
  });
}

This test fails, however if I change the height of the Container in main.dart to 599 it works.

Anyone know why this happens? Is it a bug? Is there a way around it?

like image 509
Jordan Davies Avatar asked Feb 12 '19 14:02

Jordan Davies


People also ask

What is the main feature of ListView widget?

ListView is the most commonly used scrolling widget. It displays its children one after another in the scroll direction. In the cross axis, the children are required to fill the ListView. If non-null, the itemExtent forces the children to have the given extent in the scroll direction.

What is ListView widget in flutter?

In Flutter, ListView is a scrollable list of widgets arranged linearly. It displays its children one after another in the scroll direction i.e, vertical or horizontal. There are different types of ListViews : ListView. ListView.

What is widget testing?

The widget test is testing UI components, so it is also called Component Testing. It is used to test a single widget. The main goal of widget testing is to check whether the widget works as expected. A user can write test cases for every widget present in the project.


3 Answers

Tests should behave as your app would do, otherwise, your tests become useless (since you're not testing the real behavior). As such, this is not a bug.

You have to manually scroll the ListView inside your tests to make it load more widgets.

This can be done using tester:

final gesture = await tester.startGesture(Offset.zero /* THe position of your listview */ );
// Manual scroll
await gesture.moveBy(const Offset(0, 100));

await tester.pump(); // flush the widget tree 
like image 169
Rémi Rousselet Avatar answered Oct 17 '22 17:10

Rémi Rousselet


Setting skipOffstate to false in your Finder is another approach. Try this:

expect(find.text("Find me!", skipOffstage: false), findsOneWidget);
like image 28
Touré Holder Avatar answered Oct 17 '22 19:10

Touré Holder


dragUntilVisible helps to scroll Listview or SingleChildScrollView to scroll till the expected widget is visible

     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
          duration: Duration(seconds: 2));
like image 39
Jitesh Mohite Avatar answered Oct 17 '22 19:10

Jitesh Mohite