I want to do a test that allows me to verify if my widget is showing the AnimatedIcon
that I provide, as well as to know if the animation is working (changing the icon in an animated way), the problem is that I can't find the way to do it.
finder.byIcon()
, but that accepts AnimatedIconData
instead of IconData
?To get a finder for AnimatedIconData
, use the find.byWidgetPredicate method like below (assuming the AnimatedIconData
being searched for is AnimatedIcons.menu_arrow
):
final animatedIconFinder = find.byWidgetPredicate((widget) =>
widget is AnimatedIcon && widget.icon == AnimatedIcons.menu_arrow);
To verify that the animation is happening, check the value of the AnimatedIcon widget's progress property.
Assuming the animation happens after a floating action button on the screen is tapped, the code sample below shows how to verify that the AnimatedIcon
animates after the button is tapped.
// Gets the [AnimatedIcon] widget
final animatedIconWidget = tester.widget(animatedIconFinder) as AnimatedIcon;
final animatedIconProgress = animatedIconWidget.progress.value;
// Verifies that [AnimatedIcon] is not animating
expect(animatedIconProgress, 0);
// Finds [FloatingActionButton]
final floatingActionButtonFinder =
find.widgetWithIcon(FloatingActionButton, Icons.change_circle);
// Taps [FloatingActionButton]
await tester.tap(floatingActionButtonFinder);
await tester.pumpAndSettle();
final updatedAnimatedIconProgress = animatedIconWidget.progress.value;
// Verifies that the [AnimatedIcon] has completed its animation
expect(updatedAnimatedIconProgress, 1);
To make your finder more concise and similar to find.byIcon, do the following:
Create a custom Finder by extending MatchFinder and add the matching logic in the matches
method (This is a modification of the find.byIcon implementation).
class _WidgetAnimatedIconFinder extends MatchFinder {
_WidgetAnimatedIconFinder(this.icon, {super.skipOffstage});
final AnimatedIconData icon;
@override
String get description => 'icon "$icon"';
@override
bool matches(Element candidate) {
final Widget widget = candidate.widget;
return widget is AnimatedIcon && widget.icon == icon;
}
}
Create an extension on the CommonFinders class and add a byAnimatedIcon
method that uses the custom Finder created in step 1. The CommonFinders class is provided by the flutter_test package and the find constant (as in find.byIcon
) is an instance of CommonFinders
.
extension CustomFindersExtension on CommonFinders {
Finder byAnimatedIcon(AnimatedIconData icon) =>
_WidgetAnimatedIconFinder(icon);
}
Use find.byAnimatedIcon
to find the AnimatedIcon by supplying the AnimatedIconData
being searched for.
Replace the Finder
using find.byWidgetPredicate
with this below:
final animatedIconFinder = find.byAnimatedIcon(AnimatedIcons.menu_arrow);