Skip to content

Commit

Permalink
fix(stubs): teleport stub children as a function
Browse files Browse the repository at this point in the history
Fixes #1829
  • Loading branch information
cexbrayat committed Oct 27, 2022
1 parent 9673f47 commit 250610c
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 8 deletions.
23 changes: 17 additions & 6 deletions src/vnodeTransformers/util.ts
@@ -1,6 +1,6 @@
import { isComponent } from '../utils'
import { registerStub } from '../stubs'
import { ConcreteComponent, transformVNodeArgs } from 'vue'
import { ConcreteComponent, Teleport, transformVNodeArgs } from 'vue'

type VNodeArgsTransformerFn = NonNullable<
Parameters<typeof transformVNodeArgs>[0]
Expand All @@ -20,6 +20,8 @@ export type VTUVNodeTypeTransformer = (
instance: InstanceArgsType
) => VNodeTransformerInputComponentType

const isTeleport = (type: any): boolean => type.__isTeleport

export const createVNodeTransformer = ({
transformers
}: {
Expand All @@ -31,15 +33,20 @@ export const createVNodeTransformer = ({
> = new WeakMap()

return (args: VNodeTransformerArgsType, instance: InstanceArgsType) => {
const [originalType, ...restVNodeArgs] = args
const [originalType, props, children, ...restVNodeArgs] = args

if (!isComponent(originalType)) {
return [originalType, ...restVNodeArgs]
return [originalType, props, children, ...restVNodeArgs]
}

const cachedTransformation = transformationCache.get(originalType)
if (cachedTransformation) {
return [cachedTransformation, ...restVNodeArgs]
// https://github.com/vuejs/test-utils/issues/1829
// Teleport should return child nodes as a function
if (isTeleport(originalType)) {
return [cachedTransformation, props, () => children, ...restVNodeArgs]
}
return [cachedTransformation, props, children, ...restVNodeArgs]
}

const componentType: VNodeTransformerInputComponentType = originalType
Expand All @@ -53,8 +60,12 @@ export const createVNodeTransformer = ({
transformationCache.set(originalType, transformedType)

registerStub({ source: originalType, stub: transformedType })
// https://github.com/vuejs/test-utils/issues/1829
// Teleport should return child nodes as a function
if (isTeleport(originalType)) {
return [transformedType, props, () => children, ...restVNodeArgs]
}
}

return [transformedType, ...restVNodeArgs]
return [transformedType, props, children, ...restVNodeArgs]
}
}
7 changes: 6 additions & 1 deletion tests/element.spec.ts
@@ -1,4 +1,4 @@
import { describe, expect, it } from 'vitest'
import { describe, expect, it, vi } from 'vitest'
import { defineComponent, h } from 'vue'

import { mount } from '../src'
Expand Down Expand Up @@ -107,12 +107,17 @@ describe('element', () => {
})

it('returns correct element for component which renders other component with array of vnodes in default slot', () => {
const spy = vi.spyOn(console, 'warn').mockImplementation(() => {})
const Nested = {
template: '<div class="nested-root"><slot></slot></div>'
}
const Root = () => h(Nested, {}, [h('div', {}, 'foo'), h('div', {}, 'bar')])

const wrapper = mount(Root)
expect(wrapper.element.innerHTML).toBe('<div>foo</div><div>bar</div>')
// we're expecting a warning from Vue as we're using non-function slots
expect(spy.mock.calls[0][0]).toContain(
'Non-function value encountered for default slot'
)
})
})
7 changes: 6 additions & 1 deletion tests/findAllComponents.spec.ts
@@ -1,4 +1,4 @@
import { describe, expect, it } from 'vitest'
import { describe, expect, it, vi } from 'vitest'
import { mount } from '../src'
import Hello from './components/Hello.vue'
import { DefineComponent, defineComponent, h } from 'vue'
Expand Down Expand Up @@ -100,6 +100,7 @@ describe('findAllComponents', () => {
})

it('findAllComponents with non-function slots', () => {
const spy = vi.spyOn(console, 'warn').mockImplementation(() => {})
const ComponentA = defineComponent({
template: '<div><slot /></div>'
})
Expand All @@ -119,5 +120,9 @@ describe('findAllComponents', () => {
})
expect(wrapper.findAll('span')).toHaveLength(3)
expect(wrapper.findAllComponents(ComponentB)).toHaveLength(3)
// we're expecting a warning from Vue as we're using non-function slots
expect(spy.mock.calls[0][0]).toContain(
'Non-function value encountered for default slot'
)
})
})
4 changes: 4 additions & 0 deletions tests/mountingOptions/global.stubs.spec.ts
Expand Up @@ -512,6 +512,7 @@ describe('mounting options: stubs', () => {
})

it('opts in to stubbing teleport ', () => {
const spy = vi.spyOn(console, 'warn')
const Comp = {
template: `<teleport to="body"><div id="content" /></teleport>`
}
Expand All @@ -528,6 +529,9 @@ describe('mounting options: stubs', () => {
' <div id="content"></div>\n' +
'</teleport-stub>'
)
// Make sure that we don't have a warning when stubbing teleport
// https://github.com/vuejs/test-utils/issues/1829
expect(spy).not.toHaveBeenCalled()
})

it('does not stub teleport with shallow', () => {
Expand Down

0 comments on commit 250610c

Please sign in to comment.