@@ -9,11 +9,16 @@ interface PathPart {
9
9
}
10
10
11
11
let useShadowRoot = false ;
12
+ let useRowShadowRoot = false ;
12
13
13
14
export function setUseShadowRoot ( val : boolean ) {
14
15
useShadowRoot = val ;
15
16
}
16
17
18
+ export function setUseRowShadowRoot ( val : boolean ) {
19
+ useRowShadowRoot = val ;
20
+ }
21
+
17
22
function convertPath ( path : string ) : Array < PathPart > {
18
23
let parts = path . split ( / \/ / ) . filter ( v => ! ! v ) ;
19
24
let res : Array < PathPart > = [ ] ;
@@ -35,16 +40,36 @@ function convertPath(path: string): Array<PathPart> {
35
40
return res ;
36
41
}
37
42
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
+
38
48
// 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" ) ) ;
40
51
let paths = convertPath ( path ) ;
41
- let n = node ;
52
+ let n = root ;
42
53
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 ;
48
73
}
49
74
} catch ( e ) {
50
75
//can happen for StaleElementReferenceError
@@ -70,8 +95,7 @@ export async function testTextContains(driver: WebDriver, xpath: string, text: s
70
95
return waitForCondition ( driver ) ( `testTextContains ${ xpath } ${ text } ` ,
71
96
async function ( driver ) {
72
97
try {
73
- let elem = await shadowRoot ( driver ) ;
74
- elem = await findByXPath ( elem , xpath ) ;
98
+ let elem = await findByXPath ( driver , xpath ) ;
75
99
if ( elem == null ) return false ;
76
100
let v = await elem . getText ( ) ;
77
101
return v && v . indexOf ( text ) > - 1 ;
@@ -85,8 +109,7 @@ export function testTextNotContained(driver: WebDriver, xpath: string, text: str
85
109
return waitForCondition ( driver ) ( `testTextNotContained ${ xpath } ${ text } ` ,
86
110
async function ( driver ) {
87
111
try {
88
- let elem = await shadowRoot ( driver ) ;
89
- elem = await findByXPath ( elem , xpath ) ;
112
+ let elem = await findByXPath ( driver , xpath ) ;
90
113
if ( elem == null ) return false ;
91
114
let v = await elem . getText ( ) ;
92
115
return v && v . indexOf ( text ) == - 1 ;
@@ -100,8 +123,7 @@ export function testClassContains(driver: WebDriver, xpath: string, text: string
100
123
return waitForCondition ( driver ) ( `testClassContains ${ xpath } ${ text } ` ,
101
124
async function ( driver ) {
102
125
try {
103
- let elem = await shadowRoot ( driver ) ;
104
- elem = await findByXPath ( elem , xpath ) ;
126
+ let elem = await findByXPath ( driver , xpath ) ;
105
127
if ( elem == null ) return false ;
106
128
let v = await elem . getAttribute ( "class" ) ;
107
129
return v && v . indexOf ( text ) > - 1 ;
@@ -115,8 +137,7 @@ export function testElementLocatedByXpath(driver: WebDriver, xpath: string, time
115
137
return waitForCondition ( driver ) ( `testElementLocatedByXpath ${ xpath } ` ,
116
138
async function ( driver ) {
117
139
try {
118
- let elem = await shadowRoot ( driver ) ;
119
- elem = await findByXPath ( elem , xpath ) ;
140
+ let elem = await findByXPath ( driver , xpath ) ;
120
141
return elem ? true : false ;
121
142
} catch ( err ) {
122
143
console . log ( "ignoring error in testElementLocatedByXpath for xpath = " + xpath , err . toString ( ) )
@@ -128,8 +149,7 @@ export function testElementNotLocatedByXPath(driver: WebDriver, xpath: string, t
128
149
return waitForCondition ( driver ) ( `testElementNotLocatedByXPath ${ xpath } ` ,
129
150
async function ( driver ) {
130
151
try {
131
- let elem = await shadowRoot ( driver ) ;
132
- elem = await findByXPath ( elem , xpath ) ;
152
+ let elem = await findByXPath ( driver , xpath ) ;
133
153
return elem ? false : true ;
134
154
} catch ( err ) {
135
155
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 =
141
161
return waitForCondition ( driver ) ( `testElementLocatedById ${ id } ` ,
142
162
async function ( driver ) {
143
163
try {
144
- let elem = await shadowRoot ( driver ) ;
164
+ let elem = await mainRoot ( driver ) ;
145
165
elem = await elem . findElement ( By . id ( id ) ) ;
146
166
return true ;
147
167
} catch ( err ) {
@@ -164,7 +184,7 @@ async function retry<T>(retryCount: number, driver: WebDriver, fun : (driver: W
164
184
// No idea how that can be explained
165
185
export function clickElementById ( driver : WebDriver , id : string ) {
166
186
return retry ( 5 , driver , async function ( driver ) {
167
- let elem = await shadowRoot ( driver ) ;
187
+ let elem = await mainRoot ( driver ) ;
168
188
elem = await elem . findElement ( By . id ( id ) ) ;
169
189
await elem . click ( ) ;
170
190
} ) ;
@@ -173,8 +193,7 @@ export function clickElementById(driver: WebDriver, id: string) {
173
193
export function clickElementByXPath ( driver : WebDriver , xpath : string ) {
174
194
return retry ( 5 , driver , async function ( driver , count ) {
175
195
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 ) ;
178
197
await elem . click ( ) ;
179
198
} ) ;
180
199
// Stale element possible:
@@ -184,15 +203,13 @@ export function clickElementByXPath(driver: WebDriver, xpath: string) {
184
203
export async function getTextByXPath ( driver : WebDriver , xpath : string ) : Promise < string > {
185
204
return await retry ( 5 , driver , async function ( driver , count ) {
186
205
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 ) ;
189
207
return await elem . getText ( ) ;
190
208
} ) ;
191
209
}
192
210
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" ) ) ;
196
213
}
197
214
198
215
// node_modules\.bin\chromedriver.cmd --verbose --port=9998 --log-path=chromedriver.log
0 commit comments