1
- /* eslint-disable babel/ no-invalid-this, no-eval */
1
+ /* eslint-disable no-eval, @babel/new-cap */
2
2
3
3
import path from 'path'
4
4
import fs from 'fs'
5
- import { queries as baseQueries } from '@testing-library/dom'
5
+ import {
6
+ Matcher ,
7
+ MatcherOptions ,
8
+ queries as baseQueries ,
9
+ waitForOptions as WaitForOptions ,
10
+ } from '@testing-library/dom'
6
11
import 'simmerjs'
7
12
13
+ import { BrowserBase , ElementBase } from './wdio-types'
8
14
import {
9
- BrowserBase ,
15
+ QueryArg ,
10
16
Config ,
11
- ElementBase ,
12
17
QueryName ,
13
18
WebdriverIOQueries ,
19
+ ObjectQueryArg ,
20
+ SerializedObject ,
21
+ SerializedArg ,
14
22
} from './types'
15
23
16
24
declare global {
@@ -45,9 +53,9 @@ async function injectDOMTestingLibrary(container: ElementBase) {
45
53
} )
46
54
47
55
if ( shouldInject . domTestingLibrary ) {
48
- await container . execute ( function ( library ) {
56
+ await container . execute ( function ( library : string ) {
49
57
// add DOM Testing Library to page as a script tag to support Firefox
50
- if ( navigator . userAgent . indexOf ( 'Firefox' ) !== - 1 ) {
58
+ if ( navigator . userAgent . includes ( 'Firefox' ) ) {
51
59
const script = document . createElement ( 'script' )
52
60
script . innerHTML = library
53
61
return document . head . append ( script )
@@ -62,74 +70,83 @@ async function injectDOMTestingLibrary(container: ElementBase) {
62
70
await container . execute ( SIMMERJS )
63
71
}
64
72
65
- if ( _config ) {
66
- await container . execute ( function ( config : Config ) {
67
- window . TestingLibraryDom . configure ( config )
68
- } , _config )
69
- }
73
+ await container . execute ( function ( config : Config ) {
74
+ window . TestingLibraryDom . configure ( config )
75
+ } , _config )
70
76
}
71
77
72
- function serializeObject ( object : Object ) : Object {
78
+ function serializeObject ( object : ObjectQueryArg ) : SerializedObject {
73
79
return Object . entries ( object )
74
- . map ( ( [ key , value ] ) => [ key , serializeArg ( value ) ] )
75
- . reduce ( ( acc , [ key , value ] ) => ( { ...acc , [ key ] : value } ) , { } )
80
+ . map < [ string , SerializedArg ] > ( ( [ key , value ] : [ string , QueryArg ] ) => [
81
+ key ,
82
+ serializeArg ( value ) ,
83
+ ] )
84
+ . reduce ( ( acc , [ key , value ] ) => ( { ...acc , [ key ] : value } ) , {
85
+ serialized : 'object' ,
86
+ } )
76
87
}
77
88
78
- function serializeArg ( arg : any ) {
89
+ function serializeArg ( arg : QueryArg ) : SerializedArg {
79
90
if ( arg instanceof RegExp ) {
80
- return { RegExp : arg . toString ( ) }
91
+ return { serialized : 'RegExp' , RegExp : arg . toString ( ) }
81
92
}
82
93
if ( typeof arg === 'undefined' ) {
83
- return { Undefined : true }
94
+ return { serialized : 'Undefined' , Undefined : true }
84
95
}
85
96
if ( arg && typeof arg === 'object' ) {
86
97
return serializeObject ( arg )
87
98
}
88
99
return arg
89
100
}
90
101
102
+ type SerializedQueryResult =
103
+ | { selector : string | false ; element : HTMLElement } [ ]
104
+ | string
105
+ | { selector : string | false ; element : HTMLElement }
106
+ | null
107
+
91
108
function executeQuery (
92
109
query : QueryName ,
93
110
container : HTMLElement ,
94
- ...args : any [ ]
111
+ ...args : SerializedArg [ ]
95
112
) {
96
- const done = args . pop ( ) as ( result : any ) => void
113
+ const done = args . pop ( ) as unknown as ( result : SerializedQueryResult ) => void
97
114
98
- function deserializeObject ( object : object ) : object {
115
+ function deserializeObject ( object : SerializedObject ) {
99
116
return Object . entries ( object )
100
- . map ( ( [ key , value ] ) => [ key , deserializeArg ( value ) ] )
117
+ . map < [ string , QueryArg ] > ( ( [ key , value ] ) => [ key , deserializeArg ( value ) ] )
101
118
. reduce ( ( acc , [ key , value ] ) => ( { ...acc , [ key ] : value } ) , { } )
102
119
}
103
120
104
- function deserializeArg ( arg : any ) {
105
- if ( arg && arg . RegExp ) {
121
+ function deserializeArg ( arg : SerializedArg ) : QueryArg {
122
+ if ( typeof arg === 'object' && arg . serialized === ' RegExp' ) {
106
123
return eval ( arg . RegExp )
107
124
}
108
- if ( arg && arg . Undefined ) {
125
+ if ( typeof arg === 'object' && arg . serialized === ' Undefined' ) {
109
126
return undefined
110
127
}
111
- if ( arg && typeof arg === 'object' ) {
128
+ if ( typeof arg === 'object' ) {
112
129
return deserializeObject ( arg )
113
130
}
114
131
return arg
115
132
}
116
133
117
134
const [ matcher , options , waitForOptions ] = args . map ( deserializeArg )
118
135
119
- ; ( async ( ) => {
120
- let result : undefined | null | HTMLElement | HTMLElement [ ]
136
+ void ( async ( ) => {
137
+ let result : ReturnType < typeof window . TestingLibraryDom [ typeof query ] > = null
121
138
try {
122
139
// Override RegExp to fix 'matcher instanceof RegExp' check on Firefox
123
140
window . RegExp = RegExp
124
141
125
142
result = await window . TestingLibraryDom [ query ] (
126
143
container ,
127
- matcher ,
128
- options ,
129
- waitForOptions ,
144
+ matcher as Matcher ,
145
+ options as MatcherOptions ,
146
+ waitForOptions as WaitForOptions ,
130
147
)
131
- } catch ( e ) {
132
- done ( e . message )
148
+ } catch ( e : unknown ) {
149
+ return done ( ( e as Error ) . message )
133
150
}
134
151
135
152
if ( ! result ) {
@@ -160,10 +177,10 @@ Element. There are valid WebElement JSONs that exclude the key but can be turned
160
177
into Elements, such as { ELEMENT: elementId }; this can happen in setups that
161
178
aren't generated by @wdio/cli.
162
179
*/
163
- function createElement (
180
+ async function createElement (
164
181
container : ElementBase ,
165
- result : { selector : string | false ; element : any } ,
166
- ) {
182
+ result : { selector : string | false ; element : object } ,
183
+ ) : Promise < WebdriverIO . Element > {
167
184
// use selector if possible so that element can be refetched
168
185
if ( result . selector ) {
169
186
return container . $ ( result . selector )
@@ -176,11 +193,12 @@ function createElement(
176
193
} )
177
194
}
178
195
179
- function createQuery ( container : ElementBase , queryName : string ) {
180
- return async ( ...args : any [ ] ) => {
196
+ function createQuery ( container : ElementBase , queryName : QueryName ) {
197
+ return async ( ...args : QueryArg [ ] ) => {
181
198
await injectDOMTestingLibrary ( container )
182
199
183
- const result = await container . executeAsync (
200
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
201
+ const result : SerializedQueryResult = await container . executeAsync (
184
202
executeQuery ,
185
203
queryName ,
186
204
container ,
@@ -204,7 +222,7 @@ function createQuery(container: ElementBase, queryName: string) {
204
222
}
205
223
206
224
function within ( element : ElementBase ) {
207
- return Object . keys ( baseQueries ) . reduce (
225
+ return ( Object . keys ( baseQueries ) as QueryName [ ] ) . reduce (
208
226
( queries , queryName ) => ( {
209
227
...queries ,
210
228
[ queryName ] : createQuery ( element , queryName ) ,
@@ -213,22 +231,29 @@ function within(element: ElementBase) {
213
231
) as WebdriverIOQueries
214
232
}
215
233
216
- function setupBrowser ( browser : BrowserBase ) {
217
- const queries : { [ key : string ] : any } = { }
234
+ /*
235
+ eslint-disable
236
+ @typescript -eslint/no-explicit-any,
237
+ @typescript -eslint/no-unsafe-argument
238
+ */
239
+ function setupBrowser ( browser : BrowserBase ) : WebdriverIOQueries {
240
+ const queries : { [ key : string ] : WebdriverIOQueries [ QueryName ] } = { }
218
241
219
242
Object . keys ( baseQueries ) . forEach ( ( key ) => {
220
- const queryName = key as keyof typeof baseQueries
243
+ const queryName = key as QueryName
221
244
222
- const query = async ( ...args : any [ ] ) => {
245
+ const query = async (
246
+ ...args : Parameters < WebdriverIOQueries [ QueryName ] >
247
+ ) => {
223
248
const body = await browser . $ ( 'body' )
224
- return within ( body ) [ queryName ] ( ...args )
249
+ return within ( body ) [ queryName ] ( ...( args as any [ ] ) )
225
250
}
226
251
227
252
// add query to response queries
228
- queries [ queryName ] = query
253
+ queries [ queryName ] = query as WebdriverIOQueries [ QueryName ]
229
254
230
255
// add query to BrowserObject
231
- browser . addCommand ( queryName , query )
256
+ browser . addCommand ( queryName , query as WebdriverIOQueries [ QueryName ] )
232
257
233
258
// add query to Elements
234
259
browser . addCommand (
@@ -242,6 +267,11 @@ function setupBrowser(browser: BrowserBase) {
242
267
243
268
return queries as WebdriverIOQueries
244
269
}
270
+ /*
271
+ eslint-enable
272
+ @typescript -eslint/no-explicit-any,
273
+ @typescript -eslint/no-unsafe-argument
274
+ */
245
275
246
276
function configure ( config : Partial < Config > ) {
247
277
_config = config
0 commit comments