33import path from 'path'
44import fs from 'fs'
55import { queries as baseQueries } from '@testing-library/dom'
6+ import 'simmerjs'
67
78import {
89 BrowserBase ,
@@ -29,15 +30,36 @@ const DOM_TESTING_LIBRARY_UMD = fs
2930 . readFileSync ( DOM_TESTING_LIBRARY_UMD_PATH )
3031 . toString ( )
3132
33+ const SIMMERJS = fs
34+ . readFileSync ( require . resolve ( 'simmerjs/dist/simmer.js' ) )
35+ . toString ( )
36+
3237let _config : Partial < Config >
3338
3439async function injectDOMTestingLibrary ( container : ElementBase ) {
3540 const shouldInject = await container . execute ( function ( ) {
36- return ! window . TestingLibraryDom
41+ return {
42+ domTestingLibrary : ! window . TestingLibraryDom ,
43+ simmer : ! window . Simmer ,
44+ }
3745 } )
3846
39- if ( shouldInject ) {
40- await container . execute ( DOM_TESTING_LIBRARY_UMD )
47+ if ( shouldInject . domTestingLibrary ) {
48+ await container . execute ( function ( library ) {
49+ // add DOM Testing Library to page as a script tag to support Firefox
50+ if ( navigator . userAgent . indexOf ( 'Firefox' ) !== - 1 ) {
51+ const script = document . createElement ( 'script' )
52+ script . innerHTML = library
53+ return document . head . append ( script )
54+ }
55+
56+ // eval library on other browsers
57+ return eval ( library )
58+ } , DOM_TESTING_LIBRARY_UMD )
59+ }
60+
61+ if ( shouldInject . simmer ) {
62+ await container . execute ( SIMMERJS )
4163 }
4264
4365 if ( _config ) {
@@ -67,18 +89,19 @@ function serializeArg(arg: any) {
6789}
6890
6991function executeQuery (
70- [ query , container , ...args ] : [ QueryName , HTMLElement , ...any [ ] ] ,
71- done : ( result : any ) => void ,
92+ query : QueryName ,
93+ container : HTMLElement ,
94+ ...args : any [ ]
7295) {
73- // @ts -ignore
74- function deserializeObject ( object ) {
96+ const done = args . pop ( ) as ( result : any ) => void
97+
98+ function deserializeObject ( object : object ) : object {
7599 return Object . entries ( object )
76100 . map ( ( [ key , value ] ) => [ key , deserializeArg ( value ) ] )
77101 . reduce ( ( acc , [ key , value ] ) => ( { ...acc , [ key ] : value } ) , { } )
78102 }
79103
80- // @ts -ignore
81- function deserializeArg ( arg ) {
104+ function deserializeArg ( arg : any ) {
82105 if ( arg && arg . RegExp ) {
83106 return eval ( arg . RegExp )
84107 }
@@ -93,16 +116,40 @@ function executeQuery(
93116
94117 const [ matcher , options , waitForOptions ] = args . map ( deserializeArg )
95118
96- Promise . resolve (
97- window . TestingLibraryDom [ query ] (
98- container ,
99- matcher ,
100- options ,
101- waitForOptions ,
102- ) ,
103- )
104- . then ( done )
105- . catch ( ( e ) => done ( e . message ) )
119+ ; ( async ( ) => {
120+ let result : undefined | null | HTMLElement | HTMLElement [ ]
121+ try {
122+ // Override RegExp to fix 'matcher instanceof RegExp' check on Firefox
123+ window . RegExp = RegExp
124+
125+ result = await window . TestingLibraryDom [ query ] (
126+ container ,
127+ matcher ,
128+ options ,
129+ waitForOptions ,
130+ )
131+ } catch ( e ) {
132+ done ( e . message )
133+ }
134+
135+ if ( ! result ) {
136+ return done ( null )
137+ }
138+
139+ if ( Array . isArray ( result ) ) {
140+ return done (
141+ result . map ( ( element ) => ( {
142+ selector : window . Simmer ( element ) ,
143+ element,
144+ } ) ) ,
145+ )
146+ }
147+
148+ return done ( {
149+ selector : window . Simmer ( result ) ,
150+ element : result ,
151+ } )
152+ } ) ( )
106153}
107154
108155/*
@@ -113,22 +160,32 @@ Element. There are valid WebElement JSONs that exclude the key but can be turned
113160into Elements, such as { ELEMENT: elementId }; this can happen in setups that
114161aren't generated by @wdio/cli.
115162*/
116- function createElement ( container : ElementBase , elementValue : any ) {
163+ function createElement (
164+ container : ElementBase ,
165+ result : { selector : string | false ; element : any } ,
166+ ) {
167+ // use selector if possible so that element can be refetched
168+ if ( result . selector ) {
169+ return container . $ ( result . selector )
170+ }
171+
172+ // fallback to using WebElement JSON if selector could not be created
117173 return container . $ ( {
118174 'element-6066-11e4-a52e-4f735466cecf' : '' ,
119- ...elementValue ,
175+ ...result . element ,
120176 } )
121177}
122178
123- function createQuery ( element : ElementBase , queryName : string ) {
179+ function createQuery ( container : ElementBase , queryName : string ) {
124180 return async ( ...args : any [ ] ) => {
125- await injectDOMTestingLibrary ( element )
181+ await injectDOMTestingLibrary ( container )
126182
127- const result = await element . executeAsync ( executeQuery , [
183+ const result = await container . executeAsync (
184+ executeQuery ,
128185 queryName ,
129- element ,
186+ container ,
130187 ...args . map ( serializeArg ) ,
131- ] )
188+ )
132189
133190 if ( typeof result === 'string' ) {
134191 throw new Error ( result )
@@ -139,10 +196,10 @@ function createQuery(element: ElementBase, queryName: string) {
139196 }
140197
141198 if ( Array . isArray ( result ) ) {
142- return Promise . all ( result . map ( createElement . bind ( null , element ) ) )
199+ return Promise . all ( result . map ( createElement . bind ( null , container ) ) )
143200 }
144201
145- return createElement ( element , result )
202+ return createElement ( container , result )
146203 }
147204}
148205
0 commit comments