-
Notifications
You must be signed in to change notification settings - Fork 266
/
Copy pathvue-wrapper.ts
108 lines (87 loc) · 2.87 KB
/
vue-wrapper.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { ComponentPublicInstance, nextTick } from 'vue'
import { ShapeFlags } from '@vue/shared'
import { config } from './config'
import { DOMWrapper } from './dom-wrapper'
import { WrapperAPI } from './types'
import { ErrorWrapper } from './error-wrapper'
import { MOUNT_ELEMENT_ID } from './constants'
export class VueWrapper implements WrapperAPI {
private componentVM: ComponentPublicInstance
private __emitted: Record<string, unknown[]> = {}
private __vm: ComponentPublicInstance
private __setProps: (props: Record<string, any>) => void
constructor(
vm: ComponentPublicInstance,
events: Record<string, unknown[]>,
setProps: (props: Record<string, any>) => void
) {
this.__vm = vm
this.__setProps = setProps
this.componentVM = this.vm.$refs['VTU_COMPONENT'] as ComponentPublicInstance
this.__emitted = events
// plugins hook
config.plugins.VueWrapper.extend(this)
}
private get appRootNode() {
return document.getElementById(MOUNT_ELEMENT_ID) as HTMLDivElement
}
private get hasMultipleRoots(): boolean {
// if the subtree is an array of children, we have multiple root nodes
return this.componentVM.$.subTree.shapeFlag === ShapeFlags.ARRAY_CHILDREN
}
private get parentElement(): Element {
return this.componentVM.$el.parentElement
}
get element(): Element {
// if the component has multiple root elements, we use the parent's element
return this.hasMultipleRoots ? this.parentElement : this.componentVM.$el
}
get vm(): ComponentPublicInstance {
return this.__vm
}
classes(className?: string) {
return new DOMWrapper(this.element).classes(className)
}
attributes(key?: string) {
return new DOMWrapper(this.element).attributes(key)
}
exists() {
return true
}
emitted() {
return this.__emitted
}
html() {
return this.appRootNode.innerHTML
}
text() {
return this.element.textContent?.trim()
}
find<T extends Element>(selector: string): DOMWrapper<T> | ErrorWrapper {
// force using the parentElement to allow finding the root element
const result = this.parentElement.querySelector(selector) as T
if (result) {
return new DOMWrapper(result)
}
return new ErrorWrapper({ selector })
}
findAll<T extends Element>(selector: string): DOMWrapper<T>[] {
const results = this.appRootNode.querySelectorAll<T>(selector)
return Array.from(results).map((x) => new DOMWrapper(x))
}
setProps(props: Record<string, any>) {
this.__setProps(props)
return nextTick()
}
trigger(eventString: string) {
const rootElementWrapper = new DOMWrapper(this.element)
return rootElementWrapper.trigger(eventString)
}
}
export function createWrapper(
vm: ComponentPublicInstance,
events: Record<string, unknown[]>,
setProps: (props: Record<string, any>) => void
): VueWrapper {
return new VueWrapper(vm, events, setProps)
}