4

I have a widget that displays a list of data from an api and I'm trying to write tests for it's various states starting with it's empty state.

Currently my test pumps the widget in question, the widget makes a network call which I'm mocking and then it checks to see if the empty state text is shown.

This test passes when I run the test on a device using

 flutter run --flavor myTestApp -t test/booking/booking_list_widget_test.dart

But fails when I run it from the IDE (IntelliJ) the failure exception is:

The following TestFailure object was thrown running a test:
Expected: exactly one matching node in the widget tree
Actual: _TextFinder:<zero widgets with text "You're all caught up." (ignoring offstage widgets)>
Which: means none were found but one was expected

It seems to not be waiting for the Duration given to tester.pump and I've tried wrapping it in a tester.runAsync and using pump and settle etc but i cannot get it to pass.

Any ideas welcome I cant share the widget tree but I can share the test

  void main() {
    setupFirebaseAuthMocks();
  
    setUpAll(
      () async {
        SharedPreferences.setMockInitialValues(
          {
            Constants.USER_ID: '1234567890',
          },
        );
      },
    );
  
    testWidgets(
      'emptyListTest',
      (tester) async {
        await _initializeDependencies(tester);
  
        final dio = di.getIt.get<Dio>();
        final dioAdapter = DioAdapter(dio: dio);
  
        dioAdapter.onGet(
          '/url/user/1234567890',
          (server) => server.reply(
            200,
            BookingResponse(
              (b) => b
                ..data = <Booking>[].toBuiltList().toBuilder()
                ..pagination = Pagination((b) => b
                  ..last = ''
                  ..first = ''
                  ..next = ''
                  ..skip = 0
                  ..count = 0).toBuilder(),
            ),
          ),
        );
  
        final testApp = await tester.runAsync(
          () => wordskiiTestApp(
            widgetUnderTest: BookingView(),
          ),
        );
  
        await tester.pumpWidget(testApp!);
        await tester.pump(const Duration(seconds: 1));
  
        expect(find.text('AVAILABLE'), findsOneWidget);
        // debugDumpApp();
  
        expect(
          find.text(
            'You\'re all caught up.',
          ),
          findsOneWidget,
        );
      },
    );
  }
  
  Future<void> _initializeDependencies(WidgetTester tester) async {
    await tester.runAsync(di.getIt.reset);
    await tester.runAsync(di.initTesting);
    await tester.runAsync(di.getIt.allReady);
  }
martinseal1987
  • 1,862
  • 8
  • 44
  • 77
  • From IntelliJ, what command does it run to execute the test? I'm pretty sure it's different from the device test command you use. – xamantra Feb 07 '22 at 08:56
  • I think IntelliJ is running "unit tests". and with flutter's unit test with widgets, async codes don't run properly. A lot of articles mention this problem. – xamantra Feb 07 '22 at 08:58
  • yh so they run a fake async and you can get normal functionality by using tester.runAsync but this should run the same on or off a device as these are widget tests and not integration flutter driver tests – martinseal1987 Feb 07 '22 at 09:02
  • could you plz give a full minimal reproducible sample? – ch271828n Feb 10 '22 at 11:46
  • and please dump the whole widget tree and see what is happening – ch271828n Feb 10 '22 at 11:47
  • The widget tree looks like you would expect, its essentially a list that loads after making the mocked network call, and as mentioned this passes on a device the problem is pump isnt waiting even if i add a duration it seems to just skip straight past it, i cant give you the dump logs but i can probably give a minimal repro – martinseal1987 Feb 10 '22 at 12:37

1 Answers1

1

On which Widget is 'You\'re all caught up' expected? I had similar issues encountered previously when I tried find.textContaining() on a ListView item. I was able to solve my issue by finding out which widget the Text should appear.

On mine, I had to use find.widgetWithText(InkWell, String). To find out the which Widget it is, you can tap on the widget displayed on screen when you've run the test (i.e. on an emulator). The logs should display the tapped Widget.

Omatt
  • 8,564
  • 2
  • 42
  • 144
  • when you tap on that widget on the emulator it will also give you options for finding the widget, unfortunately this is just a text widget which would be there if the test would await the pump, as it does when run on a device – martinseal1987 Feb 11 '22 at 14:44
  • bounty expired congrats – martinseal1987 Feb 14 '22 at 07:34