Testing ember-animated apps

Hi,

We recently had intermittent test failures in a fairly big Ember app that uses ember-animated transitions in a few places.

(I’m going to go into details below but I’m also interested to hear how you test parts of your app where you have ember-animated transitions, so feel free to chime in even if you don’t have answers for my specific questions below.)

Digging down into the problem I came across an ember-animated test helper called animationsSettled. It seems to be the ember-animated aware equivalent of the settled helper for built-in test helpers. It waits for all ember-animated transitions to finish before moving on to the next line in the test.

The test failures were only produced if tests (integration and acceptance) were run in a certain order. The fix was to add await animationsSettled() everywhere where an action (like click) triggered an animation. So we managed to overcome the problem but it left me with a few questions that I’d like to understand better.

  1. Is it possible for animations to “linger” between tests? In our case, each of the tests passed when run in isolation. However, if we missed to insert an animationsSettled in one test, it seemed to have broken a next one run after it (and possibly, though I’m not 100% sure about this, breaking it by hanging the next animationsSettled).
  2. It seems a bit too much to ask of the developer to know exactly which actions can trigger animations. In our case, even a visit could trigger it because a component also animated when it was first inserted. This makes someone relatively new to that part of the code having to spend quite some time figuring this out. Maybe that’s just how things are, but I wonder if there’s an easier way around this. (see next point)
  3. To address the previous point, would it make sense for all the built-in test helpers (click, visit, triggerEvent, etc.) to detect if a project uses ember-animated and then have settled also wait for animations (= call animationsSettled) behind the scenes? It’d add some overhead but the previous point would be vastly improved.
  4. ember-animated alls add a hook, setupAnimationTest which adds a bunch of useful assertions. Should this function still be called if a test doesn’t need those assertions? The only other thing it seems to do is speed up animations by calling time.runAtSpeed(40) but I wasn’t quite able to figure out if that’s needed (and if that’s what it really does :slight_smile: ).

Thanks a bunch for answering these.

Balint

1 Like

I had no idea these helpers existed. Really need this documented in the official docs.

It shouldn’t be, if you can reproduce please file a bug. A component that gets destroyed while it’s animating should clean everything up safely.

Agreed, for the case where you’re not specifically trying to test the animations, it should be enough to tell ember-animated to just run the animations super fast. setupAnimationTest does that, if you don’t use any of its other features. But I can see how its name is confusing, since it can support both tests where you want to effectively skip the animations and also tests where you want to use assertions to control the animations.

This is how it used to work, and it’s how liquid-fire still works. It’s convenient when you don’t want to test animations, but when you do want to test them it makes things much harder. For example, if you want to assert about what’s in DOM half way through a transition, you need to await click() to ensure that the animation has truly started, then await time.advance(duration / 2), then assert. If settled waits for animations to finish, await click() will wait for the transition to end, when you really want to wait for it to start.

But I think your questions have given me an idea for clarifying these APIs. We should really offer two different test setup functions. One that works like the current setupAnimationTest for when you actually want to assert about the animations, and a separate one for when you just want animations to not get in the way at all.

3 Likes
1 Like

That makes a lot of sense, I commented on the Github issue you created. Thanks!