ReMo
ReMo

Reputation: 113

Vitest: Wrapper doesn't show "teleported" HTML

imagine we have two components, Modal.vue which is lets say a component that is used to display modal content (uses slots to take in JSX), and Component.vue which is the one with content we wish to test with vitest/jest:

//Modal.vue
<template>
    <div>
        <slot name="header" />
        <slot />
        <slot name="footer" />
    </div>
</template>

//component.vue
<template>
    <Modal>
        <template #header>
            <h1>Hello world</h1>
        </template>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
            Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
            Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 
            Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
        </p>
        <template #footer>
            <button>Great</button>
        </template>
    </Modal>
</template>

The problem is that I cannot reach the wrapper HTML within my test, as it will console log something similar to this:

// snipet from the test file
...    
it('should mount Component.vue', () => {
    console.log(wrapper.html())
    expect(wrapper).toBeTruthy()
})
...

The console.log in the test will result to this:

<div>
  <!---->
  <!--teleport start-->
  <!--teleport end-->
  <!---->
</div>

Question is: How can I access the wrapper HTML that is define in 'Component.vue'??

Upvotes: 4

Views: 1963

Answers (1)

zunnzunn
zunnzunn

Reputation: 392

It appears you are trying to reach a teleported Vue component in your test.

For this reason, in the actual resulting DOM, the HTML content of the component will be outside of it (which is why your wrapper.html() returns practically nothing, besides that comment), but not so in Vue's virtual DOM. Therefore, you must query the virtual DOM somehow. You can do so using the wrapper method getComponent.

Note, however, that getComponent can only find Vue components, and not regular HTML elements. You will have to wrap the content of your <Modal> with a custom Vue component, e.g. <ModalContent>. Then you can do something like this:

  const wrapper = mount(Component)
  const modal = wrapper.findComponent(Modal)
  const modalContent = modal.getComponent(ModalContent)

Upvotes: 1

Related Questions