Finding a widget inside of a CustomScrollView in Flutter test

648

I had the same problem and I ended up using the dragUntilVisible() method instead of scrollUntilVisible().

Example of scrolling down until the widget is visible:

await tester.dragUntilVisible(myWidget, customScrollView, Offset(0, -500));
Share:
648
Matteo
Author by

Matteo

Updated on December 01, 2022

Comments

  • Matteo
    Matteo over 1 year


    I have encountered an error when trying to test my Flutter App. I have a custom widget that is at the bottom (out of the first viewport) of a CustomScrollView widget. In my test, I want to verify that it is actually there.
    I have already tried to use WidgetTester.scrollUntilVisible as well as WidgetTester.drag (like it was done in the tests of the flutter framework). Additionally, I tried to refactor my tests with the FlutterDriver which just messed everything else up completely.
    How do I scroll to the bottom of a CustomScrollView inside of a test?
    This minimal reproduction shows the application containing the CustomScrollView which has a Container widget with the height of one screen (so that the widget I want to find is out of the initial view)

    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
              body: CustomScrollView(
            slivers: [
              SliverToBoxAdapter(
                child: Container(
                  height: MediaQuery.of(context).size.height,
                ),
              ),
              MyWidget(),
            ],
          )),
        );
      }
    }
    
    class MyWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return SliverToBoxAdapter(
          child: Container(
            height: 100,
            width: 100,
          ),
        );
      }
    }
    
    

    Here is the test I initially wrote to find the widget, which failed of course.

    void main() {
      testWidgets('main contains mywidget', (WidgetTester tester) async {
        // arange
        await tester.pumpWidget(MyApp());
        // act
        final myWidget = find.byType(MyWidget);
        // assert
        expect(myWidget, findsOneWidget);
      });
    }
    

    In this iteration, I used the WidgetTester.scrollUntilVisible function but got the error below.

    void main() {
      testWidgets('main contains mywidget', (WidgetTester tester) async {
        // arange
        await tester.pumpWidget(MyApp());
        // act
        final myWidget = find.byType(MyWidget);
        final customScrollView = find.byType(CustomScrollView);
        await tester.scrollUntilVisible(myWidget, 100,
            scrollable: customScrollView);
        await tester.pump();
        // assert
        expect(myWidget, findsOneWidget);
      });
    }
    
    ══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
    The following _CastError was thrown running a test:
    type 'CustomScrollView' is not a subtype of type 'Scrollable' in type cast
    
    When the exception was thrown, this was the stack:
    #0      WidgetController.widget (package:flutter_test/src/controller.dart:66:44)
    #1      WidgetController.scrollUntilVisible.<anonymous closure> (package:flutter_test/src/controller.dart:995:15)
    #2      WidgetController.scrollUntilVisible.<anonymous closure> (package:flutter_test/src/controller.dart:993:39)
    #5      TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:72:41)
    #6      WidgetController.scrollUntilVisible (package:flutter_test/src/controller.dart:993:27)
    #7      main.<anonymous closure> (file:///C:/Users/X/test_example/test/main_test.dart:12:18)
    <asynchronous suspension>
    <asynchronous suspension>
    (elided 3 frames from dart:async and package:stack_trace)
    

    I appreciate any help or suggestions on how to fix this issue and successfully test my CustomScrollView