@@ -9,11 +9,16 @@ interface PathPart {
99}
1010
1111let useShadowRoot = false ;
12+ let useRowShadowRoot = false ;
1213
1314export function setUseShadowRoot ( val : boolean ) {
1415 useShadowRoot = val ;
1516}
1617
18+ export function setUseRowShadowRoot ( val : boolean ) {
19+ useRowShadowRoot = val ;
20+ }
21+
1722function convertPath ( path : string ) : Array < PathPart > {
1823 let parts = path . split ( / \/ / ) . filter ( v => ! ! v ) ;
1924 let res : Array < PathPart > = [ ] ;
@@ -35,16 +40,36 @@ function convertPath(path: string): Array<PathPart> {
3540 return res ;
3641}
3742
43+ async function shadowRoot ( driver : WebDriver , selector : string ) : Promise < WebElement > {
44+ const el = await driver . findElement ( By . css ( selector ) ) ;
45+ return driver . executeScript ( `return arguments[0].shadowRoot` , el ) ;
46+ }
47+
3848// Fake findByXPath for simple XPath expressions to allow usage with shadow dom
39- export async function findByXPath ( node : WebElement , path : string ) : Promise < WebElement > {
49+ export async function findByXPath ( driver : WebDriver , path : string ) : Promise < WebElement > {
50+ let root = useShadowRoot ? await shadowRoot ( driver , 'main-element' ) : await driver . findElement ( By . tagName ( "body" ) ) ;
4051 let paths = convertPath ( path ) ;
41- let n = node ;
52+ let n = root ;
4253 try {
43- for ( let p of paths ) {
44- // n = n.then(nd => nd.findElements(By.tagName(p.tagName))).then(elems => { // costly since it fetches all elements
45- let elems = await n . findElements ( By . css ( p . tagName + ":nth-child(" + ( p . index ) + ")" ) ) ;
46- if ( elems == null || elems . length == 0 ) { return null } ;
47- n = elems [ 0 ] ;
54+ for ( let p of paths ) {
55+ let elem ;
56+ if ( useRowShadowRoot && p . tagName === 'tr' ) {
57+ try {
58+ const shadowHost = await shadowRoot ( driver , `benchmark-row:nth-child(${ p . index } )` ) ;
59+ elem = await shadowHost . findElement ( By . tagName ( 'tr' ) ) ;
60+ if ( elem === null ) {
61+ return null ;
62+ }
63+ } catch {
64+ return null ;
65+ }
66+ } else {
67+ let elems = await n . findElements ( By . css ( p . tagName + ":nth-child(" + ( p . index ) + ")" ) ) ;
68+ if ( elems == null || elems . length == 0 ) { return null } ;
69+ elem = elems [ 0 ] ;
70+ }
71+
72+ n = elem ;
4873 }
4974 } catch ( e ) {
5075 //can happen for StaleElementReferenceError
@@ -70,8 +95,7 @@ export async function testTextContains(driver: WebDriver, xpath: string, text: s
7095 return waitForCondition ( driver ) ( `testTextContains ${ xpath } ${ text } ` ,
7196 async function ( driver ) {
7297 try {
73- let elem = await shadowRoot ( driver ) ;
74- elem = await findByXPath ( elem , xpath ) ;
98+ let elem = await findByXPath ( driver , xpath ) ;
7599 if ( elem == null ) return false ;
76100 let v = await elem . getText ( ) ;
77101 return v && v . indexOf ( text ) > - 1 ;
@@ -85,8 +109,7 @@ export function testTextNotContained(driver: WebDriver, xpath: string, text: str
85109 return waitForCondition ( driver ) ( `testTextNotContained ${ xpath } ${ text } ` ,
86110 async function ( driver ) {
87111 try {
88- let elem = await shadowRoot ( driver ) ;
89- elem = await findByXPath ( elem , xpath ) ;
112+ let elem = await findByXPath ( driver , xpath ) ;
90113 if ( elem == null ) return false ;
91114 let v = await elem . getText ( ) ;
92115 return v && v . indexOf ( text ) == - 1 ;
@@ -100,8 +123,7 @@ export function testClassContains(driver: WebDriver, xpath: string, text: string
100123 return waitForCondition ( driver ) ( `testClassContains ${ xpath } ${ text } ` ,
101124 async function ( driver ) {
102125 try {
103- let elem = await shadowRoot ( driver ) ;
104- elem = await findByXPath ( elem , xpath ) ;
126+ let elem = await findByXPath ( driver , xpath ) ;
105127 if ( elem == null ) return false ;
106128 let v = await elem . getAttribute ( "class" ) ;
107129 return v && v . indexOf ( text ) > - 1 ;
@@ -115,8 +137,7 @@ export function testElementLocatedByXpath(driver: WebDriver, xpath: string, time
115137 return waitForCondition ( driver ) ( `testElementLocatedByXpath ${ xpath } ` ,
116138 async function ( driver ) {
117139 try {
118- let elem = await shadowRoot ( driver ) ;
119- elem = await findByXPath ( elem , xpath ) ;
140+ let elem = await findByXPath ( driver , xpath ) ;
120141 return elem ? true : false ;
121142 } catch ( err ) {
122143 console . log ( "ignoring error in testElementLocatedByXpath for xpath = " + xpath , err . toString ( ) )
@@ -128,8 +149,7 @@ export function testElementNotLocatedByXPath(driver: WebDriver, xpath: string, t
128149 return waitForCondition ( driver ) ( `testElementNotLocatedByXPath ${ xpath } ` ,
129150 async function ( driver ) {
130151 try {
131- let elem = await shadowRoot ( driver ) ;
132- elem = await findByXPath ( elem , xpath ) ;
152+ let elem = await findByXPath ( driver , xpath ) ;
133153 return elem ? false : true ;
134154 } catch ( err ) {
135155 console . log ( "ignoring error in testElementNotLocatedByXPath for xpath = " + xpath , err . toString ( ) . split ( "\n" ) [ 0 ] ) ;
@@ -141,7 +161,7 @@ export function testElementLocatedById(driver: WebDriver, id: string, timeout =
141161 return waitForCondition ( driver ) ( `testElementLocatedById ${ id } ` ,
142162 async function ( driver ) {
143163 try {
144- let elem = await shadowRoot ( driver ) ;
164+ let elem = await mainRoot ( driver ) ;
145165 elem = await elem . findElement ( By . id ( id ) ) ;
146166 return true ;
147167 } catch ( err ) {
@@ -164,7 +184,7 @@ async function retry<T>(retryCount: number, driver: WebDriver, fun : (driver: W
164184// No idea how that can be explained
165185export function clickElementById ( driver : WebDriver , id : string ) {
166186 return retry ( 5 , driver , async function ( driver ) {
167- let elem = await shadowRoot ( driver ) ;
187+ let elem = await mainRoot ( driver ) ;
168188 elem = await elem . findElement ( By . id ( id ) ) ;
169189 await elem . click ( ) ;
170190 } ) ;
@@ -173,8 +193,7 @@ export function clickElementById(driver: WebDriver, id: string) {
173193export function clickElementByXPath ( driver : WebDriver , xpath : string ) {
174194 return retry ( 5 , driver , async function ( driver , count ) {
175195 if ( count > 1 && config . LOG_DETAILS ) console . log ( "clickElementByXPath " , xpath , " attempt #" , count ) ;
176- let elem = await shadowRoot ( driver ) ;
177- elem = await findByXPath ( elem , xpath ) ;
196+ let elem = await findByXPath ( driver , xpath ) ;
178197 await elem . click ( ) ;
179198 } ) ;
180199 // Stale element possible:
@@ -184,15 +203,13 @@ export function clickElementByXPath(driver: WebDriver, xpath: string) {
184203export async function getTextByXPath ( driver : WebDriver , xpath : string ) : Promise < string > {
185204 return await retry ( 5 , driver , async function ( driver , count ) {
186205 if ( count > 1 && config . LOG_DETAILS ) console . log ( "getTextByXPath " , xpath , " attempt #" , count ) ;
187- let elem = await shadowRoot ( driver ) ;
188- elem = await findByXPath ( elem , xpath ) ;
206+ let elem = await findByXPath ( driver , xpath ) ;
189207 return await elem . getText ( ) ;
190208 } ) ;
191209}
192210
193- export async function shadowRoot ( driver : WebDriver ) : Promise < WebElement > {
194- return useShadowRoot ? await driver . executeScript ( 'return document.querySelector("main-element").shadowRoot' ) as WebElement
195- : await driver . findElement ( By . tagName ( "body" ) ) ;
211+ export async function mainRoot ( driver : WebDriver ) : Promise < WebElement > {
212+ return useShadowRoot ? shadowRoot ( driver , 'main-element' ) : driver . findElement ( By . tagName ( "body" ) ) ;
196213}
197214
198215// node_modules\.bin\chromedriver.cmd --verbose --port=9998 --log-path=chromedriver.log
0 commit comments