How to make Vue3 test utils work with teleport

Viewed 791

I have a component that uses teleport to , the test html doesn't seem to be working as expected. I can't find any documentation on this particular use. Here's my test:

describe('MetaHead', () => {
  it('dynamic metadata tags contain custom text', () => {

    let title = 'My Page';
    let description = 'Some description about my page';
    // This component uses Vue3's teleport to tag <head>
    // we must modify wrapper to contain such tag
    document.body.innerHTML = `
      <head>
        <div id="app"></div>
      </head>
    `

    const wrapper = mount(MetaHead, {
      attachTo: document.getElementById('app'),
      props: { 
        title,
        description
      },
      global:{
        mocks: {
          $route:{fullPath: 'full/path'}
        } 
      }
    })
    expect(wrapper.html()).toContain(title)
    expect(wrapper.html()).toContain(description)
  })
})

and the minimal component looks like this:

<template>
  <teleport to="head">
    <title>{{title}}</title>
    <meta property="og:site_name" :content="title">
    <meta name="description" :content="description">
  </teleport>
</template>

Am I missing something?

1 Answers

the problem here is wrapper.html() only returns HTML in your component - since you are teleporting outside your component, that markup won't show up when you call wrapper.html().

You have a few options. One would be making an assertion against document.body.outerHTML. Another would be using a neat trick with findComponent, I wrote about it here and posted a video about it here.

Another thing you could try that I just thought of (but have not tested) would be:

mount({
  template: `
    <div id="app" />
    <MetaHead />
  `,
  components: { MetaHead }
})

I don't know if that will work, but worth a try.

Related