Vue-test-utils: `Vue.nextTick()` required with transitions.

Created on 29 Sep 2017  Â·  34Comments  Â·  Source: vuejs/vue-test-utils

Version

1.0.0-beta

Reproduction link

https://github.com/autumnwoodberry/vtu

Steps to reproduce

Nest some v-if:

<transition>
  <div v-if="a">
    <transition v-if="b"></transition>
    <transition v-if="!b"></transition>
  </div>
</transition>
test('output', () => {
    wrapper.setData({
      a: true,
      b: true
    });

    expect(wrapper.vm.a).toBe(true)
    expect(wrapper.vm.b).toBe(true)
    expect(wrapper.html()).toMatchSnapshot()
})



md5-a480ebe6655ddb631c33b438b32227db



test('output', () => {
    wrapper.setData({
      a: true,
      b: true
    });

    expect(wrapper.vm.a).toBe(true)
    expect(wrapper.vm.b).toBe(true)
    Vue.nextTick(() => {
      expect(wrapper.html()).toMatchSnapshot()
    })
})
bug

Most helpful comment

I have the same bug right now. The transition tag doesn't allow me to test when elements are visible or not because it doesn't wait until the end of the animation I supposed.

All 34 comments

Thanks for the detailed bug report 😄

This is an issue with transitions, I'll look into it over the next few days

I think the solution to this is to stub the transition and transition-group components.

We have 3 options:

  1. leave it to the user to stub using the stubs mount option
  2. Provide a transition and transition-group stub components, for the user to pass in the stubs option
  3. Stub transition and transition group by default inside mount

I'm leaning towards option 2.

I'd be happy with option 3. I don't use transition very often, so I'm not sure if there's be a use case for people testing unstubbed transitions? I'd be interested to hear others thoughts.

I like the "opt-in" option best as well and I think it keeps unexpected internal behavior to a minimum.

It might be nice to have a config somewhere so you can turn it on globally. I use transitions enough that it would be nice to that that option.

That's a good idea @autumnwoodberry . We could make a global config, like Vue has.

I'm going to be pretty busy the next few days, so I will just leave a couple more thoughts I had:

  • I'm actualy not sure what wrapper.setData({ a: true }) does vs wrapper.vm.a = true
  • If we made setData() async, or provided an async version or async option for it, it might be a more intuitive solution.
await wrapper.setData({ a: true })

expect(wrapper.vm.a).toBe(true);
expect(wrapper.html()).toMatchSnapshot();
  • Whatever gets decided, I think this should all get mentioned in the setData() docs section.

I'm actualy not sure what wrapper.setData({ a: true }) does vs wrapper.vm.a = true

setData sets the data and calls update.

If we made setData() async, or provided an async version or async option for it, it might be a more intuitive solution.

I don't think we should make setData async. Synchronous updating makes unit tests simpler to write and easier to read. I agree, it can be confusing for experienced Vue users who expect async updating, but I think that for the majority of users they would expect setData to update the Vue instance, which it does for everything except transitions. Which is why I'm tempted to stub transitions by default, and make it an opt-out feature.

Whatever gets decided, I think this should all get mentioned in the setData() docs section.

This isn't really a setData issue, it's to do with update. I agree though that this can be confusing.
I think we should link to update in all methods that call update, and add a gotchas section.

Ok yes, I see - that makes perfect sense.

I just released TransitionStub and TransitionGroupStub in 1.0.0-beta.2:

import { TransitionGroupStub, TransitionStub, shallow } from 'vue-tes-utils'

const wrapper = shallow(Component, {
  stubs: {
    'transition': TransitionStub,
    'transition-group': TransitionGroupStub
  }
})

Awesome! I will check it out when I have some spare moments.

@eddyerburgh I'm using TransitionStub and attempting to assert that elements enter & leave the dom after data change (two elements with a simple v-if/v-else inside a <transition> tag). It seems to work on enter, but not on leaving - the content inside the <transition> tag remains in the wrapper's html and receives the v-leave and v-leave-active classes. I expected the transition stub to just cause inner content to instantly enter/leave, is that understanding off the mark?

Hi @petridw, leave hasn't been implemented. I'll look into it.

Do you have an example I could add as a test?

@eddyerburgh here's a failing test that should be passing, I think:

component-with-transition.vue

<template>
  <div>
    <transition>
      <div v-if="bool" key="a">{{ trueText }}</div>
      <div v-else key="b">{{ falseText }}</div>
    </transition>
  </div>
</template>

<script>
export default {
  name: "component-with-transition",
  data() {
    return {
      bool: true,
      trueText: "a",
      falseText: "b",
    };
  },
};
</script>

transition.spec.js

import { shallow, TransitionStub } from "vue-test-utils";
import ComponentWithTransition from "@/components/component-with-transition";

const options = {
  stubs: {
    transition: TransitionStub,
  },
};

describe("component-with-transition", () => {
  it("swaps dom nodes properly", () => {
    const wrapper = shallow(ComponentWithTransition, options);
    expect(wrapper.text()).toBe(wrapper.vm.trueText);
    wrapper.setData({ bool: false });
    expect(wrapper.text()).toBe(wrapper.vm.falseText);
  });
});

Thanks @petridw, if you remove the keys, the test passes.

The TransitionStub basically behaves the same as an unstubbed transition, except it doesn't add leave classes when the component inside is hidden, and it always returns the child synchronously.

Interesting, so is there a different way I should be testing components that use transitions with keys?

No, I'll look into it. But I'm on vacation at the moment. Just pointing out
how to make the test pass

On 19 Oct 2017 22:06, "David Petri" notifications@github.com wrote:

Interesting, so is there a different way I should be testing components
that use transitions with keys?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/vuejs/vue-test-utils/issues/52#issuecomment-338038173,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AMlbW2onB52EDwzyUu3-HpW2LJxYOXC_ks5st7nngaJpZM4PoGlA
.

@eddyerburgh cool - have a great vacation & thanks for all your work!

Maybe this is no more and issue? For me it works using shallow instead o mount no need to user any extra stubs like TransitionGroupStub or TransitionStub

Thanks for the heads up, I'll look into it

The fix for the keyed bug will be released in beta.9 🎉

Transition group stub over writes slots inside,

Thanks for the hug report. Can you make a new issue for this please

On 3 Jan 2018 18:42, "jorySsense" notifications@github.com wrote:

Transition group stub over writes slots inside,

—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
https://github.com/vuejs/vue-test-utils/issues/52#issuecomment-355091872,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AMlbW2EaIcpxK-kSbgmJmBH_uxZYntWGks5tG8oUgaJpZM4PoGlA
.

I can't test component with transition.

In component:

...
<transition
  :name="optionsClass"
  @before-enter="animationFinished = false"
  @after-enter="animationFinished = true"
>
  <div v-show="opened">
...

In tests:

console.log(wrapper.html())
wrapper.find('.u-select__select').trigger('click');  // sets data to display element (v-show)
console.log(wrapper.html());

The second html in console equals the first (with style="display: none").

If I remove <transition> from component it works as expected.

@denisinvader please open a new issue with a reproduction

@eddyerburgh I've spot the bug #567

I have the same bug right now. The transition tag doesn't allow me to test when elements are visible or not because it doesn't wait until the end of the animation I supposed.

@JessicaSachs Does this bug have been fixed in beta.30?

I’m deferring to @lmiller1990 who would’ve made any code changes

I don't think this has been fixed. This issue tracks it: https://github.com/vuejs/vue-test-utils/issues/1384

This is the next issue I'm going to focus on. There is a work-around in that thread that might help you.

The solution will be likely to stub all transitions by default.

@lmiller1990 @JessicaSachs Thanks for your reply. I change my code follow Guides - Common Tips, but it doesn't work. So I do it as other way and worked.

window.getComputedStyle = () => {
    return {
      transitionDelay: '',
      animationDelay: '',
      transitionDuration: '',
      animationDuration: '',
    };
  };

By the way, could you update chinese document I update version to 30 but I don't konw how to config it follow chinese document. So I asked question as you see.

What do you want changed in the Chinese document? It's easy enough to update code snippets, but like the actual explanation will need updating, too. If you see some improvements you are more than welcome to make them.

I just can't find Mocking Transitions in Chinese document. and others, like 'Lifecycle Hooks', 'Writing asynchronous tests using nextTick (new)' and so on. I'm not sure it's a right document I read.
Thanks for your time.

Those are recent additions. No-one has updated the Chinese docs, since none of the maintainers of VTU know Chinese, I guess.

Keeping translations up to date is very challenging - would like to know if any tools solve this problem.

TransitionStub

for me this causes to fail every test

Was this page helpful?
0 / 5 - 0 ratings