/
util.ts
64 lines (52 loc) · 2.14 KB
/
util.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import { isComponent } from '../utils'
import { registerStub } from '../stubs'
import { ConcreteComponent, transformVNodeArgs } from 'vue'
type VNodeArgsTransformerFn = NonNullable<
Parameters<typeof transformVNodeArgs>[0]
>
type TransformVNodeArgs = Parameters<VNodeArgsTransformerFn>
type VNodeTransformerArgsType = TransformVNodeArgs[0]
type InstanceArgsType = TransformVNodeArgs[1]
type VNodeTransformerInputType = VNodeTransformerArgsType[0]
type ExtractComponentTypes<T> = T extends ConcreteComponent ? T : never
type VNodeTransformerInputComponentType =
ExtractComponentTypes<VNodeTransformerInputType>
export type VTUVNodeTypeTransformer = (
inputType: VNodeTransformerInputComponentType,
instance: InstanceArgsType
) => VNodeTransformerInputComponentType
export const createVNodeTransformer = ({
transformers
}: {
transformers: VTUVNodeTypeTransformer[]
}): VNodeArgsTransformerFn => {
const transformationCache: WeakMap<
VNodeTransformerInputComponentType,
VNodeTransformerInputComponentType
> = new WeakMap()
return (args: VNodeTransformerArgsType, instance: InstanceArgsType) => {
const [originalType, props, children, ...restVNodeArgs] = args
if (!isComponent(originalType)) {
return [originalType, props, children, ...restVNodeArgs]
}
const cachedTransformation = transformationCache.get(originalType)
if (cachedTransformation) {
return [cachedTransformation, props, children, ...restVNodeArgs]
}
const componentType: VNodeTransformerInputComponentType = originalType
const transformedType = transformers.reduce(
(type, transformer) => transformer(type, instance),
componentType
)
if (originalType !== transformedType) {
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 (transformedType.name === 'teleport') {
return [transformedType, props, () => children, ...restVNodeArgs]
}
}
return [transformedType, props, children, ...restVNodeArgs]
}
}