vuejs / test-utils

Vue Test Utils for Vue 3
https://test-utils.vuejs.org
MIT License
1.04k stars 244 forks source link

Bug: unable to test element inside transition with v-if #2192

Closed daniilgri closed 1 year ago

daniilgri commented 1 year ago

I have a Vue3 component whose template looks something like this (simplified example):

<button @click="toggleMenu">Toggle menu outside</button>
<transition name="fade">
  <div v-if="isMenuOpened>
    <button @click="toggleMenu">Toggle menu</button>
  </div>
</transition>

toggleMenu closes/opens the "menu" div

I want to test the behavior of showing/hiding the menu. When I click on the button "Toggle menu outside" the menu is rendered but when I'm trying to close the menu by clicking on the "Toggle menu" button it does not hide the menu.

Tried console.log(wrapper.html) after closing the menu but getting the same menu rendered and at the end of the menu I see an html comment related to hidden content with v-if.

I'm migrating my tests from Vue2 and on v2 it works correctly but in Vue3 it does not work.

cexbrayat commented 1 year ago

@daniilgri Can you provide us a small repro online using https://stackblitz.com/github/vuejs/create-vue-templates/tree/main/typescript-vitest?file=src%2Fcomponents%2F__tests__%2FHelloWorld.spec.ts ?

It only takes a few minutes, and we'll be able to take a look

daniilgri commented 1 year ago

@cexbrayat Let's say we have the same simple script that I already pasted in the issue description and I ran it through the stackblitz https://stackblitz.com/edit/github-vnbwmd?file=src%2Fcomponents%2F__tests__%2FHelloWorld.spec.ts

When I click on the button it should render content inside but it is not rendering it. I tried stubbing like this: transition: false and also tried using transition: {template: '<div><slot /></div}` but both are not working.

cexbrayat commented 1 year ago

Thanks for the repro. It looks like you're not awaiting for wrapper.trigger().

If I changed your test to:

describe('HelloWorld', () => {
  it('renders properly', async () => {
    const wrapper = shallowMount(HelloWorld, {
      global: { stubs: { transition: false } },
    });
    await findElementByText(wrapper, 'button', 'Toggle menu outside').trigger(
      'click'
    );
    console.log(wrapper.html());
  });
});

then it shows the text. See https://test-utils.vuejs.org/guide/advanced/async-suspense.html#A-Simple-Example-Updating-with-trigger on why you need to await a trigger