如何在Flutter中测试AnimatedIcon

huangapple go评论67阅读模式
英文:

How to test an AnimatedIcon in Flutter

问题

  1. 有没有类似于 finder.byIcon() 的方法,但接受 AnimatedIconData 而不是 IconData
  2. 如何验证动画是否正在进行?
英文:

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.

  1. Is there a method similar to finder.byIcon(), but that accepts AnimatedIconData instead of IconData?
  2. How to verify that the animation is happening?

答案1

得分: 2

  1. 获取 AnimatedIconData 的查找器

要获取 AnimatedIconData 的查找器,请使用以下方法,使用 find.byWidgetPredicate(假设要搜索的 AnimatedIconDataAnimatedIcons.menu_arrow):

final animatedIconFinder = find.byWidgetPredicate((widget) =>
        widget is AnimatedIcon && widget.icon == AnimatedIcons.menu_arrow); 
  1. 验证动画是否正在进行

要验证动画是否正在进行,请检查 AnimatedIcon 小部件的 progress 属性的值。

假设动画发生在屏幕上的一个浮动操作按钮被点击之后,下面的代码示例显示了如何验证在按钮被点击后 AnimatedIcon 是否进行动画。

// 获取 [AnimatedIcon] 小部件
final animatedIconWidget = tester.widget(animatedIconFinder) as AnimatedIcon;

final animatedIconProgress = animatedIconWidget.progress.value;

// 验证 [AnimatedIcon] 是否不在进行动画
expect(animatedIconProgress, 0);

// 查找 [FloatingActionButton]
final floatingActionButtonFinder = 
    find.widgetWithIcon(FloatingActionButton, Icons.change_circle);

// 点击 [FloatingActionButton]
await tester.tap(floatingActionButtonFinder);

await tester.pumpAndSettle();

final updatedAnimatedIconProgress = animatedIconWidget.progress.value;

// 验证 [AnimatedIcon] 已完成其动画
expect(updatedAnimatedIconProgress, 1);

使用自定义查找器

要使您的查找器更简洁并类似于 find.byIcon,请执行以下操作:

  1. 通过扩展 MatchFinder 创建自定义查找器,并在 matches 方法中添加匹配逻辑(这是 find.byIcon 的修改实现)。

    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;
      }
    }
    
  2. 创建 CommonFinders 类的扩展,并添加一个 byAnimatedIcon 方法,该方法使用步骤1中创建的自定义查找器。CommonFinders 类由 flutter_test 包提供,find 常量(如 find.byIcon)是 CommonFinders 的实例。

    extension CustomFindersExtension on CommonFinders {
      Finder byAnimatedIcon(AnimatedIconData icon) =>
        _WidgetAnimatedIconFinder(icon);
    }
    
  3. 使用 find.byAnimatedIcon 来查找要搜索的 AnimatedIconData

    用以下代码替换使用 find.byWidgetPredicate 的查找器:

    final animatedIconFinder = find.byAnimatedIcon(AnimatedIcons.menu_arrow);
    
英文:

1. Finder for AnimatedIconData

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); 

2. Verification that the animation is happening

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);

Using a Custom Finder

To make your finder more concise and similar to find.byIcon, do the following:

  1. 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;
      }
    }
    
  2. 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);
    }
    
  3. 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);
    

huangapple
  • 本文由 发表于 2023年3月7日 08:21:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/75657000.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定