@@ -39,12 +39,17 @@ const DOM_TESTING_LIBRARY_UMD = fs
3939 . toString ( )
4040 . replace ( 'define.amd' , 'false' ) // Never inject DTL using AMD define function
4141
42+ const SIMMERJS = fs
43+ . readFileSync ( require . resolve ( 'simmerjs/dist/simmer.js' ) )
44+ . toString ( )
45+
4246let _config : Partial < Config >
4347
4448async function injectDOMTestingLibrary ( container : ElementBase ) {
4549 const shouldInject = await container . parent . execute ( function ( ) {
4650 return {
47- domTestingLibrary : ! window . TestingLibraryDom
51+ domTestingLibrary : ! window . TestingLibraryDom ,
52+ simmer : ! window . Simmer ,
4853 }
4954 } )
5055
@@ -62,6 +67,10 @@ async function injectDOMTestingLibrary(container: ElementBase) {
6267 } , DOM_TESTING_LIBRARY_UMD )
6368 }
6469
70+ if ( shouldInject . simmer ) {
71+ await container . parent . execute ( SIMMERJS )
72+ }
73+
6574 await container . parent . execute ( function ( config : Config ) {
6675 window . TestingLibraryDom . configure ( config )
6776 } , _config )
@@ -145,17 +154,24 @@ function executeQuery(
145154 return done ( null )
146155 }
147156
148- const elementIdAttributeName = 'data-wdio-testing-lib-element-id' ;
149- const makeSelectorResult = ( element : HTMLElement ) => {
150- let elementId = element . getAttribute ( elementIdAttributeName ) ;
151- if ( elementId == null ) {
152- const idSequence = window . TestingLibraryDom . idSequence ?? 10000 ;
153- window . TestingLibraryDom . idSequence = idSequence + 1 ;
154- elementId = `${ idSequence } ` ;
157+ function makeSelectorResult ( element : HTMLElement ) {
158+ // use simmer if possible to allow element refetching by position, otherwise
159+ // situations such as a React key change causes refetching to fail.
160+ const selector = window . Simmer ( element )
161+ if ( selector ) return { selector}
162+
163+ // use generated element id as selector if Simmer fails
164+ const elementIdAttributeName = 'data-wdio-testing-lib-element-id'
165+ let elementId = element . getAttribute ( elementIdAttributeName )
166+
167+ // if id doesn't already exist create one and add it to element
168+ if ( ! elementId ) {
169+ elementId = ( Math . abs ( Math . random ( ) ) * 1000000000000 ) . toFixed ( 0 )
155170 element . setAttribute ( elementIdAttributeName , elementId )
156171 }
157- return ( { selector : `[${ elementIdAttributeName } ="${ elementId } "]` } )
158- } ;
172+
173+ return { selector :`[${ elementIdAttributeName } ="${ elementId } "]` }
174+ }
159175
160176 if ( Array . isArray ( result ) ) {
161177 return done ( result . map ( makeSelectorResult ) ) ;
@@ -165,13 +181,6 @@ function executeQuery(
165181 } ) ( )
166182}
167183
168- async function findElement (
169- container : ElementBase ,
170- result : { selector : string } ,
171- ) : Promise < WebdriverIO . Element > {
172- return container . $ ( result . selector )
173- }
174-
175184function createQuery ( container : ElementBase , queryName : QueryName ) {
176185 return async ( ...args : QueryArg [ ] ) => {
177186 await injectDOMTestingLibrary ( container )
@@ -193,10 +202,10 @@ function createQuery(container: ElementBase, queryName: QueryName) {
193202 }
194203
195204 if ( Array . isArray ( result ) ) {
196- return Promise . all ( result . map ( findElement . bind ( null , container ) ) )
205+ return Promise . all ( result . map ( ( { selector } ) => container . $ ( selector ) ) )
197206 }
198207
199- return findElement ( container , result )
208+ return container . $ ( result . selector )
200209 }
201210}
202211
0 commit comments