1
1
import { isComponent } from '../utils'
2
2
import { registerStub } from '../stubs'
3
- import { ConcreteComponent , transformVNodeArgs } from 'vue'
3
+ import { Component , ConcreteComponent , transformVNodeArgs } from 'vue'
4
4
5
5
type VNodeArgsTransformerFn = NonNullable <
6
6
Parameters < typeof transformVNodeArgs > [ 0 ]
@@ -23,9 +23,30 @@ export type VTUVNodeTypeTransformer = (
23
23
export const isTeleport = ( type : any ) : boolean => type . __isTeleport
24
24
export const isKeepAlive = ( type : any ) : boolean => type . __isKeepAlive
25
25
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
+
26
45
export const createVNodeTransformer = ( {
46
+ rootComponents,
27
47
transformers
28
48
} : {
49
+ rootComponents : RootComponents
29
50
transformers : VTUVNodeTypeTransformer [ ]
30
51
} ) : VNodeArgsTransformerFn => {
31
52
const transformationCache : WeakMap <
@@ -40,8 +61,14 @@ export const createVNodeTransformer = ({
40
61
return [ originalType , props , children , ...restVNodeArgs ]
41
62
}
42
63
64
+ const componentType : VNodeTransformerInputComponentType = originalType
65
+
43
66
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
+ ) {
45
72
// https://github.com/vuejs/test-utils/issues/1829 & https://github.com/vuejs/test-utils/issues/1888
46
73
// Teleport/KeepAlive should return child nodes as a function
47
74
if ( isTeleport ( originalType ) || isKeepAlive ( originalType ) ) {
@@ -50,8 +77,6 @@ export const createVNodeTransformer = ({
50
77
return [ cachedTransformation , props , children , ...restVNodeArgs ]
51
78
}
52
79
53
- const componentType : VNodeTransformerInputComponentType = originalType
54
-
55
80
const transformedType = transformers . reduce (
56
81
( type , transformer ) => transformer ( type , instance ) ,
57
82
componentType
0 commit comments