Skip to content

Commit 8ae1ddd

Browse files
committed
fix(stub): re-render of recursive component using wrong cached stub
1 parent b8db811 commit 8ae1ddd

File tree

3 files changed

+38
-13
lines changed

3 files changed

+38
-13
lines changed

src/createInstance.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ export function createInstance(
307307
// stub out Transition and Transition Group by default.
308308
transformVNodeArgs(
309309
createVNodeTransformer({
310+
rootComponents,
310311
transformers: [
311312
createStubComponentsTransformer({
312313
rootComponents,

src/vnodeTransformers/stubComponentsTransformer.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { isKeepAlive, isTeleport, VTUVNodeTypeTransformer } from './util'
1+
import {
2+
isKeepAlive,
3+
isRootComponent,
4+
isTeleport,
5+
VTUVNodeTypeTransformer
6+
} from './util'
27
import {
38
Transition,
49
TransitionGroup,
@@ -177,14 +182,8 @@ export function createStubComponentsTransformer({
177182
})
178183
}
179184

180-
if (
181-
// Don't stub VTU_ROOT component
182-
!instance ||
183-
// Don't stub mounted component on root level
184-
(rootComponents.component === type && !instance?.parent) ||
185-
// Don't stub component with compat wrapper
186-
(rootComponents.functional && rootComponents.functional === type)
187-
) {
185+
// Don't stub root components
186+
if (isRootComponent(rootComponents, type, instance)) {
188187
return type
189188
}
190189

src/vnodeTransformers/util.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { isComponent } from '../utils'
22
import { registerStub } from '../stubs'
3-
import { ConcreteComponent, transformVNodeArgs } from 'vue'
3+
import { Component, ConcreteComponent, transformVNodeArgs } from 'vue'
44

55
type VNodeArgsTransformerFn = NonNullable<
66
Parameters<typeof transformVNodeArgs>[0]
@@ -23,9 +23,30 @@ export type VTUVNodeTypeTransformer = (
2323
export const isTeleport = (type: any): boolean => type.__isTeleport
2424
export const isKeepAlive = (type: any): boolean => type.__isKeepAlive
2525

26+
export interface RootComponents {
27+
// Component which has been passed to mount. For functional components it contains a wrapper
28+
component?: Component
29+
// If component is functional then contains the original component otherwise empty
30+
functional?: Component
31+
}
32+
export const isRootComponent = (
33+
rootComponents: RootComponents,
34+
type: VNodeTransformerInputComponentType,
35+
instance: InstanceArgsType
36+
): boolean =>
37+
!!(
38+
!instance ||
39+
// Don't stub mounted component on root level
40+
(rootComponents.component === type && !instance?.parent) ||
41+
// Don't stub component with compat wrapper
42+
(rootComponents.functional && rootComponents.functional === type)
43+
)
44+
2645
export const createVNodeTransformer = ({
46+
rootComponents,
2747
transformers
2848
}: {
49+
rootComponents: RootComponents
2950
transformers: VTUVNodeTypeTransformer[]
3051
}): VNodeArgsTransformerFn => {
3152
const transformationCache: WeakMap<
@@ -40,8 +61,14 @@ export const createVNodeTransformer = ({
4061
return [originalType, props, children, ...restVNodeArgs]
4162
}
4263

64+
const componentType: VNodeTransformerInputComponentType = originalType
65+
4366
const cachedTransformation = transformationCache.get(originalType)
44-
if (cachedTransformation) {
67+
if (
68+
cachedTransformation &&
69+
// Don't use cache for root component, as it could use stubbed recursive component
70+
!isRootComponent(rootComponents, componentType, instance)
71+
) {
4572
// https://github.com/vuejs/test-utils/issues/1829 & https://github.com/vuejs/test-utils/issues/1888
4673
// Teleport/KeepAlive should return child nodes as a function
4774
if (isTeleport(originalType) || isKeepAlive(originalType)) {
@@ -50,8 +77,6 @@ export const createVNodeTransformer = ({
5077
return [cachedTransformation, props, children, ...restVNodeArgs]
5178
}
5279

53-
const componentType: VNodeTransformerInputComponentType = originalType
54-
5580
const transformedType = transformers.reduce(
5681
(type, transformer) => transformer(type, instance),
5782
componentType

0 commit comments

Comments
 (0)