Skip to content

Commit 4e24e99

Browse files
[js] add support for handling Shadow DOM elements
1 parent ec914c6 commit 4e24e99

File tree

7 files changed

+366
-58
lines changed

7 files changed

+366
-58
lines changed

javascript/node/selenium-webdriver/lib/command.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ const Name = {
168168
GET_ALERT_TEXT: 'getAlertText',
169169
SET_ALERT_TEXT: 'setAlertValue',
170170

171+
// Shadow DOM Commands
172+
GET_SHADOW_ROOT: 'getShadowRoot',
173+
FIND_ELEMENT_FROM_SHADOWROOT: 'findElementFromShadowRoot',
174+
FIND_ELEMENTS_FROM_SHADOWROOT: 'findElementsFromShadowRoot',
175+
171176
GET_AVAILABLE_LOG_TYPES: 'getAvailableLogTypes',
172177
GET_LOG: 'getLog',
173178
GET_SESSION_LOGS: 'getSessionLogs',

javascript/node/selenium-webdriver/lib/error.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ class WebDriverError extends Error {
3939
}
4040
}
4141

42+
/**
43+
* Indicates the shadow root is no longer attached to the DOM
44+
*/
45+
class DetachedShadowRootError extends WebDriverError {
46+
/** @param {string=} opt_error the error message, if any. */
47+
constructor(opt_error) {
48+
super(opt_error)
49+
}
50+
}
51+
4252
/**
4353
* Indicates a {@linkplain ./webdriver.WebElement#click click command} could not
4454
* completed because the click target is obscured by other elements on the
@@ -201,6 +211,16 @@ class NoSuchElementError extends WebDriverError {
201211
}
202212
}
203213

214+
/**
215+
* A ShadowRoot could not be located on the element
216+
*/
217+
class NoSuchShadowRootError extends WebDriverError {
218+
/** @param {string=} opt_error the error message, if any. */
219+
constructor(opt_error) {
220+
super(opt_error);
221+
}
222+
}
223+
204224
/**
205225
* A request to switch to a frame could not be satisfied because the frame
206226
* could not be found.
@@ -420,6 +440,7 @@ const LEGACY_ERROR_CODE_TO_TYPE = new Map([
420440

421441
const ERROR_CODE_TO_TYPE = new Map([
422442
['unknown error', WebDriverError],
443+
['detached shadow root', DetachedShadowRootError],
423444
['element click intercepted', ElementClickInterceptedError],
424445
['element not interactable', ElementNotInteractableError],
425446
['element not selectable', ElementNotSelectableError],
@@ -436,6 +457,7 @@ const ERROR_CODE_TO_TYPE = new Map([
436457
['no such cookie', NoSuchCookieError],
437458
['no such element', NoSuchElementError],
438459
['no such frame', NoSuchFrameError],
460+
['no such shadow root', NoSuchShadowRootError],
439461
['no such window', NoSuchWindowError],
440462
['script timeout', ScriptTimeoutError],
441463
['session not created', SessionNotCreatedError],
@@ -569,6 +591,7 @@ module.exports = {
569591
ErrorCode,
570592

571593
WebDriverError,
594+
DetachedShadowRootError,
572595
ElementClickInterceptedError,
573596
ElementNotInteractableError,
574597
ElementNotSelectableError,
@@ -584,6 +607,7 @@ module.exports = {
584607
NoSuchCookieError,
585608
NoSuchElementError,
586609
NoSuchFrameError,
610+
NoSuchShadowRootError,
587611
NoSuchSessionError,
588612
NoSuchWindowError,
589613
ScriptTimeoutError,

javascript/node/selenium-webdriver/lib/http.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const error = require('./error')
3131
const logging = require('./logging')
3232
const promise = require('./promise')
3333
const { Session } = require('./session')
34-
const { WebElement } = require('./webdriver')
34+
const { WebElement, ShadowRoot } = require('./webdriver')
3535

3636
const getAttribute = requireAtom(
3737
'get-attribute.js',
@@ -63,8 +63,8 @@ function requireAtom(module, bazelTarget) {
6363
console.log(ex2)
6464
throw Error(
6565
`Failed to import atoms module ${module}. If running in dev mode, you` +
66-
` need to run \`bazel build ${bazelTarget}\` from the project` +
67-
`root: ${ex}`
66+
` need to run \`bazel build ${bazelTarget}\` from the project` +
67+
`root: ${ex}`
6868
)
6969
}
7070
}
@@ -173,7 +173,7 @@ var CommandSpec // eslint-disable-line
173173
/** @typedef {function(!cmd.Command): !cmd.Command} */
174174
var CommandTransformer // eslint-disable-line
175175

176-
class InternalTypeError extends TypeError {}
176+
class InternalTypeError extends TypeError { }
177177

178178
/**
179179
* @param {!cmd.Command} command The initial command.
@@ -421,6 +421,10 @@ const W3C_COMMAND_MAP = new Map([
421421
],
422422
// print page.
423423
[cmd.Name.PRINT_PAGE, post('/session/:sessionId/print')],
424+
// Shadow Root
425+
[cmd.Name.GET_SHADOW_ROOT, get('/session/:sessionId/element/:id/shadow')],
426+
[cmd.Name.FIND_ELEMENT_FROM_SHADOWROOT, post('/session/:sessionId/shadow/:id/element')],
427+
[cmd.Name.FIND_ELEMENTS_FROM_SHADOWROOT, post('/session/:sessionId/shadow/:id/elements')],
424428
// Log extensions.
425429
[cmd.Name.GET_LOG, post('/session/:sessionId/se/log')],
426430
[cmd.Name.GET_AVAILABLE_LOG_TYPES, get('/session/:sessionId/se/log/types')],
@@ -441,7 +445,7 @@ class Client {
441445
* @return {!Promise<Response>} A promise that will be fulfilled with the
442446
* server's response.
443447
*/
444-
send(httpRequest) {} // eslint-disable-line
448+
send(httpRequest) { } // eslint-disable-line
445449
}
446450

447451
/**
@@ -584,7 +588,7 @@ class Executor {
584588
// No implementations use the `capabilities` key yet...
585589
let capabilities = value.capabilities || value.value
586590
return new Session(
587-
/** @type {{sessionId: string}} */ (value).sessionId,
591+
/** @type {{sessionId: string}} */(value).sessionId,
588592
capabilities
589593
)
590594
}

javascript/node/selenium-webdriver/lib/test/fileserver.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ const Pages = (function () {
102102
addPage('unicodeLtrPage', 'utf8/unicode_ltr.html')
103103
addPage('uploadPage', 'upload.html')
104104
addPage('veryLargeCanvas', 'veryLargeCanvas.html')
105+
addPage('webComponents', 'webComponents.html')
105106
addPage('xhtmlTestPage', 'xhtmlTest.html')
106107
addPage('uploadInvisibleTestPage', 'upload_invisible.html')
107108

0 commit comments

Comments
 (0)