/
index.ts
125 lines (107 loc) Β· 3.5 KB
/
index.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import {type PointerCoords} from '../event'
import {type Instance} from '../setup'
import {type pointerKey, type PointerPosition} from '../system/pointer'
import {ApiLevel, setLevelRef, wait} from '../utils'
import {parseKeyDef} from './parseKeyDef'
type PointerActionInput =
| string
| ({keys: string} & PointerActionPosition)
| PointerAction
export type PointerInput = PointerActionInput | Array<PointerActionInput>
type PointerAction = PointerPressAction | PointerMoveAction
type PointerActionPosition = {
target?: Element
coords?: PointerCoords
node?: Node
/**
* If `node` is set, this is the DOM offset.
* Otherwise this is the `textContent`/`value` offset on the `target`.
*/
offset?: number
}
interface PointerPressAction extends PointerActionPosition {
keyDef: pointerKey
releasePrevious: boolean
releaseSelf: boolean
}
interface PointerMoveAction extends PointerActionPosition {
pointerName?: string
}
export async function pointer(
this: Instance,
input: PointerInput,
): Promise<void> {
const {pointerMap} = this.config
const actions: PointerAction[] = []
;(Array.isArray(input) ? input : [input]).forEach(actionInput => {
if (typeof actionInput === 'string') {
actions.push(...parseKeyDef(pointerMap, actionInput))
} else if ('keys' in actionInput) {
actions.push(
...parseKeyDef(pointerMap, actionInput.keys).map(i => ({
...actionInput,
...i,
})),
)
} else {
actions.push(actionInput)
}
})
for (let i = 0; i < actions.length; i++) {
await wait(this.config)
await pointerAction(this, actions[i])
}
this.system.pointer.resetClickCount()
}
async function pointerAction(instance: Instance, action: PointerAction) {
const pointerName =
'pointerName' in action && action.pointerName
? action.pointerName
: 'keyDef' in action
? instance.system.pointer.getPointerName(action.keyDef)
: 'mouse'
const previousPosition =
instance.system.pointer.getPreviousPosition(pointerName)
const position: PointerPosition = {
target: action.target ?? getPrevTarget(instance, previousPosition),
coords: action.coords ?? previousPosition?.coords,
caret: {
node:
action.node ??
(hasCaretPosition(action) ? undefined : previousPosition?.caret?.node),
offset:
action.offset ??
(hasCaretPosition(action)
? undefined
: previousPosition?.caret?.offset),
},
}
if ('keyDef' in action) {
if (instance.system.pointer.isKeyPressed(action.keyDef)) {
setLevelRef(instance, ApiLevel.Trigger)
await instance.system.pointer.release(instance, action.keyDef, position)
}
if (!action.releasePrevious) {
setLevelRef(instance, ApiLevel.Trigger)
await instance.system.pointer.press(instance, action.keyDef, position)
if (action.releaseSelf) {
setLevelRef(instance, ApiLevel.Trigger)
await instance.system.pointer.release(instance, action.keyDef, position)
}
}
} else {
setLevelRef(instance, ApiLevel.Trigger)
await instance.system.pointer.move(instance, pointerName, position)
}
}
function hasCaretPosition(action: PointerAction) {
return !!(action.target ?? action.node ?? action.offset !== undefined)
}
function getPrevTarget(instance: Instance, position?: PointerPosition) {
if (!position) {
throw new Error(
'This pointer has no previous position. Provide a target property!',
)
}
return position.target ?? instance.config.document.body
}