Skip to content

Commit

Permalink
[js] add support for handling Shadow DOM elements
Browse files Browse the repository at this point in the history
  • Loading branch information
AutomatedTester committed Nov 18, 2021
1 parent ec914c6 commit 4e24e99
Show file tree
Hide file tree
Showing 7 changed files with 366 additions and 58 deletions.
5 changes: 5 additions & 0 deletions javascript/node/selenium-webdriver/lib/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ const Name = {
GET_ALERT_TEXT: 'getAlertText',
SET_ALERT_TEXT: 'setAlertValue',

// Shadow DOM Commands
GET_SHADOW_ROOT: 'getShadowRoot',
FIND_ELEMENT_FROM_SHADOWROOT: 'findElementFromShadowRoot',
FIND_ELEMENTS_FROM_SHADOWROOT: 'findElementsFromShadowRoot',

GET_AVAILABLE_LOG_TYPES: 'getAvailableLogTypes',
GET_LOG: 'getLog',
GET_SESSION_LOGS: 'getSessionLogs',
Expand Down
24 changes: 24 additions & 0 deletions javascript/node/selenium-webdriver/lib/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ class WebDriverError extends Error {
}
}

/**
* Indicates the shadow root is no longer attached to the DOM
*/
class DetachedShadowRootError extends WebDriverError {
/** @param {string=} opt_error the error message, if any. */
constructor(opt_error) {
super(opt_error)
}
}

/**
* Indicates a {@linkplain ./webdriver.WebElement#click click command} could not
* completed because the click target is obscured by other elements on the
Expand Down Expand Up @@ -201,6 +211,16 @@ class NoSuchElementError extends WebDriverError {
}
}

/**
* A ShadowRoot could not be located on the element
*/
class NoSuchShadowRootError extends WebDriverError {
/** @param {string=} opt_error the error message, if any. */
constructor(opt_error) {
super(opt_error);
}
}

/**
* A request to switch to a frame could not be satisfied because the frame
* could not be found.
Expand Down Expand Up @@ -420,6 +440,7 @@ const LEGACY_ERROR_CODE_TO_TYPE = new Map([

const ERROR_CODE_TO_TYPE = new Map([
['unknown error', WebDriverError],
['detached shadow root', DetachedShadowRootError],
['element click intercepted', ElementClickInterceptedError],
['element not interactable', ElementNotInteractableError],
['element not selectable', ElementNotSelectableError],
Expand All @@ -436,6 +457,7 @@ const ERROR_CODE_TO_TYPE = new Map([
['no such cookie', NoSuchCookieError],
['no such element', NoSuchElementError],
['no such frame', NoSuchFrameError],
['no such shadow root', NoSuchShadowRootError],
['no such window', NoSuchWindowError],
['script timeout', ScriptTimeoutError],
['session not created', SessionNotCreatedError],
Expand Down Expand Up @@ -569,6 +591,7 @@ module.exports = {
ErrorCode,

WebDriverError,
DetachedShadowRootError,
ElementClickInterceptedError,
ElementNotInteractableError,
ElementNotSelectableError,
Expand All @@ -584,6 +607,7 @@ module.exports = {
NoSuchCookieError,
NoSuchElementError,
NoSuchFrameError,
NoSuchShadowRootError,
NoSuchSessionError,
NoSuchWindowError,
ScriptTimeoutError,
Expand Down
16 changes: 10 additions & 6 deletions javascript/node/selenium-webdriver/lib/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const error = require('./error')
const logging = require('./logging')
const promise = require('./promise')
const { Session } = require('./session')
const { WebElement } = require('./webdriver')
const { WebElement, ShadowRoot } = require('./webdriver')

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

class InternalTypeError extends TypeError {}
class InternalTypeError extends TypeError { }

/**
* @param {!cmd.Command} command The initial command.
Expand Down Expand Up @@ -421,6 +421,10 @@ const W3C_COMMAND_MAP = new Map([
],
// print page.
[cmd.Name.PRINT_PAGE, post('/session/:sessionId/print')],
// Shadow Root
[cmd.Name.GET_SHADOW_ROOT, get('/session/:sessionId/element/:id/shadow')],
[cmd.Name.FIND_ELEMENT_FROM_SHADOWROOT, post('/session/:sessionId/shadow/:id/element')],
[cmd.Name.FIND_ELEMENTS_FROM_SHADOWROOT, post('/session/:sessionId/shadow/:id/elements')],
// Log extensions.
[cmd.Name.GET_LOG, post('/session/:sessionId/se/log')],
[cmd.Name.GET_AVAILABLE_LOG_TYPES, get('/session/:sessionId/se/log/types')],
Expand All @@ -441,7 +445,7 @@ class Client {
* @return {!Promise<Response>} A promise that will be fulfilled with the
* server's response.
*/
send(httpRequest) {} // eslint-disable-line
send(httpRequest) { } // eslint-disable-line
}

/**
Expand Down Expand Up @@ -584,7 +588,7 @@ class Executor {
// No implementations use the `capabilities` key yet...
let capabilities = value.capabilities || value.value
return new Session(
/** @type {{sessionId: string}} */ (value).sessionId,
/** @type {{sessionId: string}} */(value).sessionId,
capabilities
)
}
Expand Down
1 change: 1 addition & 0 deletions javascript/node/selenium-webdriver/lib/test/fileserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ const Pages = (function () {
addPage('unicodeLtrPage', 'utf8/unicode_ltr.html')
addPage('uploadPage', 'upload.html')
addPage('veryLargeCanvas', 'veryLargeCanvas.html')
addPage('webComponents', 'webComponents.html')
addPage('xhtmlTestPage', 'xhtmlTest.html')
addPage('uploadInvisibleTestPage', 'upload_invisible.html')

Expand Down
Loading

0 comments on commit 4e24e99

Please sign in to comment.