Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

request: AnimationSheetBuilder implementation #134

Open
1 task done
lesleysin opened this issue Oct 3, 2024 · 5 comments
Open
1 task done

request: AnimationSheetBuilder implementation #134

lesleysin opened this issue Oct 3, 2024 · 5 comments

Comments

@lesleysin
Copy link

Is there an existing feature request for this?

  • I have searched the existing issues.

Command

Implementation of AnimationSheetBuilder for testing animated widgets

Description

Flutter doc: https://api.flutter.dev/flutter/flutter_test/AnimationSheetBuilder-class.html

This feature will help you get images that clearly display the process of complex animations.

Reasoning

useful in cases where you need to compare the results of widget animation with golden.

Additional context and comments

No response

@btrautmann
Copy link
Contributor

@lesleysin could you elaborate on your request more? I'm having trouble understanding what the ask here is. If you could share a use case, e.g the code of a Widget you're unable to fully test with Alchemist and how the feature you're requesting would help solve that, it would be very helpful. Thank you.

@lesleysin
Copy link
Author

lesleysin commented Oct 3, 2024

@btrautmann
Previously I used golden_toolkit to create golden tests. But due to problems with CI, I started using Alchemist.

I had this example test:

    testWidgets("DuitText props animations", (tester) async {
      final AnimationSheetBuilder animationSheet = AnimationSheetBuilder(
        frameSize: const Size(100, 100),
      );
      addTearDown(animationSheet.dispose);
      
      final driver = DuitDriver.static(
        _textWithPropAnimation,
        transportOptions: HttpTransportOptions(),
        enableDevMetrics: false,
      );
      
      final widget = Material(
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: DuitViewHost(driver: driver),
        ),
      );
      
      await tester.pumpFrames(
        animationSheet.record(widget),
        const Duration(milliseconds: 1000),
      );
      
      await expectLater(
        animationSheet.collate(10),
        matchesGoldenFile("goldens/d_text_animation.png"),
      );
    });

As a result of running this code, I received the following screenshot, which captures the widget animation process:

I'd like to see an opportunity to do something like this within Alchemist

@btrautmann
Copy link
Contributor

Gotcha -- this reminds me of #50. @Kirpal was that just lost due to time constraints (totally fine if that's the case) or was there some other blocking reason?

@lesleysin
Copy link
Author

Any news on this issue?

@Kirpal
Copy link
Collaborator

Kirpal commented Oct 14, 2024

@btrautmann I had built out an implementation of it, but never could get it to reliably pass across local and CI. I believe there were pixel-level diffs on certain frames of the animation. I do think this would be a valuable feature to include, but I'm not really sure what else to try in order to make it pass across platforms, and I don't have the time currently to dig into it again.

As far as I remember, the feat/animations branch has the latest attempts I had made, so someone could merge it with main and try it again, but I'm not too confident in the approach working.

I know this answer's not very helpful with the problem you're facing @lesleysin. The way I've gotten around this in the past is by composing the animation out of multiple components. For example, you could structure the text animation in two widgets, one of which controls the animation (TextAnimation), and one which renders the animation at a specific point (TextAnimationContent). Then, you can test the TextAnimation widget with testWidgets, by checking that it renders TextAnimationContent with the correct values. Finally, you can test TextAnimationContent with golden tests at different points in the animation. I hope that's helpful 🙂

class TextAnimation extends StatefulWidget {
  const TextAnimation({super.key});

  @override
  State<TextAnimation> createState() => _TextAnimationState();
}

class _TextAnimationState extends State<TextAnimation> {
  late AnimationController controller;

  /// Animation logic

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: controller,
      builder: (context, _) => TextAnimationContent(progress: controller.value),
    );
  }
}

class TextAnimationContent extends StatelessWidget {
  const TextAnimationContent({
    required this.progress,
    super.key,
  });

  final double progress;

  TextStyle get _style => TextStyleTween(
        begin: TextStyle(),
        end: TextStyle(),
      ).transform(progress);

  @override
  Widget build(BuildContext context) {
    return Text('Hello World', style: _style);
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants