vendredi 8 février 2019

How to test widget that is instantiated in didUpdateWidget() in Flutter?

I have a StatefulWidget that creates an AnimatedCrossFade widget in didUpdateWidget(), and saves it as animation. Here's a pared down example:

class BackgroundImage extends StatefulWidget {
  final Color colorA;
  final Color colorB;

  const BackgroundImage({
      this.colorA,
      this.colorB,
  });
}

class _BackgroundImageState extends State<BackgroundImage> {
  Widget _animation;

  @override
  void didUpdateWidget(Widget old) {
    super.didUpdateWidget(old);
    _buildBackgroundA(colorA).then((backgroundA) {
      _buildBackgroundB(colorB).then(backgroundB) {
        print(backgroundA); // this is not null
        print(backgroundB); // this is not null
        _animation = AnimatedCrossFade(
          duration: Duration(seconds: 15),
          firstChild: backgroundA,
          secondChild: backgroundB,
          crossFadeState: someVarToSwitchColors,
              ? CrossFadeState.showFirst
              : CrossFadeState.showSecond,
          );
       }
     }
  }

  @override
  Widget build(BuildContext context) {
    return _animation != null ? _animation : Container();
  }
}

_buildBackgroundA() and _buildBackgroundB() are async functions that reuturn Future<Widget>. This works fine in my app - didUpdateWidget() is called, my AnimatedCrossFade shows up and animates between the two backgrounds.

However, I'm having trouble finding AnimatedCrossFade in my test. I'm able to find my other Stateless widgets, and also able to find the BackgroundImage widget. I have something like:

    await tester.pump();
    await tester.pumpAndSettle(Duration(minutes: 1));
    expect(
        find.descendant(
            of: find.byType(BackgroundImage),
            matching: find.byType(AnimatedCrossFade)),
        findsOneWidget);

This fails as it can't find AnimatedCrossFade.

If I change my build() function to:

  @override
  Widget build(BuildContext context) {
    return AnimatedCrossFade(...);
  }

I'm able to find my widget. So I suspect it has something to do with my test expect executing before my _buildBackground() functions are done. I've tried altering the duration in my pump and pumpAndSettle to no effect. How do I force the test to wait more? Is there something else I'm missing?

The test log looks like this (with my prints):

Running Flutter tests.
00:00 +0: ...d/work/.../cl00:00 +0: (setUpAll)                                                                                                          00:00 +0: Test background                                              
init state called
_buildBackgroundA called
init state called
_buildBackgroundB called
...
00:00 +0 -1: Test background
    Expected: exactly one matching node in the widget tree
    Actual: ?:<zero widgets with type "AnimatedCrossFade" that has ancestor(s) with type "BackgroundImage" (ignoring offstage widgets)>
     Which: means none were found but one was expected
  This was caught by the test expectation on the following line:
 ...line 179

about to return from calling _buildBackgroundA
image: Image(image: MemoryImage(_Uint8ArrayView#af55b, scale: 1.0), width: 50.0, height: 200.0, fit: cover, alignment: center, this.excludeFromSemantics: false, filterQuality: low)
about to return from calling _buildBackgroundB
image: Image(image: MemoryImage(_Uint8ArrayView#79291, scale: 1.0), width: 50.0, height: 830.0, fit: cover, alignment: center, this.excludeFromSemantics: false, filterQuality: low)
...


Aucun commentaire:

Enregistrer un commentaire