123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598 |
- // Licensed to the Software Freedom Conservancy (SFC) under one
- // or more contributor license agreements. See the NOTICE file
- // distributed with this work for additional information
- // regarding copyright ownership. The SFC licenses this file
- // to you under the Apache License, Version 2.0 (the
- // "License"); you may not use this file except in compliance
- // with the License. You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing,
- // software distributed under the License is distributed on an
- // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- // KIND, either express or implied. See the License for the
- // specific language governing permissions and limitations
- // under the License.
- 'use strict';
- /**
- * The base WebDriver error type. This error type is only used directly when a
- * more appropriate category is not defined for the offending error.
- */
- class WebDriverError extends Error {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- /** @override */
- this.name = this.constructor.name;
- /**
- * A stacktrace reported by the remote webdriver endpoint that initially
- * reported this error. This property will be an empty string if the remote
- * end did not provide a stacktrace.
- * @type {string}
- */
- this.remoteStacktrace = '';
- }
- }
- /**
- * An attempt was made to select an element that cannot be selected.
- */
- class ElementNotSelectableError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * Indicates a command could not be completed because the target element is
- * not pointer or keyboard interactable. This will often occur if an element
- * is present in the DOM, but not rendered (i.e. its CSS style has
- * "display: none").
- */
- class ElementNotInteractableError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * An element command could not be completed because the element is not visible
- * on the page.
- *
- * @deprecated Use {@link ElementNotInteractable} instead.
- */
- class ElementNotVisibleError extends ElementNotInteractableError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * The arguments passed to a command are either invalid or malformed.
- */
- class InvalidArgumentError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * An illegal attempt was made to set a cookie under a different domain than
- * the current page.
- */
- class InvalidCookieDomainError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * The coordinates provided to an interactions operation are invalid.
- */
- class InvalidElementCoordinatesError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * An element command could not be completed because the element is in an
- * invalid state, e.g. attempting to click an element that is no longer attached
- * to the document.
- */
- class InvalidElementStateError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * Argument was an invalid selector.
- */
- class InvalidSelectorError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * Occurs when a command is directed to a session that does not exist.
- */
- class NoSuchSessionError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * An error occurred while executing JavaScript supplied by the user.
- */
- class JavascriptError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * The target for mouse interaction is not in the browser’s viewport and cannot
- * be brought into that viewport.
- */
- class MoveTargetOutOfBoundsError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * An attempt was made to operate on a modal dialog when one was not open.
- */
- class NoSuchAlertError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * An element could not be located on the page using the given search
- * parameters.
- */
- class NoSuchElementError 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.
- */
- class NoSuchFrameError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * A request to switch to a window could not be satisfied because the window
- * could not be found.
- */
- class NoSuchWindowError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * A script did not complete before its timeout expired.
- */
- class ScriptTimeoutError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * A new session could not be created.
- */
- class SessionNotCreatedError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * An element command failed because the referenced element is no longer
- * attached to the DOM.
- */
- class StaleElementReferenceError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * An operation did not complete before its timeout expired.
- */
- class TimeoutError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * A request to set a cookie’s value could not be satisfied.
- */
- class UnableToSetCookieError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * A screen capture operation was not possible.
- */
- class UnableToCaptureScreenError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * A modal dialog was open, blocking this operation.
- */
- class UnexpectedAlertOpenError extends WebDriverError {
- /**
- * @param {string=} opt_error the error message, if any.
- * @param {string=} opt_text the text of the open dialog, if available.
- */
- constructor(opt_error, opt_text) {
- super(opt_error);
- /** @private {(string|undefined)} */
- this.text_ = opt_text;
- }
- /**
- * @return {(string|undefined)} The text displayed with the unhandled alert,
- * if available.
- */
- getAlertText() {
- return this.text_;
- }
- }
- /**
- * A command could not be executed because the remote end is not aware of it.
- */
- class UnknownCommandError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * The requested command matched a known URL but did not match an method for
- * that URL.
- */
- class UnknownMethodError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- /**
- * Reports an unsupported operation.
- */
- class UnsupportedOperationError extends WebDriverError {
- /** @param {string=} opt_error the error message, if any. */
- constructor(opt_error) {
- super(opt_error);
- }
- }
- // TODO(jleyba): Define UnknownError as an alias of WebDriverError?
- /**
- * Enum of legacy error codes.
- * TODO: remove this when all code paths have been switched to the new error
- * types.
- * @deprecated
- * @enum {number}
- */
- const ErrorCode = {
- SUCCESS: 0,
- NO_SUCH_ELEMENT: 7,
- NO_SUCH_FRAME: 8,
- UNKNOWN_COMMAND: 9,
- UNSUPPORTED_OPERATION: 9,
- STALE_ELEMENT_REFERENCE: 10,
- ELEMENT_NOT_VISIBLE: 11,
- INVALID_ELEMENT_STATE: 12,
- UNKNOWN_ERROR: 13,
- ELEMENT_NOT_SELECTABLE: 15,
- JAVASCRIPT_ERROR: 17,
- XPATH_LOOKUP_ERROR: 19,
- TIMEOUT: 21,
- NO_SUCH_WINDOW: 23,
- INVALID_COOKIE_DOMAIN: 24,
- UNABLE_TO_SET_COOKIE: 25,
- UNEXPECTED_ALERT_OPEN: 26,
- NO_SUCH_ALERT: 27,
- SCRIPT_TIMEOUT: 28,
- INVALID_ELEMENT_COORDINATES: 29,
- IME_NOT_AVAILABLE: 30,
- IME_ENGINE_ACTIVATION_FAILED: 31,
- INVALID_SELECTOR_ERROR: 32,
- SESSION_NOT_CREATED: 33,
- MOVE_TARGET_OUT_OF_BOUNDS: 34,
- SQL_DATABASE_ERROR: 35,
- INVALID_XPATH_SELECTOR: 51,
- INVALID_XPATH_SELECTOR_RETURN_TYPE: 52,
- METHOD_NOT_ALLOWED: 405
- };
- const LEGACY_ERROR_CODE_TO_TYPE = new Map([
- [ErrorCode.NO_SUCH_ELEMENT, NoSuchElementError],
- [ErrorCode.NO_SUCH_FRAME, NoSuchFrameError],
- [ErrorCode.UNSUPPORTED_OPERATION, UnsupportedOperationError],
- [ErrorCode.STALE_ELEMENT_REFERENCE, StaleElementReferenceError],
- [ErrorCode.ELEMENT_NOT_VISIBLE, ElementNotVisibleError],
- [ErrorCode.INVALID_ELEMENT_STATE, InvalidElementStateError],
- [ErrorCode.UNKNOWN_ERROR, WebDriverError],
- [ErrorCode.ELEMENT_NOT_SELECTABLE, ElementNotSelectableError],
- [ErrorCode.JAVASCRIPT_ERROR, JavascriptError],
- [ErrorCode.XPATH_LOOKUP_ERROR, InvalidSelectorError],
- [ErrorCode.TIMEOUT, TimeoutError],
- [ErrorCode.NO_SUCH_WINDOW, NoSuchWindowError],
- [ErrorCode.INVALID_COOKIE_DOMAIN, InvalidCookieDomainError],
- [ErrorCode.UNABLE_TO_SET_COOKIE, UnableToSetCookieError],
- [ErrorCode.UNEXPECTED_ALERT_OPEN, UnexpectedAlertOpenError],
- [ErrorCode.NO_SUCH_ALERT, NoSuchAlertError],
- [ErrorCode.SCRIPT_TIMEOUT, ScriptTimeoutError],
- [ErrorCode.INVALID_ELEMENT_COORDINATES, InvalidElementCoordinatesError],
- [ErrorCode.INVALID_SELECTOR_ERROR, InvalidSelectorError],
- [ErrorCode.SESSION_NOT_CREATED, SessionNotCreatedError],
- [ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS, MoveTargetOutOfBoundsError],
- [ErrorCode.INVALID_XPATH_SELECTOR, InvalidSelectorError],
- [ErrorCode.INVALID_XPATH_SELECTOR_RETURN_TYPE, InvalidSelectorError],
- [ErrorCode.METHOD_NOT_ALLOWED, UnsupportedOperationError]]);
- const ERROR_CODE_TO_TYPE = new Map([
- ['unknown error', WebDriverError],
- ['element not interactable', ElementNotInteractableError],
- ['element not selectable', ElementNotSelectableError],
- ['element not visible', ElementNotVisibleError],
- ['invalid argument', InvalidArgumentError],
- ['invalid cookie domain', InvalidCookieDomainError],
- ['invalid element coordinates', InvalidElementCoordinatesError],
- ['invalid element state', InvalidElementStateError],
- ['invalid selector', InvalidSelectorError],
- ['invalid session id', NoSuchSessionError],
- ['javascript error', JavascriptError],
- ['move target out of bounds', MoveTargetOutOfBoundsError],
- ['no such alert', NoSuchAlertError],
- ['no such element', NoSuchElementError],
- ['no such frame', NoSuchFrameError],
- ['no such window', NoSuchWindowError],
- ['script timeout', ScriptTimeoutError],
- ['session not created', SessionNotCreatedError],
- ['stale element reference', StaleElementReferenceError],
- ['timeout', TimeoutError],
- ['unable to set cookie', UnableToSetCookieError],
- ['unable to capture screen', UnableToCaptureScreenError],
- ['unexpected alert open', UnexpectedAlertOpenError],
- ['unknown command', UnknownCommandError],
- ['unknown method', UnknownMethodError],
- ['unsupported operation', UnsupportedOperationError]]);
- const TYPE_TO_ERROR_CODE = new Map;
- ERROR_CODE_TO_TYPE.forEach((value, key) => {
- TYPE_TO_ERROR_CODE.set(value, key);
- });
- /**
- * @param {*} err The error to encode.
- * @return {{error: string, message: string}} the encoded error.
- */
- function encodeError(err) {
- let type = WebDriverError;
- if (err instanceof WebDriverError
- && TYPE_TO_ERROR_CODE.has(err.constructor)) {
- type = err.constructor;
- }
- let message = err instanceof Error
- ? err.message
- : err + '';
- let code = /** @type {string} */(TYPE_TO_ERROR_CODE.get(type));
- return {'error': code, 'message': message};
- }
- /**
- * Checks a response object from a server that adheres to the W3C WebDriver
- * protocol.
- * @param {*} data The response data to check.
- * @return {*} The response data if it was not an encoded error.
- * @throws {WebDriverError} the decoded error, if present in the data object.
- * @deprecated Use {@link #throwDecodedError(data)} instead.
- * @see https://w3c.github.io/webdriver/webdriver-spec.html#protocol
- */
- function checkResponse(data) {
- if (data && typeof data.error === 'string') {
- let ctor = ERROR_CODE_TO_TYPE.get(data.error) || WebDriverError;
- throw new ctor(data.message);
- }
- return data;
- }
- /**
- * Tests if the given value is a valid error response object according to the
- * W3C WebDriver spec.
- *
- * @param {?} data The value to test.
- * @return {boolean} Whether the given value data object is a valid error
- * response.
- * @see https://w3c.github.io/webdriver/webdriver-spec.html#protocol
- */
- function isErrorResponse(data) {
- return data && typeof data === 'object' && typeof data.error === 'string';
- }
- /**
- * Throws an error coded from the W3C protocol. A generic error will be thrown
- * if the provided `data` is not a valid encoded error.
- *
- * @param {{error: string, message: string}} data The error data to decode.
- * @throws {WebDriverError} the decoded error.
- * @see https://w3c.github.io/webdriver/webdriver-spec.html#protocol
- */
- function throwDecodedError(data) {
- if (isErrorResponse(data)) {
- let ctor = ERROR_CODE_TO_TYPE.get(data.error) || WebDriverError;
- let err = new ctor(data.message);
- if (typeof data.stacktrace === 'string') {
- err.remoteStacktrace = data.stacktrace;
- }
- throw err;
- }
- throw new WebDriverError('Unknown error: ' + JSON.stringify(data));
- }
- /**
- * Checks a legacy response from the Selenium 2.0 wire protocol for an error.
- * @param {*} responseObj the response object to check.
- * @return {*} responseObj the original response if it does not define an error.
- * @throws {WebDriverError} if the response object defines an error.
- */
- function checkLegacyResponse(responseObj) {
- // Handle the legacy Selenium error response format.
- if (responseObj
- && typeof responseObj === 'object'
- && typeof responseObj['status'] === 'number'
- && responseObj['status'] !== 0) {
- let status = responseObj['status'];
- let ctor = LEGACY_ERROR_CODE_TO_TYPE.get(status) || WebDriverError;
- let value = responseObj['value'];
- if (!value || typeof value !== 'object') {
- throw new ctor(value + '');
- } else {
- let message = value['message'] + '';
- if (ctor !== UnexpectedAlertOpenError) {
- throw new ctor(message);
- }
- let text = '';
- if (value['alert'] && typeof value['alert']['text'] === 'string') {
- text = value['alert']['text'];
- }
- throw new UnexpectedAlertOpenError(message, text);
- }
- }
- return responseObj;
- }
- // PUBLIC API
- module.exports = {
- ErrorCode: ErrorCode,
- WebDriverError: WebDriverError,
- ElementNotInteractableError: ElementNotInteractableError,
- ElementNotSelectableError: ElementNotSelectableError,
- ElementNotVisibleError: ElementNotVisibleError,
- InvalidArgumentError: InvalidArgumentError,
- InvalidCookieDomainError: InvalidCookieDomainError,
- InvalidElementCoordinatesError: InvalidElementCoordinatesError,
- InvalidElementStateError: InvalidElementStateError,
- InvalidSelectorError: InvalidSelectorError,
- JavascriptError: JavascriptError,
- MoveTargetOutOfBoundsError: MoveTargetOutOfBoundsError,
- NoSuchAlertError: NoSuchAlertError,
- NoSuchElementError: NoSuchElementError,
- NoSuchFrameError: NoSuchFrameError,
- NoSuchSessionError: NoSuchSessionError,
- NoSuchWindowError: NoSuchWindowError,
- ScriptTimeoutError: ScriptTimeoutError,
- SessionNotCreatedError: SessionNotCreatedError,
- StaleElementReferenceError: StaleElementReferenceError,
- TimeoutError: TimeoutError,
- UnableToSetCookieError: UnableToSetCookieError,
- UnableToCaptureScreenError: UnableToCaptureScreenError,
- UnexpectedAlertOpenError: UnexpectedAlertOpenError,
- UnknownCommandError: UnknownCommandError,
- UnknownMethodError: UnknownMethodError,
- UnsupportedOperationError: UnsupportedOperationError,
- checkResponse: checkResponse,
- checkLegacyResponse: checkLegacyResponse,
- encodeError: encodeError,
- isErrorResponse: isErrorResponse,
- throwDecodedError: throwDecodedError,
- };
|