From 250610c4b438179b6911472b2e8a0857ff011c8a Mon Sep 17 00:00:00 2001 From: ced Date: Wed, 26 Oct 2022 17:08:17 +0200 Subject: [PATCH] fix(stubs): teleport stub children as a function Fixes #1829 --- src/vnodeTransformers/util.ts | 23 ++++++++++++++++------ tests/element.spec.ts | 7 ++++++- tests/findAllComponents.spec.ts | 7 ++++++- tests/mountingOptions/global.stubs.spec.ts | 4 ++++ 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/vnodeTransformers/util.ts b/src/vnodeTransformers/util.ts index 3a3987b5a8..b30f7c2df7 100644 --- a/src/vnodeTransformers/util.ts +++ b/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[0] @@ -20,6 +20,8 @@ export type VTUVNodeTypeTransformer = ( instance: InstanceArgsType ) => VNodeTransformerInputComponentType +const isTeleport = (type: any): boolean => type.__isTeleport + export const createVNodeTransformer = ({ transformers }: { @@ -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 @@ -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] } } diff --git a/tests/element.spec.ts b/tests/element.spec.ts index d164caac06..9d4d39d6dd 100644 --- a/tests/element.spec.ts +++ b/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' @@ -107,6 +107,7 @@ 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: '
' } @@ -114,5 +115,9 @@ describe('element', () => { const wrapper = mount(Root) expect(wrapper.element.innerHTML).toBe('
foo
bar
') + // 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' + ) }) }) diff --git a/tests/findAllComponents.spec.ts b/tests/findAllComponents.spec.ts index 7785d7d7d2..155a8f696c 100644 --- a/tests/findAllComponents.spec.ts +++ b/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' @@ -100,6 +100,7 @@ describe('findAllComponents', () => { }) it('findAllComponents with non-function slots', () => { + const spy = vi.spyOn(console, 'warn').mockImplementation(() => {}) const ComponentA = defineComponent({ template: '
' }) @@ -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' + ) }) }) diff --git a/tests/mountingOptions/global.stubs.spec.ts b/tests/mountingOptions/global.stubs.spec.ts index 09d9327c0b..c410bb402a 100644 --- a/tests/mountingOptions/global.stubs.spec.ts +++ b/tests/mountingOptions/global.stubs.spec.ts @@ -512,6 +512,7 @@ describe('mounting options: stubs', () => { }) it('opts in to stubbing teleport ', () => { + const spy = vi.spyOn(console, 'warn') const Comp = { template: `
` } @@ -528,6 +529,9 @@ describe('mounting options: stubs', () => { '
\n' + '' ) + // 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', () => {