cmdrootaccess / another-flushbar

A flexible widget for user notification. Customize your text, button, duration, animations and much more. For Android devs, it is made to replace Snackbars and Toasts.
https://pub.dev/packages/another_flushbar
MIT License
145 stars 89 forks source link

Widget testing for Flushbar with duration #40

Open stevanusw28 opened 3 years ago

stevanusw28 commented 3 years ago

Hello, I try to create the widget test for the flushbar component (with duration). However, is seems there is timer that block the process like this:

Pending timers: Timer (duration: 0:00:02.000000, periodic: false), created:

0 new FakeTimer._ (package:fake_async/fake_async.dart:284:41)

1 FakeAsync._createTimer (package:fake_async/fake_async.dart:248:27)

2 FakeAsync.run. (package:fake_async/fake_async.dart:181:19)

5 FlushbarRoute._configureTimer (package:another_flushbar/flushbar_route.dart:393:16)

6 FlushbarRoute.didPush (package:another_flushbar/flushbar_route.dart:347:5)

7 _RouteEntry.handlePush (package:flutter/src/widgets/navigator.dart:3013:46)

8 NavigatorState._flushHistoryUpdates (package:flutter/src/widgets/navigator.dart:3958:17)

9 NavigatorState._pushEntry (package:flutter/src/widgets/navigator.dart:4573:5)

10 NavigatorState.push (package:flutter/src/widgets/navigator.dart:4480:5)

11 Flushbar.show (package:another_flushbar/flushbar.dart:267:10)

12 _RandomUserScreenState._buildGenerateButton. (package:feature_user/presentation/views/random_user_screen.dart:110:15)

(elided 2 frames from dart:async) ══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════ The following assertion was thrown running a test (but after the test had completed): A Timer is still pending even after the widget tree was disposed. 'package:flutter_test/src/binding.dart': Failed assertion: line 1245 pos 12: '!timersPending' When the exception was thrown, this was the stack: #2 AutomatedTestWidgetsFlutterBinding._verifyInvariants (package:flutter_test/src/binding.dart:1245:12) #3 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:806:7) (elided 2 frames from class _AssertionError)

Because of this, I can only expect the flushbar value just after the timer process done like this:

      // Duration of flushbar is 2 second
      await tester.pumpAndSettle(Duration(seconds: 2));
      final flushbarSuccess = find.text("Successfully added");
      expect(flushbarSuccess, findsOneWidget);

However, this will give the test result is failed because the flushbarSuccess already dismissed after 2 second. Is there any way to test the Flushbar?

kharisazhar commented 3 years ago

Depends on your implementation, is there only Flushbar with duration 2 sec ? or you have some Timer(...);

in my case i added difference -1 second and add pump again after expect , and finally works

Example :

// My Snackbar

Flushbar(
            title: 'Hey Ninja',
            message:
                'Lorem Ipsum is simply dummy text of the printing and typesetting industry',
            duration: Duration(seconds: 3),
          ).show(context);

// Widget Test

await tester.pump(Duration(seconds: 2));
      final flushbarSuccess = find.text("Hey Ninja");
      expect(flushbarSuccess, findsOneWidget);
await tester.pump(Duration(seconds: 2));

gap 1 seconds means to execute matcher before flush bar is gone

JideGuru commented 2 years ago

@stevanusw28 Did you later find a way to test the Flushbar?

tijanirf commented 2 years ago

Depends on your implementation, is there only Flushbar with duration 2 sec ? or you have some Timer(...);

in my case i added difference -1 second and add pump again after expect , and finally works

Example :

// My Snackbar

Flushbar(
            title: 'Hey Ninja',
            message:
                'Lorem Ipsum is simply dummy text of the printing and typesetting industry',
            duration: Duration(seconds: 3),
          ).show(context);

// Widget Test

await tester.pump(Duration(seconds: 2));
      final flushbarSuccess = find.text("Hey Ninja");
      expect(flushbarSuccess, findsOneWidget);
await tester.pump(Duration(seconds: 2));

gap 1 seconds means to execute matcher before flush bar is gone

This solution at least not working for me.

In my implementation, the flushbar is wrapped by WidgetsBinding.instance!.addPostFrameCallback(). Already tried using tester.binding.scheduleFrame() and tester.binding.scheduleWarmUpFrame() but still not working

source: https://stackoverflow.com/questions/57612693/widget-test-a-widget-which-uses-widgetsbinding-instance-addpostframecallback