Reputation: 427
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?
Upvotes: 7
Views: 4758
Reputation: 1
There is official documentaiton how to handle teleport. It basically adds a beforeEach and afterEach for target element of your teleport.
https://test-utils.vuejs.org/guide/advanced/teleport
beforeEach(() => {
// create teleport target
const el = document.createElement('div')
el.id = 'target-id'
document.body.appendChild(el)
})
afterEach(() => {
// clean up
document.body.innerHTML = ''
})
Upvotes: 0
Reputation: 339
Another approach is, you can get element of your destination of teleport in your test.
From your case, you can just get element with id 'app', and get the innerHtml
e.g:
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(document.getElementById('app')?.innerHTML).toContain(title)
expect(document.getElementById('app')?.innerHTML).toContain(description)
})
Upvotes: 2
Reputation: 945
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.
Upvotes: 4