webdriverio 9.16.2 → 9.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/commands/browser/debug.d.ts.map +1 -1
- package/build/commands/browser/switchFrame.d.ts.map +1 -1
- package/build/commands/browser/url.d.ts +6 -0
- package/build/commands/browser/url.d.ts.map +1 -1
- package/build/commands/constant.d.ts.map +1 -1
- package/build/commands/element/getHTML.d.ts +8 -0
- package/build/commands/element/getHTML.d.ts.map +1 -1
- package/build/commands/element.d.ts +1 -1
- package/build/commands/element.d.ts.map +1 -1
- package/build/environment.d.ts +5 -0
- package/build/environment.d.ts.map +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +347 -320
- package/build/middlewares.d.ts.map +1 -1
- package/build/node.d.ts.map +1 -1
- package/build/node.js +386 -357
- package/build/scripts/resq.d.ts.map +1 -1
- package/build/scripts/shadowFnFactory.d.ts.map +1 -1
- package/build/session/context.d.ts.map +1 -1
- package/build/session/session.d.ts.map +1 -1
- package/build/utils/Timer.d.ts.map +1 -1
- package/build/utils/findStrategy.d.ts.map +1 -1
- package/build/utils/getElementObject.d.ts.map +1 -1
- package/build/utils/index.d.ts.map +1 -1
- package/package.json +10 -10
package/build/index.js
CHANGED
|
@@ -42,8 +42,8 @@ import logger from "@wdio/logger";
|
|
|
42
42
|
import { getBrowserObject } from "@wdio/utils";
|
|
43
43
|
var log = logger("webdriverio");
|
|
44
44
|
async function implicitWait(currentElement, commandName) {
|
|
45
|
-
const
|
|
46
|
-
const skipForMobileScroll =
|
|
45
|
+
const browser = getBrowserObject(currentElement);
|
|
46
|
+
const skipForMobileScroll = browser.isMobile && await browser.isNativeContext && (commandName === "scrollIntoView" || commandName === "tap");
|
|
47
47
|
if (!currentElement.elementId && !/(waitUntil|waitFor|isExisting|is?\w+Displayed|is?\w+Clickable)/.test(commandName) && !skipForMobileScroll) {
|
|
48
48
|
log.debug(
|
|
49
49
|
"command ".concat(commandName, ' was called on an element ("').concat(currentElement.selector, '") ') + "that wasn't found, waiting for it..."
|
|
@@ -176,13 +176,13 @@ var WebDriverError = class extends Error {
|
|
|
176
176
|
}
|
|
177
177
|
};
|
|
178
178
|
function getElement(selector, res, props = { isReactElement: false, isShadowElement: false }) {
|
|
179
|
-
const
|
|
179
|
+
const browser = getBrowserObject2(this);
|
|
180
180
|
const browserCommandKeys = Object.keys(browser_exports);
|
|
181
181
|
const propertiesObject = {
|
|
182
182
|
/**
|
|
183
183
|
* filter out browser commands from object
|
|
184
184
|
*/
|
|
185
|
-
...Object.entries(clone(
|
|
185
|
+
...Object.entries(clone(browser.__propertiesObject__)).reduce((commands, [name, descriptor]) => {
|
|
186
186
|
if (!browserCommandKeys.includes(name)) {
|
|
187
187
|
commands[name] = descriptor;
|
|
188
188
|
}
|
|
@@ -214,19 +214,19 @@ function getElement(selector, res, props = { isReactElement: false, isShadowElem
|
|
|
214
214
|
const elementInstance = element(this.sessionId, elementErrorHandler(wrapCommand));
|
|
215
215
|
const origAddCommand = elementInstance.addCommand.bind(elementInstance);
|
|
216
216
|
elementInstance.addCommand = (name, fn) => {
|
|
217
|
-
|
|
217
|
+
browser.__propertiesObject__[name] = { value: fn };
|
|
218
218
|
origAddCommand(name, fn);
|
|
219
219
|
};
|
|
220
220
|
return elementInstance;
|
|
221
221
|
}
|
|
222
222
|
var getElements = function getElements2(selector, elemResponse, props = { isReactElement: false, isShadowElement: false }) {
|
|
223
|
-
const
|
|
223
|
+
const browser = getBrowserObject2(this);
|
|
224
224
|
const browserCommandKeys = Object.keys(browser_exports);
|
|
225
225
|
const propertiesObject = {
|
|
226
226
|
/**
|
|
227
227
|
* filter out browser commands from object
|
|
228
228
|
*/
|
|
229
|
-
...Object.entries(clone(
|
|
229
|
+
...Object.entries(clone(browser.__propertiesObject__)).reduce((commands, [name, descriptor]) => {
|
|
230
230
|
if (!browserCommandKeys.includes(name)) {
|
|
231
231
|
commands[name] = descriptor;
|
|
232
232
|
}
|
|
@@ -265,7 +265,7 @@ var getElements = function getElements2(selector, elemResponse, props = { isReac
|
|
|
265
265
|
const elementInstance = element(this.sessionId, elementErrorHandler(wrapCommand));
|
|
266
266
|
const origAddCommand = elementInstance.addCommand.bind(elementInstance);
|
|
267
267
|
elementInstance.addCommand = (name, fn) => {
|
|
268
|
-
|
|
268
|
+
browser.__propertiesObject__[name] = { value: fn };
|
|
269
269
|
origAddCommand(name, fn);
|
|
270
270
|
};
|
|
271
271
|
return elementInstance;
|
|
@@ -546,6 +546,9 @@ var environment = {
|
|
|
546
546
|
},
|
|
547
547
|
get osType() {
|
|
548
548
|
return () => "browser";
|
|
549
|
+
},
|
|
550
|
+
get variables() {
|
|
551
|
+
return isNode ? process.env : {};
|
|
549
552
|
}
|
|
550
553
|
}
|
|
551
554
|
};
|
|
@@ -1059,7 +1062,8 @@ import WDIORepl from "@wdio/repl";
|
|
|
1059
1062
|
function debug(commandTimeout = 5e3) {
|
|
1060
1063
|
const repl = new WDIORepl();
|
|
1061
1064
|
const { introMessage } = WDIORepl;
|
|
1062
|
-
|
|
1065
|
+
const process2 = globalThis.process;
|
|
1066
|
+
if (!environment.value.variables.WDIO_WORKER_ID || typeof process2.send !== "function") {
|
|
1063
1067
|
console.log(WDIORepl.introMessage);
|
|
1064
1068
|
const context = {
|
|
1065
1069
|
browser: this,
|
|
@@ -1069,8 +1073,8 @@ function debug(commandTimeout = 5e3) {
|
|
|
1069
1073
|
};
|
|
1070
1074
|
return repl.start(context);
|
|
1071
1075
|
}
|
|
1072
|
-
|
|
1073
|
-
|
|
1076
|
+
process2._debugProcess(process2.pid);
|
|
1077
|
+
process2.send({
|
|
1074
1078
|
origin: "debugger",
|
|
1075
1079
|
name: "start",
|
|
1076
1080
|
params: { commandTimeout, introMessage }
|
|
@@ -1080,21 +1084,21 @@ function debug(commandTimeout = 5e3) {
|
|
|
1080
1084
|
() => {
|
|
1081
1085
|
}
|
|
1082
1086
|
);
|
|
1083
|
-
|
|
1087
|
+
process2.on("message", (m) => {
|
|
1084
1088
|
if (m.origin !== "debugger") {
|
|
1085
1089
|
return;
|
|
1086
1090
|
}
|
|
1087
1091
|
if (m.name === "stop") {
|
|
1088
|
-
|
|
1092
|
+
process2._debugEnd(process2.pid);
|
|
1089
1093
|
return commandResolve();
|
|
1090
1094
|
}
|
|
1091
1095
|
if (m.name === "eval") {
|
|
1092
1096
|
repl.eval(m.content.cmd, global, void 0, (err, result) => {
|
|
1093
|
-
if (typeof
|
|
1097
|
+
if (typeof process2.send !== "function") {
|
|
1094
1098
|
return;
|
|
1095
1099
|
}
|
|
1096
1100
|
if (err) {
|
|
1097
|
-
|
|
1101
|
+
process2.send({
|
|
1098
1102
|
origin: "debugger",
|
|
1099
1103
|
name: "result",
|
|
1100
1104
|
params: {
|
|
@@ -1106,7 +1110,7 @@ function debug(commandTimeout = 5e3) {
|
|
|
1106
1110
|
if (typeof result === "function") {
|
|
1107
1111
|
result = "[Function: ".concat(result.name, "]");
|
|
1108
1112
|
}
|
|
1109
|
-
|
|
1113
|
+
process2.send({
|
|
1110
1114
|
origin: "debugger",
|
|
1111
1115
|
name: "result",
|
|
1112
1116
|
params: { result }
|
|
@@ -1181,11 +1185,11 @@ function uninstallFakeTimers() {
|
|
|
1181
1185
|
var fakerScript = 'function FakeTimers () {\n/*\n * Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no. All rights reserved.\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/**\n * @typedef {object} IdleDeadline\n * @property {boolean} didTimeout - whether or not the callback was called before reaching the optional timeout\n * @property {function():number} timeRemaining - a floating-point value providing an estimate of the number of milliseconds remaining in the current idle period\n */\n\n/**\n * Queues a function to be called during a browser\'s idle periods\n *\n * @callback RequestIdleCallback\n * @param {function(IdleDeadline)} callback\n * @param {{timeout: number}} options - an options object\n * @returns {number} the id\n */\n\n/**\n * @callback NextTick\n * @param {VoidVarArgsFunc} callback - the callback to run\n * @param {...*} args - optional arguments to call the callback with\n * @returns {void}\n */\n\n/**\n * @callback SetImmediate\n * @param {VoidVarArgsFunc} callback - the callback to run\n * @param {...*} args - optional arguments to call the callback with\n * @returns {NodeImmediate}\n */\n\n/**\n * @callback VoidVarArgsFunc\n * @param {...*} callback - the callback to run\n * @returns {void}\n */\n\n/**\n * @typedef RequestAnimationFrame\n * @property {function(number):void} requestAnimationFrame\n * @returns {number} - the id\n */\n\n/**\n * @typedef Performance\n * @property {function(): number} now\n */\n\n/* eslint-disable jsdoc/require-property-description */\n/**\n * @typedef {object} Clock\n * @property {number} now - the current time\n * @property {Date} Date - the Date constructor\n * @property {number} loopLimit - the maximum number of timers before assuming an infinite loop\n * @property {RequestIdleCallback} requestIdleCallback\n * @property {function(number):void} cancelIdleCallback\n * @property {setTimeout} setTimeout\n * @property {clearTimeout} clearTimeout\n * @property {NextTick} nextTick\n * @property {queueMicrotask} queueMicrotask\n * @property {setInterval} setInterval\n * @property {clearInterval} clearInterval\n * @property {SetImmediate} setImmediate\n * @property {function(NodeImmediate):void} clearImmediate\n * @property {function():number} countTimers\n * @property {RequestAnimationFrame} requestAnimationFrame\n * @property {function(number):void} cancelAnimationFrame\n * @property {function():void} runMicrotasks\n * @property {function(string | number): number} tick\n * @property {function(string | number): Promise<number>} tickAsync\n * @property {function(): number} next\n * @property {function(): Promise<number>} nextAsync\n * @property {function(): number} runAll\n * @property {function(): number} runToFrame\n * @property {function(): Promise<number>} runAllAsync\n * @property {function(): number} runToLast\n * @property {function(): Promise<number>} runToLastAsync\n * @property {function(): void} reset\n * @property {function(number | Date): void} setSystemTime\n * @property {function(number): void} jump\n * @property {Performance} performance\n * @property {function(number[]): number[]} hrtime - process.hrtime (legacy)\n * @property {function(): void} uninstall Uninstall the clock.\n * @property {Function[]} methods - the methods that are faked\n * @property {boolean} [shouldClearNativeTimers] inherited from config\n * @property {{methodName:string, original:any}[] | undefined} timersModuleMethods\n */\n/* eslint-enable jsdoc/require-property-description */\n\n/**\n * Configuration object for the `install` method.\n *\n * @typedef {object} Config\n * @property {number|Date} [now] a number (in milliseconds) or a Date object (default epoch)\n * @property {string[]} [toFake] names of the methods that should be faked.\n * @property {number} [loopLimit] the maximum number of timers that will be run when calling runAll()\n * @property {boolean} [shouldAdvanceTime] tells FakeTimers to increment mocked time automatically (default false)\n * @property {number} [advanceTimeDelta] increment mocked time every <<advanceTimeDelta>> ms (default: 20ms)\n * @property {boolean} [shouldClearNativeTimers] forwards clear timer calls to native functions if they are not fakes (default: false)\n */\n\n/* eslint-disable jsdoc/require-property-description */\n/**\n * The internal structure to describe a scheduled fake timer\n *\n * @typedef {object} Timer\n * @property {Function} func\n * @property {*[]} args\n * @property {number} delay\n * @property {number} callAt\n * @property {number} createdAt\n * @property {boolean} immediate\n * @property {number} id\n * @property {Error} [error]\n */\n\n/**\n * A Node timer\n *\n * @typedef {object} NodeImmediate\n * @property {function(): boolean} hasRef\n * @property {function(): NodeImmediate} ref\n * @property {function(): NodeImmediate} unref\n */\n/* eslint-enable jsdoc/require-property-description */\n\n/**\n * Mocks available features in the specified global namespace.\n *\n * @param {*} _global Namespace to mock (e.g. `window`)\n * @returns {FakeTimers}\n */\nfunction withGlobal(_global) {\n const maxTimeout = Math.pow(2, 31) - 1; //see https://heycam.github.io/webidl/#abstract-opdef-converttoint\n const idCounterStart = 1e12; // arbitrarily large number to avoid collisions with native timer IDs\n const NOOP = function () {\n return undefined;\n };\n const NOOP_ARRAY = function () {\n return [];\n };\n const timeoutResult = _global.setTimeout(NOOP, 0);\n const addTimerReturnsObject = typeof timeoutResult === "object";\n const hrtimePresent =\n _global.process && typeof _global.process.hrtime === "function";\n const hrtimeBigintPresent =\n hrtimePresent && typeof _global.process.hrtime.bigint === "function";\n const nextTickPresent =\n _global.process && typeof _global.process.nextTick === "function";\n const utilPromisify = _global.process && require("util").promisify;\n const performancePresent =\n _global.performance && typeof _global.performance.now === "function";\n const hasPerformancePrototype =\n _global.Performance &&\n (typeof _global.Performance).match(/^(function|object)$/);\n const hasPerformanceConstructorPrototype =\n _global.performance &&\n _global.performance.constructor &&\n _global.performance.constructor.prototype;\n const queueMicrotaskPresent = _global.hasOwnProperty("queueMicrotask");\n const requestAnimationFramePresent =\n _global.requestAnimationFrame &&\n typeof _global.requestAnimationFrame === "function";\n const cancelAnimationFramePresent =\n _global.cancelAnimationFrame &&\n typeof _global.cancelAnimationFrame === "function";\n const requestIdleCallbackPresent =\n _global.requestIdleCallback &&\n typeof _global.requestIdleCallback === "function";\n const cancelIdleCallbackPresent =\n _global.cancelIdleCallback &&\n typeof _global.cancelIdleCallback === "function";\n const setImmediatePresent =\n _global.setImmediate && typeof _global.setImmediate === "function";\n const intlPresent = _global.Intl && typeof _global.Intl === "object";\n\n _global.clearTimeout(timeoutResult);\n\n const NativeDate = _global.Date;\n const NativeIntl = _global.Intl;\n let uniqueTimerId = idCounterStart;\n\n /**\n * @param {number} num\n * @returns {boolean}\n */\n function isNumberFinite(num) {\n if (Number.isFinite) {\n return Number.isFinite(num);\n }\n\n return isFinite(num);\n }\n\n let isNearInfiniteLimit = false;\n\n /**\n * @param {Clock} clock\n * @param {number} i\n */\n function checkIsNearInfiniteLimit(clock, i) {\n if (clock.loopLimit && i === clock.loopLimit - 1) {\n isNearInfiniteLimit = true;\n }\n }\n\n /**\n *\n */\n function resetIsNearInfiniteLimit() {\n isNearInfiniteLimit = false;\n }\n\n /**\n * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into\n * number of milliseconds. This is used to support human-readable strings passed\n * to clock.tick()\n *\n * @param {string} str\n * @returns {number}\n */\n function parseTime(str) {\n if (!str) {\n return 0;\n }\n\n const strings = str.split(":");\n const l = strings.length;\n let i = l;\n let ms = 0;\n let parsed;\n\n if (l > 3 || !/^(\\d\\d:){0,2}\\d\\d?$/.test(str)) {\n throw new Error(\n "tick only understands numbers, \'m:s\' and \'h:m:s\'. Each part must be two digits",\n );\n }\n\n while (i--) {\n parsed = parseInt(strings[i], 10);\n\n if (parsed >= 60) {\n throw new Error(`Invalid time ${str}`);\n }\n\n ms += parsed * Math.pow(60, l - i - 1);\n }\n\n return ms * 1000;\n }\n\n /**\n * Get the decimal part of the millisecond value as nanoseconds\n *\n * @param {number} msFloat the number of milliseconds\n * @returns {number} an integer number of nanoseconds in the range [0,1e6)\n *\n * Example: nanoRemainer(123.456789) -> 456789\n */\n function nanoRemainder(msFloat) {\n const modulo = 1e6;\n const remainder = (msFloat * 1e6) % modulo;\n const positiveRemainder =\n remainder < 0 ? remainder + modulo : remainder;\n\n return Math.floor(positiveRemainder);\n }\n\n /**\n * Used to grok the `now` parameter to createClock.\n *\n * @param {Date|number} epoch the system time\n * @returns {number}\n */\n function getEpoch(epoch) {\n if (!epoch) {\n return 0;\n }\n if (typeof epoch.getTime === "function") {\n return epoch.getTime();\n }\n if (typeof epoch === "number") {\n return epoch;\n }\n throw new TypeError("now should be milliseconds since UNIX epoch");\n }\n\n /**\n * @param {number} from\n * @param {number} to\n * @param {Timer} timer\n * @returns {boolean}\n */\n function inRange(from, to, timer) {\n return timer && timer.callAt >= from && timer.callAt <= to;\n }\n\n /**\n * @param {Clock} clock\n * @param {Timer} job\n */\n function getInfiniteLoopError(clock, job) {\n const infiniteLoopError = new Error(\n `Aborting after running ${clock.loopLimit} timers, assuming an infinite loop!`,\n );\n\n if (!job.error) {\n return infiniteLoopError;\n }\n\n // pattern never matched in Node\n const computedTargetPattern = /target\\.*[<|(|[].*?[>|\\]|)]\\s*/;\n let clockMethodPattern = new RegExp(\n String(Object.keys(clock).join("|")),\n );\n\n if (addTimerReturnsObject) {\n // node.js environment\n clockMethodPattern = new RegExp(\n `\\\\s+at (Object\\\\.)?(?:${Object.keys(clock).join("|")})\\\\s+`,\n );\n }\n\n let matchedLineIndex = -1;\n job.error.stack.split("\\n").some(function (line, i) {\n // If we\'ve matched a computed target line (e.g. setTimeout) then we\n // don\'t need to look any further. Return true to stop iterating.\n const matchedComputedTarget = line.match(computedTargetPattern);\n /* istanbul ignore if */\n if (matchedComputedTarget) {\n matchedLineIndex = i;\n return true;\n }\n\n // If we\'ve matched a clock method line, then there may still be\n // others further down the trace. Return false to keep iterating.\n const matchedClockMethod = line.match(clockMethodPattern);\n if (matchedClockMethod) {\n matchedLineIndex = i;\n return false;\n }\n\n // If we haven\'t matched anything on this line, but we matched\n // previously and set the matched line index, then we can stop.\n // If we haven\'t matched previously, then we should keep iterating.\n return matchedLineIndex >= 0;\n });\n\n const stack = `${infiniteLoopError}\\n${job.type || "Microtask"} - ${\n job.func.name || "anonymous"\n }\\n${job.error.stack\n .split("\\n")\n .slice(matchedLineIndex + 1)\n .join("\\n")}`;\n\n try {\n Object.defineProperty(infiniteLoopError, "stack", {\n value: stack,\n });\n } catch (e) {\n // noop\n }\n\n return infiniteLoopError;\n }\n\n /**\n * @param {Date} target\n * @param {Date} source\n * @returns {Date} the target after modifications\n */\n function mirrorDateProperties(target, source) {\n let prop;\n for (prop in source) {\n if (source.hasOwnProperty(prop)) {\n target[prop] = source[prop];\n }\n }\n\n // set special now implementation\n if (source.now) {\n target.now = function now() {\n return target.clock.now;\n };\n } else {\n delete target.now;\n }\n\n // set special toSource implementation\n if (source.toSource) {\n target.toSource = function toSource() {\n return source.toSource();\n };\n } else {\n delete target.toSource;\n }\n\n // set special toString implementation\n target.toString = function toString() {\n return source.toString();\n };\n\n target.prototype = source.prototype;\n target.parse = source.parse;\n target.UTC = source.UTC;\n target.prototype.toUTCString = source.prototype.toUTCString;\n target.isFake = true;\n\n return target;\n }\n\n //eslint-disable-next-line jsdoc/require-jsdoc\n function createDate() {\n /**\n * @param {number} year\n * @param {number} month\n * @param {number} date\n * @param {number} hour\n * @param {number} minute\n * @param {number} second\n * @param {number} ms\n * @returns {Date}\n */\n function ClockDate(year, month, date, hour, minute, second, ms) {\n // the Date constructor called as a function, ref Ecma-262 Edition 5.1, section 15.9.2.\n // This remains so in the 10th edition of 2019 as well.\n if (!(this instanceof ClockDate)) {\n return new NativeDate(ClockDate.clock.now).toString();\n }\n\n // if Date is called as a constructor with \'new\' keyword\n // Defensive and verbose to avoid potential harm in passing\n // explicit undefined when user does not pass argument\n switch (arguments.length) {\n case 0:\n return new NativeDate(ClockDate.clock.now);\n case 1:\n return new NativeDate(year);\n case 2:\n return new NativeDate(year, month);\n case 3:\n return new NativeDate(year, month, date);\n case 4:\n return new NativeDate(year, month, date, hour);\n case 5:\n return new NativeDate(year, month, date, hour, minute);\n case 6:\n return new NativeDate(\n year,\n month,\n date,\n hour,\n minute,\n second,\n );\n default:\n return new NativeDate(\n year,\n month,\n date,\n hour,\n minute,\n second,\n ms,\n );\n }\n }\n\n return mirrorDateProperties(ClockDate, NativeDate);\n }\n\n /**\n * Mirror Intl by default on our fake implementation\n *\n * Most of the properties are the original native ones,\n * but we need to take control of those that have a\n * dependency on the current clock.\n *\n * @returns {object} the partly fake Intl implementation\n */\n function createIntl() {\n const ClockIntl = {};\n /*\n * All properties of Intl are non-enumerable, so we need\n * to do a bit of work to get them out.\n */\n Object.getOwnPropertyNames(NativeIntl).forEach(\n (property) => (ClockIntl[property] = NativeIntl[property]),\n );\n\n ClockIntl.DateTimeFormat = function (...args) {\n const realFormatter = new NativeIntl.DateTimeFormat(...args);\n const formatter = {};\n\n ["formatRange", "formatRangeToParts", "resolvedOptions"].forEach(\n (method) => {\n formatter[method] =\n realFormatter[method].bind(realFormatter);\n },\n );\n\n ["format", "formatToParts"].forEach((method) => {\n formatter[method] = function (date) {\n return realFormatter[method](date || ClockIntl.clock.now);\n };\n });\n\n return formatter;\n };\n\n ClockIntl.DateTimeFormat.prototype = Object.create(\n NativeIntl.DateTimeFormat.prototype,\n );\n\n ClockIntl.DateTimeFormat.supportedLocalesOf =\n NativeIntl.DateTimeFormat.supportedLocalesOf;\n\n return ClockIntl;\n }\n\n //eslint-disable-next-line jsdoc/require-jsdoc\n function enqueueJob(clock, job) {\n // enqueues a microtick-deferred task - ecma262/#sec-enqueuejob\n if (!clock.jobs) {\n clock.jobs = [];\n }\n clock.jobs.push(job);\n }\n\n //eslint-disable-next-line jsdoc/require-jsdoc\n function runJobs(clock) {\n // runs all microtick-deferred tasks - ecma262/#sec-runjobs\n if (!clock.jobs) {\n return;\n }\n for (let i = 0; i < clock.jobs.length; i++) {\n const job = clock.jobs[i];\n job.func.apply(null, job.args);\n\n checkIsNearInfiniteLimit(clock, i);\n if (clock.loopLimit && i > clock.loopLimit) {\n throw getInfiniteLoopError(clock, job);\n }\n }\n resetIsNearInfiniteLimit();\n clock.jobs = [];\n }\n\n /**\n * @param {Clock} clock\n * @param {Timer} timer\n * @returns {number} id of the created timer\n */\n function addTimer(clock, timer) {\n if (timer.func === undefined) {\n throw new Error("Callback must be provided to timer calls");\n }\n\n if (addTimerReturnsObject) {\n // Node.js environment\n if (typeof timer.func !== "function") {\n throw new TypeError(\n `[ERR_INVALID_CALLBACK]: Callback must be a function. Received ${\n timer.func\n } of type ${typeof timer.func}`,\n );\n }\n }\n\n if (isNearInfiniteLimit) {\n timer.error = new Error();\n }\n\n timer.type = timer.immediate ? "Immediate" : "Timeout";\n\n if (timer.hasOwnProperty("delay")) {\n if (typeof timer.delay !== "number") {\n timer.delay = parseInt(timer.delay, 10);\n }\n\n if (!isNumberFinite(timer.delay)) {\n timer.delay = 0;\n }\n timer.delay = timer.delay > maxTimeout ? 1 : timer.delay;\n timer.delay = Math.max(0, timer.delay);\n }\n\n if (timer.hasOwnProperty("interval")) {\n timer.type = "Interval";\n timer.interval = timer.interval > maxTimeout ? 1 : timer.interval;\n }\n\n if (timer.hasOwnProperty("animation")) {\n timer.type = "AnimationFrame";\n timer.animation = true;\n }\n\n if (timer.hasOwnProperty("idleCallback")) {\n timer.type = "IdleCallback";\n timer.idleCallback = true;\n }\n\n if (!clock.timers) {\n clock.timers = {};\n }\n\n timer.id = uniqueTimerId++;\n timer.createdAt = clock.now;\n timer.callAt =\n clock.now + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0));\n\n clock.timers[timer.id] = timer;\n\n if (addTimerReturnsObject) {\n const res = {\n refed: true,\n ref: function () {\n this.refed = true;\n return res;\n },\n unref: function () {\n this.refed = false;\n return res;\n },\n hasRef: function () {\n return this.refed;\n },\n refresh: function () {\n timer.callAt =\n clock.now +\n (parseInt(timer.delay) || (clock.duringTick ? 1 : 0));\n\n // it _might_ have been removed, but if not the assignment is perfectly fine\n clock.timers[timer.id] = timer;\n\n return res;\n },\n [Symbol.toPrimitive]: function () {\n return timer.id;\n },\n };\n return res;\n }\n\n return timer.id;\n }\n\n /* eslint consistent-return: "off" */\n /**\n * Timer comparitor\n *\n * @param {Timer} a\n * @param {Timer} b\n * @returns {number}\n */\n function compareTimers(a, b) {\n // Sort first by absolute timing\n if (a.callAt < b.callAt) {\n return -1;\n }\n if (a.callAt > b.callAt) {\n return 1;\n }\n\n // Sort next by immediate, immediate timers take precedence\n if (a.immediate && !b.immediate) {\n return -1;\n }\n if (!a.immediate && b.immediate) {\n return 1;\n }\n\n // Sort next by creation time, earlier-created timers take precedence\n if (a.createdAt < b.createdAt) {\n return -1;\n }\n if (a.createdAt > b.createdAt) {\n return 1;\n }\n\n // Sort next by id, lower-id timers take precedence\n if (a.id < b.id) {\n return -1;\n }\n if (a.id > b.id) {\n return 1;\n }\n\n // As timer ids are unique, no fallback `0` is necessary\n }\n\n /**\n * @param {Clock} clock\n * @param {number} from\n * @param {number} to\n * @returns {Timer}\n */\n function firstTimerInRange(clock, from, to) {\n const timers = clock.timers;\n let timer = null;\n let id, isInRange;\n\n for (id in timers) {\n if (timers.hasOwnProperty(id)) {\n isInRange = inRange(from, to, timers[id]);\n\n if (\n isInRange &&\n (!timer || compareTimers(timer, timers[id]) === 1)\n ) {\n timer = timers[id];\n }\n }\n }\n\n return timer;\n }\n\n /**\n * @param {Clock} clock\n * @returns {Timer}\n */\n function firstTimer(clock) {\n const timers = clock.timers;\n let timer = null;\n let id;\n\n for (id in timers) {\n if (timers.hasOwnProperty(id)) {\n if (!timer || compareTimers(timer, timers[id]) === 1) {\n timer = timers[id];\n }\n }\n }\n\n return timer;\n }\n\n /**\n * @param {Clock} clock\n * @returns {Timer}\n */\n function lastTimer(clock) {\n const timers = clock.timers;\n let timer = null;\n let id;\n\n for (id in timers) {\n if (timers.hasOwnProperty(id)) {\n if (!timer || compareTimers(timer, timers[id]) === -1) {\n timer = timers[id];\n }\n }\n }\n\n return timer;\n }\n\n /**\n * @param {Clock} clock\n * @param {Timer} timer\n */\n function callTimer(clock, timer) {\n if (typeof timer.interval === "number") {\n clock.timers[timer.id].callAt += timer.interval;\n } else {\n delete clock.timers[timer.id];\n }\n\n if (typeof timer.func === "function") {\n timer.func.apply(null, timer.args);\n } else {\n /* eslint no-eval: "off" */\n const eval2 = eval;\n (function () {\n eval2(timer.func);\n })();\n }\n }\n\n /**\n * Gets clear handler name for a given timer type\n *\n * @param {string} ttype\n */\n function getClearHandler(ttype) {\n if (ttype === "IdleCallback" || ttype === "AnimationFrame") {\n return `cancel${ttype}`;\n }\n return `clear${ttype}`;\n }\n\n /**\n * Gets schedule handler name for a given timer type\n *\n * @param {string} ttype\n */\n function getScheduleHandler(ttype) {\n if (ttype === "IdleCallback" || ttype === "AnimationFrame") {\n return `request${ttype}`;\n }\n return `set${ttype}`;\n }\n\n /**\n * Creates an anonymous function to warn only once\n */\n function createWarnOnce() {\n let calls = 0;\n return function (msg) {\n // eslint-disable-next-line\n !calls++ && console.warn(msg);\n };\n }\n const warnOnce = createWarnOnce();\n\n /**\n * @param {Clock} clock\n * @param {number} timerId\n * @param {string} ttype\n */\n function clearTimer(clock, timerId, ttype) {\n if (!timerId) {\n // null appears to be allowed in most browsers, and appears to be\n // relied upon by some libraries, like Bootstrap carousel\n return;\n }\n\n if (!clock.timers) {\n clock.timers = {};\n }\n\n // in Node, the ID is stored as the primitive value for `Timeout` objects\n // for `Immediate` objects, no ID exists, so it gets coerced to NaN\n const id = Number(timerId);\n\n if (Number.isNaN(id) || id < idCounterStart) {\n const handlerName = getClearHandler(ttype);\n\n if (clock.shouldClearNativeTimers === true) {\n const nativeHandler = clock[`_${handlerName}`];\n return typeof nativeHandler === "function"\n ? nativeHandler(timerId)\n : undefined;\n }\n warnOnce(\n `FakeTimers: ${handlerName} was invoked to clear a native timer instead of one created by this library.` +\n "\\nTo automatically clean-up native timers, use `shouldClearNativeTimers`.",\n );\n }\n\n if (clock.timers.hasOwnProperty(id)) {\n // check that the ID matches a timer of the correct type\n const timer = clock.timers[id];\n if (\n timer.type === ttype ||\n (timer.type === "Timeout" && ttype === "Interval") ||\n (timer.type === "Interval" && ttype === "Timeout")\n ) {\n delete clock.timers[id];\n } else {\n const clear = getClearHandler(ttype);\n const schedule = getScheduleHandler(timer.type);\n throw new Error(\n `Cannot clear timer: timer created with ${schedule}() but cleared with ${clear}()`,\n );\n }\n }\n }\n\n /**\n * @param {Clock} clock\n * @param {Config} config\n * @returns {Timer[]}\n */\n function uninstall(clock, config) {\n let method, i, l;\n const installedHrTime = "_hrtime";\n const installedNextTick = "_nextTick";\n\n for (i = 0, l = clock.methods.length; i < l; i++) {\n method = clock.methods[i];\n if (method === "hrtime" && _global.process) {\n _global.process.hrtime = clock[installedHrTime];\n } else if (method === "nextTick" && _global.process) {\n _global.process.nextTick = clock[installedNextTick];\n } else if (method === "performance") {\n const originalPerfDescriptor = Object.getOwnPropertyDescriptor(\n clock,\n `_${method}`,\n );\n if (\n originalPerfDescriptor &&\n originalPerfDescriptor.get &&\n !originalPerfDescriptor.set\n ) {\n Object.defineProperty(\n _global,\n method,\n originalPerfDescriptor,\n );\n } else if (originalPerfDescriptor.configurable) {\n _global[method] = clock[`_${method}`];\n }\n } else {\n if (_global[method] && _global[method].hadOwnProperty) {\n _global[method] = clock[`_${method}`];\n } else {\n try {\n delete _global[method];\n } catch (ignore) {\n /* eslint no-empty: "off" */\n }\n }\n }\n }\n\n if (config.shouldAdvanceTime === true) {\n _global.clearInterval(clock.attachedInterval);\n }\n\n // Prevent multiple executions which will completely remove these props\n clock.methods = [];\n\n // return pending timers, to enable checking what timers remained on uninstall\n if (!clock.timers) {\n return [];\n }\n return Object.keys(clock.timers).map(function mapper(key) {\n return clock.timers[key];\n });\n }\n\n /**\n * @param {object} target the target containing the method to replace\n * @param {string} method the keyname of the method on the target\n * @param {Clock} clock\n */\n function hijackMethod(target, method, clock) {\n clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(\n target,\n method,\n );\n clock[`_${method}`] = target[method];\n\n if (method === "Date") {\n const date = mirrorDateProperties(clock[method], target[method]);\n target[method] = date;\n } else if (method === "Intl") {\n target[method] = clock[method];\n } else if (method === "performance") {\n const originalPerfDescriptor = Object.getOwnPropertyDescriptor(\n target,\n method,\n );\n // JSDOM has a read only performance field so we have to save/copy it differently\n if (\n originalPerfDescriptor &&\n originalPerfDescriptor.get &&\n !originalPerfDescriptor.set\n ) {\n Object.defineProperty(\n clock,\n `_${method}`,\n originalPerfDescriptor,\n );\n\n const perfDescriptor = Object.getOwnPropertyDescriptor(\n clock,\n method,\n );\n Object.defineProperty(target, method, perfDescriptor);\n } else {\n target[method] = clock[method];\n }\n } else {\n target[method] = function () {\n return clock[method].apply(clock, arguments);\n };\n\n Object.defineProperties(\n target[method],\n Object.getOwnPropertyDescriptors(clock[method]),\n );\n }\n\n target[method].clock = clock;\n }\n\n /**\n * @param {Clock} clock\n * @param {number} advanceTimeDelta\n */\n function doIntervalTick(clock, advanceTimeDelta) {\n clock.tick(advanceTimeDelta);\n }\n\n /**\n * @typedef {object} Timers\n * @property {setTimeout} setTimeout\n * @property {clearTimeout} clearTimeout\n * @property {setInterval} setInterval\n * @property {clearInterval} clearInterval\n * @property {Date} Date\n * @property {Intl} Intl\n * @property {SetImmediate=} setImmediate\n * @property {function(NodeImmediate): void=} clearImmediate\n * @property {function(number[]):number[]=} hrtime\n * @property {NextTick=} nextTick\n * @property {Performance=} performance\n * @property {RequestAnimationFrame=} requestAnimationFrame\n * @property {boolean=} queueMicrotask\n * @property {function(number): void=} cancelAnimationFrame\n * @property {RequestIdleCallback=} requestIdleCallback\n * @property {function(number): void=} cancelIdleCallback\n */\n\n /** @type {Timers} */\n const timers = {\n setTimeout: _global.setTimeout,\n clearTimeout: _global.clearTimeout,\n setInterval: _global.setInterval,\n clearInterval: _global.clearInterval,\n Date: _global.Date,\n };\n\n if (setImmediatePresent) {\n timers.setImmediate = _global.setImmediate;\n timers.clearImmediate = _global.clearImmediate;\n }\n\n if (hrtimePresent) {\n timers.hrtime = _global.process.hrtime;\n }\n\n if (nextTickPresent) {\n timers.nextTick = _global.process.nextTick;\n }\n\n if (performancePresent) {\n timers.performance = _global.performance;\n }\n\n if (requestAnimationFramePresent) {\n timers.requestAnimationFrame = _global.requestAnimationFrame;\n }\n\n if (queueMicrotaskPresent) {\n timers.queueMicrotask = true;\n }\n\n if (cancelAnimationFramePresent) {\n timers.cancelAnimationFrame = _global.cancelAnimationFrame;\n }\n\n if (requestIdleCallbackPresent) {\n timers.requestIdleCallback = _global.requestIdleCallback;\n }\n\n if (cancelIdleCallbackPresent) {\n timers.cancelIdleCallback = _global.cancelIdleCallback;\n }\n\n if (intlPresent) {\n timers.Intl = _global.Intl;\n }\n\n const originalSetTimeout = _global.setImmediate || _global.setTimeout;\n\n /**\n * @param {Date|number} [start] the system time - non-integer values are floored\n * @param {number} [loopLimit] maximum number of timers that will be run when calling runAll()\n * @returns {Clock}\n */\n function createClock(start, loopLimit) {\n // eslint-disable-next-line no-param-reassign\n start = Math.floor(getEpoch(start));\n // eslint-disable-next-line no-param-reassign\n loopLimit = loopLimit || 1000;\n let nanos = 0;\n const adjustedSystemTime = [0, 0]; // [millis, nanoremainder]\n\n if (NativeDate === undefined) {\n throw new Error(\n "The global scope doesn\'t have a `Date` object" +\n " (see https://github.com/sinonjs/sinon/issues/1852#issuecomment-419622780)",\n );\n }\n\n const clock = {\n now: start,\n Date: createDate(),\n loopLimit: loopLimit,\n };\n\n clock.Date.clock = clock;\n\n //eslint-disable-next-line jsdoc/require-jsdoc\n function getTimeToNextFrame() {\n return 16 - ((clock.now - start) % 16);\n }\n\n //eslint-disable-next-line jsdoc/require-jsdoc\n function hrtime(prev) {\n const millisSinceStart = clock.now - adjustedSystemTime[0] - start;\n const secsSinceStart = Math.floor(millisSinceStart / 1000);\n const remainderInNanos =\n (millisSinceStart - secsSinceStart * 1e3) * 1e6 +\n nanos -\n adjustedSystemTime[1];\n\n if (Array.isArray(prev)) {\n if (prev[1] > 1e9) {\n throw new TypeError(\n "Number of nanoseconds can\'t exceed a billion",\n );\n }\n\n const oldSecs = prev[0];\n let nanoDiff = remainderInNanos - prev[1];\n let secDiff = secsSinceStart - oldSecs;\n\n if (nanoDiff < 0) {\n nanoDiff += 1e9;\n secDiff -= 1;\n }\n\n return [secDiff, nanoDiff];\n }\n return [secsSinceStart, remainderInNanos];\n }\n\n /**\n * A high resolution timestamp in milliseconds.\n *\n * @typedef {number} DOMHighResTimeStamp\n */\n\n /**\n * performance.now()\n *\n * @returns {DOMHighResTimeStamp}\n */\n function fakePerformanceNow() {\n const hrt = hrtime();\n const millis = hrt[0] * 1000 + hrt[1] / 1e6;\n return millis;\n }\n\n if (hrtimeBigintPresent) {\n hrtime.bigint = function () {\n const parts = hrtime();\n return BigInt(parts[0]) * BigInt(1e9) + BigInt(parts[1]); // eslint-disable-line\n };\n }\n\n if (intlPresent) {\n clock.Intl = createIntl();\n clock.Intl.clock = clock;\n }\n\n clock.requestIdleCallback = function requestIdleCallback(\n func,\n timeout,\n ) {\n let timeToNextIdlePeriod = 0;\n\n if (clock.countTimers() > 0) {\n timeToNextIdlePeriod = 50; // const for now\n }\n\n const result = addTimer(clock, {\n func: func,\n args: Array.prototype.slice.call(arguments, 2),\n delay:\n typeof timeout === "undefined"\n ? timeToNextIdlePeriod\n : Math.min(timeout, timeToNextIdlePeriod),\n idleCallback: true,\n });\n\n return Number(result);\n };\n\n clock.cancelIdleCallback = function cancelIdleCallback(timerId) {\n return clearTimer(clock, timerId, "IdleCallback");\n };\n\n clock.setTimeout = function setTimeout(func, timeout) {\n return addTimer(clock, {\n func: func,\n args: Array.prototype.slice.call(arguments, 2),\n delay: timeout,\n });\n };\n if (typeof _global.Promise !== "undefined" && utilPromisify) {\n clock.setTimeout[utilPromisify.custom] =\n function promisifiedSetTimeout(timeout, arg) {\n return new _global.Promise(function setTimeoutExecutor(\n resolve,\n ) {\n addTimer(clock, {\n func: resolve,\n args: [arg],\n delay: timeout,\n });\n });\n };\n }\n\n clock.clearTimeout = function clearTimeout(timerId) {\n return clearTimer(clock, timerId, "Timeout");\n };\n\n clock.nextTick = function nextTick(func) {\n return enqueueJob(clock, {\n func: func,\n args: Array.prototype.slice.call(arguments, 1),\n error: isNearInfiniteLimit ? new Error() : null,\n });\n };\n\n clock.queueMicrotask = function queueMicrotask(func) {\n return clock.nextTick(func); // explicitly drop additional arguments\n };\n\n clock.setInterval = function setInterval(func, timeout) {\n // eslint-disable-next-line no-param-reassign\n timeout = parseInt(timeout, 10);\n return addTimer(clock, {\n func: func,\n args: Array.prototype.slice.call(arguments, 2),\n delay: timeout,\n interval: timeout,\n });\n };\n\n clock.clearInterval = function clearInterval(timerId) {\n return clearTimer(clock, timerId, "Interval");\n };\n\n if (setImmediatePresent) {\n clock.setImmediate = function setImmediate(func) {\n return addTimer(clock, {\n func: func,\n args: Array.prototype.slice.call(arguments, 1),\n immediate: true,\n });\n };\n\n if (typeof _global.Promise !== "undefined" && utilPromisify) {\n clock.setImmediate[utilPromisify.custom] =\n function promisifiedSetImmediate(arg) {\n return new _global.Promise(\n function setImmediateExecutor(resolve) {\n addTimer(clock, {\n func: resolve,\n args: [arg],\n immediate: true,\n });\n },\n );\n };\n }\n\n clock.clearImmediate = function clearImmediate(timerId) {\n return clearTimer(clock, timerId, "Immediate");\n };\n }\n\n clock.countTimers = function countTimers() {\n return (\n Object.keys(clock.timers || {}).length +\n (clock.jobs || []).length\n );\n };\n\n clock.requestAnimationFrame = function requestAnimationFrame(func) {\n const result = addTimer(clock, {\n func: func,\n delay: getTimeToNextFrame(),\n get args() {\n return [fakePerformanceNow()];\n },\n animation: true,\n });\n\n return Number(result);\n };\n\n clock.cancelAnimationFrame = function cancelAnimationFrame(timerId) {\n return clearTimer(clock, timerId, "AnimationFrame");\n };\n\n clock.runMicrotasks = function runMicrotasks() {\n runJobs(clock);\n };\n\n /**\n * @param {number|string} tickValue milliseconds or a string parseable by parseTime\n * @param {boolean} isAsync\n * @param {Function} resolve\n * @param {Function} reject\n * @returns {number|undefined} will return the new `now` value or nothing for async\n */\n function doTick(tickValue, isAsync, resolve, reject) {\n const msFloat =\n typeof tickValue === "number"\n ? tickValue\n : parseTime(tickValue);\n const ms = Math.floor(msFloat);\n const remainder = nanoRemainder(msFloat);\n let nanosTotal = nanos + remainder;\n let tickTo = clock.now + ms;\n\n if (msFloat < 0) {\n throw new TypeError("Negative ticks are not supported");\n }\n\n // adjust for positive overflow\n if (nanosTotal >= 1e6) {\n tickTo += 1;\n nanosTotal -= 1e6;\n }\n\n nanos = nanosTotal;\n let tickFrom = clock.now;\n let previous = clock.now;\n // ESLint fails to detect this correctly\n /* eslint-disable prefer-const */\n let timer,\n firstException,\n oldNow,\n nextPromiseTick,\n compensationCheck,\n postTimerCall;\n /* eslint-enable prefer-const */\n\n clock.duringTick = true;\n\n // perform microtasks\n oldNow = clock.now;\n runJobs(clock);\n if (oldNow !== clock.now) {\n // compensate for any setSystemTime() call during microtask callback\n tickFrom += clock.now - oldNow;\n tickTo += clock.now - oldNow;\n }\n\n //eslint-disable-next-line jsdoc/require-jsdoc\n function doTickInner() {\n // perform each timer in the requested range\n timer = firstTimerInRange(clock, tickFrom, tickTo);\n // eslint-disable-next-line no-unmodified-loop-condition\n while (timer && tickFrom <= tickTo) {\n if (clock.timers[timer.id]) {\n tickFrom = timer.callAt;\n clock.now = timer.callAt;\n oldNow = clock.now;\n try {\n runJobs(clock);\n callTimer(clock, timer);\n } catch (e) {\n firstException = firstException || e;\n }\n\n if (isAsync) {\n // finish up after native setImmediate callback to allow\n // all native es6 promises to process their callbacks after\n // each timer fires.\n originalSetTimeout(nextPromiseTick);\n return;\n }\n\n compensationCheck();\n }\n\n postTimerCall();\n }\n\n // perform process.nextTick()s again\n oldNow = clock.now;\n runJobs(clock);\n if (oldNow !== clock.now) {\n // compensate for any setSystemTime() call during process.nextTick() callback\n tickFrom += clock.now - oldNow;\n tickTo += clock.now - oldNow;\n }\n clock.duringTick = false;\n\n // corner case: during runJobs new timers were scheduled which could be in the range [clock.now, tickTo]\n timer = firstTimerInRange(clock, tickFrom, tickTo);\n if (timer) {\n try {\n clock.tick(tickTo - clock.now); // do it all again - for the remainder of the requested range\n } catch (e) {\n firstException = firstException || e;\n }\n } else {\n // no timers remaining in the requested range: move the clock all the way to the end\n clock.now = tickTo;\n\n // update nanos\n nanos = nanosTotal;\n }\n if (firstException) {\n throw firstException;\n }\n\n if (isAsync) {\n resolve(clock.now);\n } else {\n return clock.now;\n }\n }\n\n nextPromiseTick =\n isAsync &&\n function () {\n try {\n compensationCheck();\n postTimerCall();\n doTickInner();\n } catch (e) {\n reject(e);\n }\n };\n\n compensationCheck = function () {\n // compensate for any setSystemTime() call during timer callback\n if (oldNow !== clock.now) {\n tickFrom += clock.now - oldNow;\n tickTo += clock.now - oldNow;\n previous += clock.now - oldNow;\n }\n };\n\n postTimerCall = function () {\n timer = firstTimerInRange(clock, previous, tickTo);\n previous = tickFrom;\n };\n\n return doTickInner();\n }\n\n /**\n * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15"\n * @returns {number} will return the new `now` value\n */\n clock.tick = function tick(tickValue) {\n return doTick(tickValue, false);\n };\n\n if (typeof _global.Promise !== "undefined") {\n /**\n * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15"\n * @returns {Promise}\n */\n clock.tickAsync = function tickAsync(tickValue) {\n return new _global.Promise(function (resolve, reject) {\n originalSetTimeout(function () {\n try {\n doTick(tickValue, true, resolve, reject);\n } catch (e) {\n reject(e);\n }\n });\n });\n };\n }\n\n clock.next = function next() {\n runJobs(clock);\n const timer = firstTimer(clock);\n if (!timer) {\n return clock.now;\n }\n\n clock.duringTick = true;\n try {\n clock.now = timer.callAt;\n callTimer(clock, timer);\n runJobs(clock);\n return clock.now;\n } finally {\n clock.duringTick = false;\n }\n };\n\n if (typeof _global.Promise !== "undefined") {\n clock.nextAsync = function nextAsync() {\n return new _global.Promise(function (resolve, reject) {\n originalSetTimeout(function () {\n try {\n const timer = firstTimer(clock);\n if (!timer) {\n resolve(clock.now);\n return;\n }\n\n let err;\n clock.duringTick = true;\n clock.now = timer.callAt;\n try {\n callTimer(clock, timer);\n } catch (e) {\n err = e;\n }\n clock.duringTick = false;\n\n originalSetTimeout(function () {\n if (err) {\n reject(err);\n } else {\n resolve(clock.now);\n }\n });\n } catch (e) {\n reject(e);\n }\n });\n });\n };\n }\n\n clock.runAll = function runAll() {\n let numTimers, i;\n runJobs(clock);\n for (i = 0; i < clock.loopLimit; i++) {\n if (!clock.timers) {\n resetIsNearInfiniteLimit();\n return clock.now;\n }\n\n numTimers = Object.keys(clock.timers).length;\n if (numTimers === 0) {\n resetIsNearInfiniteLimit();\n return clock.now;\n }\n\n clock.next();\n checkIsNearInfiniteLimit(clock, i);\n }\n\n const excessJob = firstTimer(clock);\n throw getInfiniteLoopError(clock, excessJob);\n };\n\n clock.runToFrame = function runToFrame() {\n return clock.tick(getTimeToNextFrame());\n };\n\n if (typeof _global.Promise !== "undefined") {\n clock.runAllAsync = function runAllAsync() {\n return new _global.Promise(function (resolve, reject) {\n let i = 0;\n /**\n *\n */\n function doRun() {\n originalSetTimeout(function () {\n try {\n runJobs(clock);\n\n let numTimers;\n if (i < clock.loopLimit) {\n if (!clock.timers) {\n resetIsNearInfiniteLimit();\n resolve(clock.now);\n return;\n }\n\n numTimers = Object.keys(\n clock.timers,\n ).length;\n if (numTimers === 0) {\n resetIsNearInfiniteLimit();\n resolve(clock.now);\n return;\n }\n\n clock.next();\n\n i++;\n\n doRun();\n checkIsNearInfiniteLimit(clock, i);\n return;\n }\n\n const excessJob = firstTimer(clock);\n reject(getInfiniteLoopError(clock, excessJob));\n } catch (e) {\n reject(e);\n }\n });\n }\n doRun();\n });\n };\n }\n\n clock.runToLast = function runToLast() {\n const timer = lastTimer(clock);\n if (!timer) {\n runJobs(clock);\n return clock.now;\n }\n\n return clock.tick(timer.callAt - clock.now);\n };\n\n if (typeof _global.Promise !== "undefined") {\n clock.runToLastAsync = function runToLastAsync() {\n return new _global.Promise(function (resolve, reject) {\n originalSetTimeout(function () {\n try {\n const timer = lastTimer(clock);\n if (!timer) {\n runJobs(clock);\n resolve(clock.now);\n }\n\n resolve(clock.tickAsync(timer.callAt - clock.now));\n } catch (e) {\n reject(e);\n }\n });\n });\n };\n }\n\n clock.reset = function reset() {\n nanos = 0;\n clock.timers = {};\n clock.jobs = [];\n clock.now = start;\n };\n\n clock.setSystemTime = function setSystemTime(systemTime) {\n // determine time difference\n const newNow = getEpoch(systemTime);\n const difference = newNow - clock.now;\n let id, timer;\n\n adjustedSystemTime[0] = adjustedSystemTime[0] + difference;\n adjustedSystemTime[1] = adjustedSystemTime[1] + nanos;\n // update \'system clock\'\n clock.now = newNow;\n nanos = 0;\n\n // update timers and intervals to keep them stable\n for (id in clock.timers) {\n if (clock.timers.hasOwnProperty(id)) {\n timer = clock.timers[id];\n timer.createdAt += difference;\n timer.callAt += difference;\n }\n }\n };\n\n /**\n * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15"\n * @returns {number} will return the new `now` value\n */\n clock.jump = function jump(tickValue) {\n const msFloat =\n typeof tickValue === "number"\n ? tickValue\n : parseTime(tickValue);\n const ms = Math.floor(msFloat);\n\n for (const timer of Object.values(clock.timers)) {\n if (clock.now + ms > timer.callAt) {\n timer.callAt = clock.now + ms;\n }\n }\n clock.tick(ms);\n };\n\n if (performancePresent) {\n clock.performance = Object.create(null);\n clock.performance.now = fakePerformanceNow;\n }\n\n if (hrtimePresent) {\n clock.hrtime = hrtime;\n }\n\n return clock;\n }\n\n /* eslint-disable complexity */\n\n /**\n * @param {Config=} [config] Optional config\n * @returns {Clock}\n */\n function install(config) {\n if (\n arguments.length > 1 ||\n config instanceof Date ||\n Array.isArray(config) ||\n typeof config === "number"\n ) {\n throw new TypeError(\n `FakeTimers.install called with ${String(\n config,\n )} install requires an object parameter`,\n );\n }\n\n if (_global.Date.isFake === true) {\n // Timers are already faked; this is a problem.\n // Make the user reset timers before continuing.\n throw new TypeError(\n "Can\'t install fake timers twice on the same global object.",\n );\n }\n\n // eslint-disable-next-line no-param-reassign\n config = typeof config !== "undefined" ? config : {};\n config.shouldAdvanceTime = config.shouldAdvanceTime || false;\n config.advanceTimeDelta = config.advanceTimeDelta || 20;\n config.shouldClearNativeTimers =\n config.shouldClearNativeTimers || false;\n\n if (config.target) {\n throw new TypeError(\n "config.target is no longer supported. Use `withGlobal(target)` instead.",\n );\n }\n\n let i, l;\n const clock = createClock(config.now, config.loopLimit);\n clock.shouldClearNativeTimers = config.shouldClearNativeTimers;\n\n clock.uninstall = function () {\n return uninstall(clock, config);\n };\n\n clock.methods = config.toFake || [];\n\n if (clock.methods.length === 0) {\n // do not fake nextTick by default - GitHub#126\n clock.methods = Object.keys(timers).filter(function (key) {\n return key !== "nextTick" && key !== "queueMicrotask";\n });\n }\n\n if (config.shouldAdvanceTime === true) {\n const intervalTick = doIntervalTick.bind(\n null,\n clock,\n config.advanceTimeDelta,\n );\n const intervalId = _global.setInterval(\n intervalTick,\n config.advanceTimeDelta,\n );\n clock.attachedInterval = intervalId;\n }\n\n if (clock.methods.includes("performance")) {\n const proto = (() => {\n if (hasPerformanceConstructorPrototype) {\n return _global.performance.constructor.prototype;\n }\n if (hasPerformancePrototype) {\n return _global.Performance.prototype;\n }\n })();\n if (proto) {\n Object.getOwnPropertyNames(proto).forEach(function (name) {\n if (name !== "now") {\n clock.performance[name] =\n name.indexOf("getEntries") === 0\n ? NOOP_ARRAY\n : NOOP;\n }\n });\n } else if ((config.toFake || []).includes("performance")) {\n // user explicitly tried to fake performance when not present\n throw new ReferenceError(\n "non-existent performance object cannot be faked",\n );\n }\n }\n for (i = 0, l = clock.methods.length; i < l; i++) {\n const nameOfMethodToReplace = clock.methods[i];\n if (nameOfMethodToReplace === "hrtime") {\n if (\n _global.process &&\n typeof _global.process.hrtime === "function"\n ) {\n hijackMethod(_global.process, nameOfMethodToReplace, clock);\n }\n } else if (nameOfMethodToReplace === "nextTick") {\n if (\n _global.process &&\n typeof _global.process.nextTick === "function"\n ) {\n hijackMethod(_global.process, nameOfMethodToReplace, clock);\n }\n } else {\n hijackMethod(_global, nameOfMethodToReplace, clock);\n }\n }\n\n return clock;\n }\n\n /* eslint-enable complexity */\n\n return {\n timers: timers,\n createClock: createClock,\n install: install,\n withGlobal: withGlobal,\n };\n}\n\n/**\n * @typedef {object} FakeTimers\n * @property {Timers} timers\n * @property {createClock} createClock\n * @property {Function} install\n * @property {withGlobal} withGlobal\n */\n\n// /** @type {FakeTimers} */\nwindow.__wdio_sinon = withGlobal(globalThis);\n\n// // exports.timers = defaultImplementation.timers;\n// // exports.createClock = defaultImplementation.createClock;\n// // exports.install = defaultImplementation.install;\n// // exports.withGlobal = withGlobal;\n}\n';
|
|
1182
1186
|
var _browser, _resetFn, _isInstalled;
|
|
1183
1187
|
var ClockManager = class {
|
|
1184
|
-
constructor(
|
|
1188
|
+
constructor(browser) {
|
|
1185
1189
|
__privateAdd(this, _browser);
|
|
1186
1190
|
__privateAdd(this, _resetFn, () => Promise.resolve());
|
|
1187
1191
|
__privateAdd(this, _isInstalled, false);
|
|
1188
|
-
__privateSet(this, _browser,
|
|
1192
|
+
__privateSet(this, _browser, browser);
|
|
1189
1193
|
}
|
|
1190
1194
|
/**
|
|
1191
1195
|
* Install fake timers on the browser. If you call the `emulate` command, WebdriverIO will automatically install
|
|
@@ -2630,14 +2634,14 @@ var deviceDescriptorsSource = {
|
|
|
2630
2634
|
};
|
|
2631
2635
|
|
|
2632
2636
|
// src/commands/browser/emulate.ts
|
|
2633
|
-
function storeRestoreFunction(
|
|
2637
|
+
function storeRestoreFunction(browser, scope, fn) {
|
|
2634
2638
|
var _a, _b;
|
|
2635
|
-
if (!restoreFunctions.has(
|
|
2636
|
-
restoreFunctions.set(
|
|
2639
|
+
if (!restoreFunctions.has(browser)) {
|
|
2640
|
+
restoreFunctions.set(browser, /* @__PURE__ */ new Map());
|
|
2637
2641
|
}
|
|
2638
|
-
const restoreFunctionsList = (_a = restoreFunctions.get(
|
|
2642
|
+
const restoreFunctionsList = (_a = restoreFunctions.get(browser)) == null ? void 0 : _a.get(scope);
|
|
2639
2643
|
const updatedList = restoreFunctionsList ? [...restoreFunctionsList, fn] : [fn];
|
|
2640
|
-
(_b = restoreFunctions.get(
|
|
2644
|
+
(_b = restoreFunctions.get(browser)) == null ? void 0 : _b.set(scope, updatedList);
|
|
2641
2645
|
}
|
|
2642
2646
|
async function emulate(scope, options) {
|
|
2643
2647
|
if (!this.isBidi) {
|
|
@@ -3008,11 +3012,11 @@ var SessionManager = class {
|
|
|
3008
3012
|
* @param browser WebdriverIO.Browser
|
|
3009
3013
|
* @param scope scope of the session manager, e.g. context, network etc.
|
|
3010
3014
|
*/
|
|
3011
|
-
constructor(
|
|
3015
|
+
constructor(browser, scope) {
|
|
3012
3016
|
__privateAdd(this, _SessionManager_instances);
|
|
3013
3017
|
__privateAdd(this, _browser2);
|
|
3014
3018
|
__privateAdd(this, _scope);
|
|
3015
|
-
__privateSet(this, _browser2,
|
|
3019
|
+
__privateSet(this, _browser2, browser);
|
|
3016
3020
|
__privateSet(this, _scope, scope);
|
|
3017
3021
|
const registrationId = "".concat(__privateGet(this, _browser2).sessionId, "-").concat(__privateGet(this, _scope));
|
|
3018
3022
|
if (!listenerRegisteredSession.has(registrationId)) {
|
|
@@ -3033,20 +3037,20 @@ var SessionManager = class {
|
|
|
3033
3037
|
return (
|
|
3034
3038
|
// we are in a Bidi session
|
|
3035
3039
|
__privateGet(this, _browser2).isBidi && // we are not running unit tests
|
|
3036
|
-
!
|
|
3040
|
+
!environment.value.variables.WDIO_UNIT_TESTS
|
|
3037
3041
|
);
|
|
3038
3042
|
}
|
|
3039
|
-
static getSessionManager(
|
|
3043
|
+
static getSessionManager(browser, Manager) {
|
|
3040
3044
|
const scope = Manager.name;
|
|
3041
3045
|
let sessionManagerInstances = sessionManager.get(scope);
|
|
3042
3046
|
if (!sessionManagerInstances) {
|
|
3043
3047
|
sessionManagerInstances = /* @__PURE__ */ new Map();
|
|
3044
3048
|
sessionManager.set(scope, sessionManagerInstances);
|
|
3045
3049
|
}
|
|
3046
|
-
let sessionManagerInstance = sessionManagerInstances.get(
|
|
3050
|
+
let sessionManagerInstance = sessionManagerInstances.get(browser);
|
|
3047
3051
|
if (!sessionManagerInstance) {
|
|
3048
|
-
sessionManagerInstance = new Manager(
|
|
3049
|
-
sessionManagerInstances.set(
|
|
3052
|
+
sessionManagerInstance = new Manager(browser);
|
|
3053
|
+
sessionManagerInstances.set(browser, sessionManagerInstance);
|
|
3050
3054
|
}
|
|
3051
3055
|
return sessionManagerInstance;
|
|
3052
3056
|
}
|
|
@@ -3091,20 +3095,20 @@ function getMobileContext({ capabilities, isAndroid, isNativeContext }) {
|
|
|
3091
3095
|
isAndroid && ((_a = capabilities == null ? void 0 : capabilities.browserName) == null ? void 0 : _a.toLowerCase()) === "chrome" ? "CHROMIUM" : void 0
|
|
3092
3096
|
);
|
|
3093
3097
|
}
|
|
3094
|
-
function calculateAndroidPinchAndZoomSpeed({ browser
|
|
3098
|
+
function calculateAndroidPinchAndZoomSpeed({ browser, duration, scale }) {
|
|
3095
3099
|
var _a;
|
|
3096
|
-
const deviceScreenSize = (((_a =
|
|
3100
|
+
const deviceScreenSize = (((_a = browser.capabilities) == null ? void 0 : _a.deviceScreenSize) || "1080x2400").split("x").reduce((a, b) => a * b);
|
|
3097
3101
|
const baseDistance = Math.sqrt(deviceScreenSize);
|
|
3098
3102
|
const gestureDistance = Math.max(baseDistance * Math.abs(scale), baseDistance * 0.1);
|
|
3099
3103
|
const durationSeconds = duration / 1e3;
|
|
3100
3104
|
return Math.floor(gestureDistance / durationSeconds);
|
|
3101
3105
|
}
|
|
3102
|
-
function validatePinchAndZoomOptions({ browser
|
|
3106
|
+
function validatePinchAndZoomOptions({ browser, gesture, options }) {
|
|
3103
3107
|
if (typeof options !== "undefined" && (typeof options !== "object" || Array.isArray(options))) {
|
|
3104
3108
|
throw new TypeError("Options must be an object");
|
|
3105
3109
|
}
|
|
3106
3110
|
const DEFAULT_SCALE = 0.5;
|
|
3107
|
-
const DEFAULT_DURATION =
|
|
3111
|
+
const DEFAULT_DURATION = browser.isIOS ? 1.5 : 1500;
|
|
3108
3112
|
const MIN_SCALE = 0;
|
|
3109
3113
|
const MAX_SCALE = 1;
|
|
3110
3114
|
const MIN_DURATION_MS = 500;
|
|
@@ -3113,32 +3117,32 @@ function validatePinchAndZoomOptions({ browser: browser2, gesture, options }) {
|
|
|
3113
3117
|
const scale = typeof scaleOption === "number" ? scaleOption >= MIN_SCALE && scaleOption <= MAX_SCALE ? scaleOption : (() => {
|
|
3114
3118
|
throw new Error("The 'scale' option must be a number between ".concat(MIN_SCALE, " and ").concat(MAX_SCALE));
|
|
3115
3119
|
})() : DEFAULT_SCALE;
|
|
3116
|
-
const duration = typeof durationOption === "number" ? durationOption >= MIN_DURATION_MS && durationOption <= MAX_DURATION_MS ?
|
|
3120
|
+
const duration = typeof durationOption === "number" ? durationOption >= MIN_DURATION_MS && durationOption <= MAX_DURATION_MS ? browser.isIOS ? durationOption / 1e3 : durationOption : (() => {
|
|
3117
3121
|
throw new Error("The 'duration' option must be between ".concat(MIN_DURATION_MS, " and ").concat(MAX_DURATION_MS, " ms (").concat(MIN_DURATION_MS / 1e3, " and ").concat(MAX_DURATION_MS / 1e3, " seconds)"));
|
|
3118
3122
|
})() : DEFAULT_DURATION;
|
|
3119
3123
|
return {
|
|
3120
3124
|
duration,
|
|
3121
|
-
scale:
|
|
3125
|
+
scale: browser.isIOS && gesture === "zoom" ? scale * 10 : scale
|
|
3122
3126
|
};
|
|
3123
3127
|
}
|
|
3124
3128
|
|
|
3125
3129
|
// src/session/context.ts
|
|
3126
3130
|
var log3 = logger3("webdriverio:context");
|
|
3127
3131
|
var COMMANDS_REQUIRING_RESET = ["deleteSession", "refresh", "switchToParentFrame"];
|
|
3128
|
-
function getContextManager(
|
|
3129
|
-
return SessionManager.getSessionManager(
|
|
3132
|
+
function getContextManager(browser) {
|
|
3133
|
+
return SessionManager.getSessionManager(browser, ContextManager);
|
|
3130
3134
|
}
|
|
3131
3135
|
var _browser3, _currentContext, _mobileContext, _isNativeContext, _getContextSupport, _ContextManager_instances, onCommandResultBidiAndClassic_fn, onCommand_fn2, onCommandResultMobile_fn;
|
|
3132
3136
|
var _ContextManager = class _ContextManager extends SessionManager {
|
|
3133
|
-
constructor(
|
|
3134
|
-
super(
|
|
3137
|
+
constructor(browser) {
|
|
3138
|
+
super(browser, _ContextManager.name);
|
|
3135
3139
|
__privateAdd(this, _ContextManager_instances);
|
|
3136
3140
|
__privateAdd(this, _browser3);
|
|
3137
3141
|
__privateAdd(this, _currentContext);
|
|
3138
3142
|
__privateAdd(this, _mobileContext);
|
|
3139
3143
|
__privateAdd(this, _isNativeContext);
|
|
3140
3144
|
__privateAdd(this, _getContextSupport, true);
|
|
3141
|
-
__privateSet(this, _browser3,
|
|
3145
|
+
__privateSet(this, _browser3, browser);
|
|
3142
3146
|
const capabilities = __privateGet(this, _browser3).capabilities;
|
|
3143
3147
|
__privateSet(this, _isNativeContext, getNativeContext({ capabilities, isMobile: __privateGet(this, _browser3).isMobile }));
|
|
3144
3148
|
__privateSet(this, _mobileContext, getMobileContext({
|
|
@@ -3184,7 +3188,7 @@ var _ContextManager = class _ContextManager extends SessionManager {
|
|
|
3184
3188
|
* set context at the start of the session
|
|
3185
3189
|
*/
|
|
3186
3190
|
async initialize() {
|
|
3187
|
-
if (
|
|
3191
|
+
if (environment.value.variables.WDIO_UNIT_TESTS) {
|
|
3188
3192
|
return "";
|
|
3189
3193
|
}
|
|
3190
3194
|
if (__privateGet(this, _browser3).isMobile && !__privateGet(this, _isNativeContext) && !__privateGet(this, _mobileContext) && __privateGet(this, _getContextSupport)) {
|
|
@@ -3361,8 +3365,8 @@ async function execute(script, ...args) {
|
|
|
3361
3365
|
throw new Error("number or type of arguments don't agree with execute protocol command");
|
|
3362
3366
|
}
|
|
3363
3367
|
if (this.isBidi && !this.isMultiremote) {
|
|
3364
|
-
const
|
|
3365
|
-
const contextManager = getContextManager(
|
|
3368
|
+
const browser = getBrowserObject3(this);
|
|
3369
|
+
const contextManager = getContextManager(browser);
|
|
3366
3370
|
const context = await contextManager.getCurrentContext();
|
|
3367
3371
|
const userScript = typeof script === "string" ? new Function(script) : script;
|
|
3368
3372
|
const functionDeclaration = createFunctionDeclarationFromString(userScript);
|
|
@@ -3374,7 +3378,7 @@ async function execute(script, ...args) {
|
|
|
3374
3378
|
context
|
|
3375
3379
|
}
|
|
3376
3380
|
};
|
|
3377
|
-
const result = await
|
|
3381
|
+
const result = await browser.scriptCallFunction(params);
|
|
3378
3382
|
return parseScriptResult(params, result);
|
|
3379
3383
|
}
|
|
3380
3384
|
if (typeof script === "function") {
|
|
@@ -3390,8 +3394,8 @@ async function executeAsync(script, ...args) {
|
|
|
3390
3394
|
throw new Error("number or type of arguments don't agree with execute protocol command");
|
|
3391
3395
|
}
|
|
3392
3396
|
if (this.isBidi && !this.isMultiremote) {
|
|
3393
|
-
const
|
|
3394
|
-
const contextManager = getContextManager(
|
|
3397
|
+
const browser = getBrowserObject4(this);
|
|
3398
|
+
const contextManager = getContextManager(browser);
|
|
3395
3399
|
const context = await contextManager.getCurrentContext();
|
|
3396
3400
|
const userScript = typeof script === "string" ? new Function(script) : script;
|
|
3397
3401
|
const functionDeclaration = new Function("\n const args = Array.from(arguments)\n return new Promise(async (resolve, reject) => {\n const cb = (result) => resolve(result)\n try {\n await (".concat(userScript.toString(), ").apply(this, [...args, cb])\n } catch (err) {\n return reject(err)\n }\n })\n ")).toString();
|
|
@@ -3403,7 +3407,7 @@ async function executeAsync(script, ...args) {
|
|
|
3403
3407
|
context
|
|
3404
3408
|
}
|
|
3405
3409
|
};
|
|
3406
|
-
const result = await
|
|
3410
|
+
const result = await browser.scriptCallFunction(params);
|
|
3407
3411
|
return parseScriptResult(params, result);
|
|
3408
3412
|
}
|
|
3409
3413
|
if (typeof script === "function") {
|
|
@@ -3558,8 +3562,8 @@ async function getPuppeteer() {
|
|
|
3558
3562
|
// src/commands/browser/getWindowSize.ts
|
|
3559
3563
|
import { getBrowserObject as getBrowserObject5 } from "@wdio/utils";
|
|
3560
3564
|
async function getWindowSize() {
|
|
3561
|
-
const
|
|
3562
|
-
const { width, height } = await
|
|
3565
|
+
const browser = getBrowserObject5(this);
|
|
3566
|
+
const { width, height } = await browser.getWindowRect();
|
|
3563
3567
|
return { width, height };
|
|
3564
3568
|
}
|
|
3565
3569
|
|
|
@@ -3632,6 +3636,9 @@ var Timer = class {
|
|
|
3632
3636
|
} else {
|
|
3633
3637
|
this._timeoutId = setTimeout(this._tick.bind(this), this._delay);
|
|
3634
3638
|
}
|
|
3639
|
+
if (this._wasConditionExecuted()) {
|
|
3640
|
+
return;
|
|
3641
|
+
}
|
|
3635
3642
|
this._mainTimeoutId = setTimeout(() => {
|
|
3636
3643
|
if (!this._wasConditionExecuted()) {
|
|
3637
3644
|
return;
|
|
@@ -3711,7 +3718,7 @@ function parseOverwrite(overwrite, request) {
|
|
|
3711
3718
|
const result = {};
|
|
3712
3719
|
if ("body" in overwrite && overwrite.body) {
|
|
3713
3720
|
const bodyOverwrite = typeof overwrite.body === "function" ? overwrite.body(request) : overwrite.body;
|
|
3714
|
-
result.body = (bodyOverwrite == null ? void 0 : bodyOverwrite.type) === "string" || (bodyOverwrite == null ? void 0 : bodyOverwrite.type) === "base64" ? bodyOverwrite : typeof bodyOverwrite === "string" ? { type: "string", value: bodyOverwrite } : { type: "base64", value:
|
|
3721
|
+
result.body = (bodyOverwrite == null ? void 0 : bodyOverwrite.type) === "string" || (bodyOverwrite == null ? void 0 : bodyOverwrite.type) === "base64" ? bodyOverwrite : typeof bodyOverwrite === "string" ? { type: "string", value: bodyOverwrite } : { type: "base64", value: btoa(JSON.stringify(bodyOverwrite || "")) };
|
|
3715
3722
|
}
|
|
3716
3723
|
if ("headers" in overwrite) {
|
|
3717
3724
|
const headersOverwrite = typeof overwrite.headers === "function" ? overwrite.headers(request) : overwrite.headers;
|
|
@@ -3766,7 +3773,7 @@ var log6 = logger6("WebDriverInterception");
|
|
|
3766
3773
|
var hasSubscribedToEvents = false;
|
|
3767
3774
|
var _pattern, _mockId, _filterOptions, _browser4, _eventHandler, _restored, _requestOverwrites, _respondOverwrites, _calls, _responseBodies, _WebDriverInterception_instances, emit_fn, addEventHandler_fn, handleBeforeRequestSent_fn, handleResponseStarted_fn, handleNetworkProvideResponseError_fn, isRequestMatching_fn, matchesFilterOptions_fn, _setOverwrite, ensureNotRestored_fn;
|
|
3768
3775
|
var _WebDriverInterception = class _WebDriverInterception {
|
|
3769
|
-
constructor(pattern, mockId, filterOptions,
|
|
3776
|
+
constructor(pattern, mockId, filterOptions, browser) {
|
|
3770
3777
|
__privateAdd(this, _WebDriverInterception_instances);
|
|
3771
3778
|
__privateAdd(this, _pattern);
|
|
3772
3779
|
__privateAdd(this, _mockId);
|
|
@@ -3787,14 +3794,14 @@ var _WebDriverInterception = class _WebDriverInterception {
|
|
|
3787
3794
|
__privateSet(this, _pattern, pattern);
|
|
3788
3795
|
__privateSet(this, _mockId, mockId);
|
|
3789
3796
|
__privateSet(this, _filterOptions, filterOptions);
|
|
3790
|
-
__privateSet(this, _browser4,
|
|
3791
|
-
|
|
3792
|
-
|
|
3797
|
+
__privateSet(this, _browser4, browser);
|
|
3798
|
+
browser.on("network.beforeRequestSent", __privateMethod(this, _WebDriverInterception_instances, handleBeforeRequestSent_fn).bind(this));
|
|
3799
|
+
browser.on("network.responseStarted", __privateMethod(this, _WebDriverInterception_instances, handleResponseStarted_fn).bind(this));
|
|
3793
3800
|
}
|
|
3794
|
-
static async initiate(url2, filterOptions,
|
|
3801
|
+
static async initiate(url2, filterOptions, browser) {
|
|
3795
3802
|
const pattern = parseUrlPattern(url2);
|
|
3796
3803
|
if (!hasSubscribedToEvents) {
|
|
3797
|
-
await
|
|
3804
|
+
await browser.sessionSubscribe({
|
|
3798
3805
|
events: [
|
|
3799
3806
|
"network.beforeRequestSent",
|
|
3800
3807
|
"network.responseStarted"
|
|
@@ -3803,7 +3810,7 @@ var _WebDriverInterception = class _WebDriverInterception {
|
|
|
3803
3810
|
log6.info("subscribed to network events");
|
|
3804
3811
|
hasSubscribedToEvents = true;
|
|
3805
3812
|
}
|
|
3806
|
-
const interception = await
|
|
3813
|
+
const interception = await browser.networkAddIntercept({
|
|
3807
3814
|
phases: ["beforeRequestSent", "responseStarted"],
|
|
3808
3815
|
urlPatterns: [{
|
|
3809
3816
|
type: "pattern",
|
|
@@ -3814,7 +3821,7 @@ var _WebDriverInterception = class _WebDriverInterception {
|
|
|
3814
3821
|
search: getPatternParam(pattern, "search")
|
|
3815
3822
|
}]
|
|
3816
3823
|
});
|
|
3817
|
-
return new _WebDriverInterception(pattern, interception.intercept, filterOptions,
|
|
3824
|
+
return new _WebDriverInterception(pattern, interception.intercept, filterOptions, browser);
|
|
3818
3825
|
}
|
|
3819
3826
|
/**
|
|
3820
3827
|
* Get the raw binary data for a mock response by request ID
|
|
@@ -4150,8 +4157,8 @@ async function mock(url2, filterOptions) {
|
|
|
4150
4157
|
if (!this.isBidi) {
|
|
4151
4158
|
throw new Error("Mocking is only supported when running tests using WebDriver Bidi");
|
|
4152
4159
|
}
|
|
4153
|
-
const
|
|
4154
|
-
const contextManager = getContextManager(
|
|
4160
|
+
const browser = getBrowserObject6(this);
|
|
4161
|
+
const contextManager = getContextManager(browser);
|
|
4155
4162
|
const context = await contextManager.getCurrentContext();
|
|
4156
4163
|
if (!SESSION_MOCKS[context]) {
|
|
4157
4164
|
SESSION_MOCKS[context] = /* @__PURE__ */ new Set();
|
|
@@ -4314,19 +4321,19 @@ import logger12 from "@wdio/logger";
|
|
|
4314
4321
|
|
|
4315
4322
|
// src/session/polyfill.ts
|
|
4316
4323
|
import logger10 from "@wdio/logger";
|
|
4317
|
-
function getPolyfillManager(
|
|
4318
|
-
return SessionManager.getSessionManager(
|
|
4324
|
+
function getPolyfillManager(browser) {
|
|
4325
|
+
return SessionManager.getSessionManager(browser, PolyfillManager);
|
|
4319
4326
|
}
|
|
4320
4327
|
var log10 = logger10("webdriverio:PolyfillManager");
|
|
4321
4328
|
var _initialize, _browser5, _scriptsRegisteredInContexts, _PolyfillManager_instances, registerScripts_fn;
|
|
4322
4329
|
var _PolyfillManager = class _PolyfillManager extends SessionManager {
|
|
4323
|
-
constructor(
|
|
4324
|
-
super(
|
|
4330
|
+
constructor(browser) {
|
|
4331
|
+
super(browser, _PolyfillManager.name);
|
|
4325
4332
|
__privateAdd(this, _PolyfillManager_instances);
|
|
4326
4333
|
__privateAdd(this, _initialize);
|
|
4327
4334
|
__privateAdd(this, _browser5);
|
|
4328
4335
|
__privateAdd(this, _scriptsRegisteredInContexts, /* @__PURE__ */ new Set());
|
|
4329
|
-
__privateSet(this, _browser5,
|
|
4336
|
+
__privateSet(this, _browser5, browser);
|
|
4330
4337
|
if (!this.isEnabled()) {
|
|
4331
4338
|
__privateSet(this, _initialize, Promise.resolve(true));
|
|
4332
4339
|
return;
|
|
@@ -4413,20 +4420,20 @@ function customElementWrapper() {
|
|
|
4413
4420
|
|
|
4414
4421
|
// src/session/shadowRoot.ts
|
|
4415
4422
|
var log11 = logger11("webdriverio:ShadowRootManager");
|
|
4416
|
-
function getShadowRootManager(
|
|
4417
|
-
return SessionManager.getSessionManager(
|
|
4423
|
+
function getShadowRootManager(browser) {
|
|
4424
|
+
return SessionManager.getSessionManager(browser, ShadowRootManager);
|
|
4418
4425
|
}
|
|
4419
4426
|
var _browser6, _initialize2, _shadowRoots, _documentElement, _frameDepth, _ShadowRootManager_instances, handleBidiCommand_fn, commandResultHandler_fn;
|
|
4420
4427
|
var _ShadowRootManager = class _ShadowRootManager extends SessionManager {
|
|
4421
|
-
constructor(
|
|
4422
|
-
super(
|
|
4428
|
+
constructor(browser) {
|
|
4429
|
+
super(browser, _ShadowRootManager.name);
|
|
4423
4430
|
__privateAdd(this, _ShadowRootManager_instances);
|
|
4424
4431
|
__privateAdd(this, _browser6);
|
|
4425
4432
|
__privateAdd(this, _initialize2);
|
|
4426
4433
|
__privateAdd(this, _shadowRoots, /* @__PURE__ */ new Map());
|
|
4427
4434
|
__privateAdd(this, _documentElement);
|
|
4428
4435
|
__privateAdd(this, _frameDepth, 0);
|
|
4429
|
-
__privateSet(this, _browser6,
|
|
4436
|
+
__privateSet(this, _browser6, browser);
|
|
4430
4437
|
if (!this.isEnabled()) {
|
|
4431
4438
|
__privateSet(this, _initialize2, Promise.resolve(true));
|
|
4432
4439
|
return;
|
|
@@ -4691,21 +4698,21 @@ var ShadowRootTree = class _ShadowRootTree {
|
|
|
4691
4698
|
};
|
|
4692
4699
|
|
|
4693
4700
|
// src/session/networkManager.ts
|
|
4694
|
-
function getNetworkManager(
|
|
4695
|
-
return SessionManager.getSessionManager(
|
|
4701
|
+
function getNetworkManager(browser) {
|
|
4702
|
+
return SessionManager.getSessionManager(browser, NetworkManager);
|
|
4696
4703
|
}
|
|
4697
4704
|
var UNKNOWN_NAVIGATION_ID = "UNKNOWN_NAVIGATION_ID";
|
|
4698
4705
|
var SUPPORTED_NAVIGATION_PROTOCOLS = ["http", "https", "data", "file"];
|
|
4699
4706
|
var _browser7, _initialize3, _requests, _lastNetworkId, _NetworkManager_instances, beforeRequestSent_fn, navigationStarted_fn, fetchError_fn, findRootRequest_fn, responseCompleted_fn;
|
|
4700
4707
|
var _NetworkManager = class _NetworkManager extends SessionManager {
|
|
4701
|
-
constructor(
|
|
4702
|
-
super(
|
|
4708
|
+
constructor(browser) {
|
|
4709
|
+
super(browser, _NetworkManager.name);
|
|
4703
4710
|
__privateAdd(this, _NetworkManager_instances);
|
|
4704
4711
|
__privateAdd(this, _browser7);
|
|
4705
4712
|
__privateAdd(this, _initialize3);
|
|
4706
4713
|
__privateAdd(this, _requests, /* @__PURE__ */ new Map());
|
|
4707
4714
|
__privateAdd(this, _lastNetworkId);
|
|
4708
|
-
__privateSet(this, _browser7,
|
|
4715
|
+
__privateSet(this, _browser7, browser);
|
|
4709
4716
|
if (!this.isEnabled()) {
|
|
4710
4717
|
__privateSet(this, _initialize3, Promise.resolve(true));
|
|
4711
4718
|
return;
|
|
@@ -4892,18 +4899,18 @@ function headerListToObject(headers) {
|
|
|
4892
4899
|
}
|
|
4893
4900
|
|
|
4894
4901
|
// src/session/dialog.ts
|
|
4895
|
-
function getDialogManager(
|
|
4896
|
-
return SessionManager.getSessionManager(
|
|
4902
|
+
function getDialogManager(browser) {
|
|
4903
|
+
return SessionManager.getSessionManager(browser, DialogManager);
|
|
4897
4904
|
}
|
|
4898
4905
|
var _browser8, _initialize4, _autoHandleDialog, _DialogManager_instances, handleUserPrompt_fn, switchListenerFlag_fn;
|
|
4899
4906
|
var _DialogManager = class _DialogManager extends SessionManager {
|
|
4900
|
-
constructor(
|
|
4901
|
-
super(
|
|
4907
|
+
constructor(browser) {
|
|
4908
|
+
super(browser, _DialogManager.name);
|
|
4902
4909
|
__privateAdd(this, _DialogManager_instances);
|
|
4903
4910
|
__privateAdd(this, _browser8);
|
|
4904
4911
|
__privateAdd(this, _initialize4);
|
|
4905
4912
|
__privateAdd(this, _autoHandleDialog, true);
|
|
4906
|
-
__privateSet(this, _browser8,
|
|
4913
|
+
__privateSet(this, _browser8, browser);
|
|
4907
4914
|
if (!this.isEnabled()) {
|
|
4908
4915
|
__privateSet(this, _initialize4, Promise.resolve(true));
|
|
4909
4916
|
return;
|
|
@@ -4950,7 +4957,7 @@ switchListenerFlag_fn = function(value) {
|
|
|
4950
4957
|
var DialogManager = _DialogManager;
|
|
4951
4958
|
var _browser9, _context, _message, _defaultValue, _type2;
|
|
4952
4959
|
var Dialog = class {
|
|
4953
|
-
constructor(event,
|
|
4960
|
+
constructor(event, browser) {
|
|
4954
4961
|
__privateAdd(this, _browser9);
|
|
4955
4962
|
__privateAdd(this, _context);
|
|
4956
4963
|
__privateAdd(this, _message);
|
|
@@ -4960,7 +4967,7 @@ var Dialog = class {
|
|
|
4960
4967
|
__privateSet(this, _defaultValue, event.defaultValue);
|
|
4961
4968
|
__privateSet(this, _type2, event.type);
|
|
4962
4969
|
__privateSet(this, _context, event.context);
|
|
4963
|
-
__privateSet(this, _browser9,
|
|
4970
|
+
__privateSet(this, _browser9, browser);
|
|
4964
4971
|
}
|
|
4965
4972
|
message() {
|
|
4966
4973
|
return __privateGet(this, _message);
|
|
@@ -5177,8 +5184,8 @@ async function setWindowSize(width, height) {
|
|
|
5177
5184
|
if (width < minWindowSize2 || width > maxWindowSize2 || height < minWindowSize2 || height > maxWindowSize2) {
|
|
5178
5185
|
throw new Error("setWindowSize expects width and height to be a number in the 0 to 2^31 \u2212 1 range");
|
|
5179
5186
|
}
|
|
5180
|
-
const
|
|
5181
|
-
await
|
|
5187
|
+
const browser = getBrowserObject7(this);
|
|
5188
|
+
await browser.setWindowRect(null, null, width, height);
|
|
5182
5189
|
}
|
|
5183
5190
|
|
|
5184
5191
|
// src/commands/browser/switchWindow.ts
|
|
@@ -5257,28 +5264,31 @@ async function switchFrame(context) {
|
|
|
5257
5264
|
return handle;
|
|
5258
5265
|
}
|
|
5259
5266
|
if (typeof context === "string") {
|
|
5260
|
-
const
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5267
|
+
const newContextId = await this.waitUntil(async () => {
|
|
5268
|
+
const tree = await this.browsingContextGetTree({});
|
|
5269
|
+
const urlContext = sessionContext.findContext(context, tree.contexts, "byUrl") || /**
|
|
5270
|
+
* In case the user provides an url without `/` at the end, e.g. `https://example.com`,
|
|
5271
|
+
* the `browsingContextGetTree` command may return a context with the url `https://example.com/`.
|
|
5272
|
+
*/
|
|
5273
|
+
sessionContext.findContext("".concat(context, "/"), tree.contexts, "byUrl");
|
|
5274
|
+
const urlContextContaining = sessionContext.findContext(context, tree.contexts, "byUrlContaining");
|
|
5275
|
+
const contextIdContext = sessionContext.findContext(context, tree.contexts, "byContextId");
|
|
5276
|
+
if (urlContext) {
|
|
5277
|
+
log14.info('Found context by url "'.concat(urlContext.url, '" with context id "').concat(urlContext.context, '"'));
|
|
5278
|
+
return urlContext.context;
|
|
5279
|
+
} else if (urlContextContaining) {
|
|
5280
|
+
log14.info('Found context by url containing "'.concat(urlContextContaining.url, '" with context id "').concat(urlContextContaining.context, '"'));
|
|
5281
|
+
return urlContextContaining.context;
|
|
5282
|
+
} else if (contextIdContext) {
|
|
5283
|
+
log14.info('Found context by id "'.concat(contextIdContext, '" with url "').concat(contextIdContext.url, '"'));
|
|
5284
|
+
return contextIdContext.context;
|
|
5285
|
+
}
|
|
5286
|
+
return false;
|
|
5287
|
+
}, {
|
|
5288
|
+
timeout: this.options.waitforTimeout,
|
|
5289
|
+
interval: this.options.waitforInterval,
|
|
5290
|
+
timeoutMsg: 'No frame with url or id "'.concat(context, '" found within the timeout')
|
|
5291
|
+
});
|
|
5282
5292
|
const currentContext = await sessionContext.getCurrentContext();
|
|
5283
5293
|
const allContexts = await sessionContext.getFlatContextTree();
|
|
5284
5294
|
const allFrames = (await Promise.all(Object.keys(allContexts).map(async (id) => {
|
|
@@ -5358,49 +5368,61 @@ async function switchFrame(context) {
|
|
|
5358
5368
|
return switchToFrameUsingElement(this, element);
|
|
5359
5369
|
}
|
|
5360
5370
|
if (typeof context === "function") {
|
|
5361
|
-
const
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
const
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5371
|
+
const foundContextId = await this.waitUntil(async () => {
|
|
5372
|
+
const allContexts = await sessionContext.getFlatContextTree();
|
|
5373
|
+
const allContextIds = Object.keys(allContexts);
|
|
5374
|
+
for (const contextId of allContextIds) {
|
|
5375
|
+
const functionDeclaration = new Function("\n return (".concat(SCRIPT_PREFIX).concat(context.toString()).concat(SCRIPT_SUFFIX, ").apply(this, arguments);\n ")).toString();
|
|
5376
|
+
const params = {
|
|
5377
|
+
functionDeclaration,
|
|
5378
|
+
awaitPromise: false,
|
|
5379
|
+
arguments: [],
|
|
5380
|
+
target: { context: contextId }
|
|
5381
|
+
};
|
|
5382
|
+
const result = await this.scriptCallFunction(params).catch((err) => {
|
|
5383
|
+
log14.warn("switchFrame context callback threw error: ".concat(err.message));
|
|
5384
|
+
return void 0;
|
|
5385
|
+
});
|
|
5386
|
+
if (result && result.type === "success" && result.result.type === "boolean" && result.result.value) {
|
|
5387
|
+
return contextId;
|
|
5388
|
+
}
|
|
5374
5389
|
}
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5390
|
+
return false;
|
|
5391
|
+
}, {
|
|
5392
|
+
timeout: this.options.waitforTimeout,
|
|
5393
|
+
interval: this.options.waitforInterval,
|
|
5394
|
+
timeoutMsg: "Could not find the desired frame within the timeout"
|
|
5395
|
+
});
|
|
5396
|
+
await this.switchFrame(null);
|
|
5397
|
+
await this.switchFrame(foundContextId);
|
|
5398
|
+
return foundContextId;
|
|
5380
5399
|
}
|
|
5381
5400
|
throw new Error(
|
|
5382
5401
|
"Invalid type for context parameter: ".concat(typeof context, ", expected one of number, string or null. ") + "Check out our docs: https://webdriver.io/docs/api/browser/switchFrame.html"
|
|
5383
5402
|
);
|
|
5384
5403
|
}
|
|
5385
|
-
function switchToFrameHelper(
|
|
5386
|
-
const sessionContext = getContextManager(
|
|
5404
|
+
function switchToFrameHelper(browser, context) {
|
|
5405
|
+
const sessionContext = getContextManager(browser);
|
|
5387
5406
|
sessionContext.setCurrentContext(context);
|
|
5388
5407
|
}
|
|
5389
|
-
async function switchToFrameUsingElement(
|
|
5390
|
-
const frame = await
|
|
5408
|
+
async function switchToFrameUsingElement(browser, element) {
|
|
5409
|
+
const frame = await browser.execute(
|
|
5391
5410
|
(iframe) => iframe.contentWindow,
|
|
5392
5411
|
element
|
|
5393
5412
|
);
|
|
5394
|
-
switchToFrameHelper(
|
|
5413
|
+
switchToFrameHelper(browser, frame.context);
|
|
5395
5414
|
const elementId = element[ELEMENT_KEY8];
|
|
5396
|
-
await switchToFrame(
|
|
5415
|
+
await switchToFrame(browser, { [ELEMENT_KEY8]: elementId });
|
|
5397
5416
|
return frame.context;
|
|
5398
5417
|
}
|
|
5399
|
-
function switchToFrame(
|
|
5400
|
-
|
|
5401
|
-
return
|
|
5402
|
-
|
|
5403
|
-
|
|
5418
|
+
function switchToFrame(browser, frame) {
|
|
5419
|
+
toggleDisableDeprecationWarning();
|
|
5420
|
+
return browser.switchToFrame(frame).finally(toggleDisableDeprecationWarning);
|
|
5421
|
+
}
|
|
5422
|
+
function toggleDisableDeprecationWarning() {
|
|
5423
|
+
if (typeof process !== "undefined" && process.env) {
|
|
5424
|
+
process.env.DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS = process.env.DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS ? void 0 : "true";
|
|
5425
|
+
}
|
|
5404
5426
|
}
|
|
5405
5427
|
|
|
5406
5428
|
// src/commands/browser/throttle.ts
|
|
@@ -5409,8 +5431,8 @@ import { getBrowserObject as getBrowserObject8 } from "@wdio/utils";
|
|
|
5409
5431
|
var log15 = logger15("webdriverio:throttle");
|
|
5410
5432
|
async function throttle(params) {
|
|
5411
5433
|
log15.warn('Command "throttle" is deprecated and will be removed with the next major version release! Use `throttleNetwork` instead.');
|
|
5412
|
-
const
|
|
5413
|
-
await
|
|
5434
|
+
const browser = getBrowserObject8(this);
|
|
5435
|
+
await browser.throttleNetwork(params);
|
|
5414
5436
|
}
|
|
5415
5437
|
|
|
5416
5438
|
// src/commands/browser/throttleCPU.ts
|
|
@@ -5509,8 +5531,8 @@ async function throttleNetwork(params) {
|
|
|
5509
5531
|
throw new Error('Invalid parameter for "throttleNetwork". Expected it to be typeof object or one of the following values: '.concat(NETWORK_PRESET_TYPES.join(", "), ' but found "').concat(params, '"'));
|
|
5510
5532
|
}
|
|
5511
5533
|
if (this.isSauce) {
|
|
5512
|
-
const
|
|
5513
|
-
await
|
|
5534
|
+
const browser = getBrowserObject9(this);
|
|
5535
|
+
await browser.sauceThrottleNetwork(params);
|
|
5514
5536
|
return;
|
|
5515
5537
|
}
|
|
5516
5538
|
const failedConnectionMessage = "No Puppeteer connection could be established which is required to use this command";
|
|
@@ -5640,14 +5662,14 @@ function waitUntil(condition, {
|
|
|
5640
5662
|
if (typeof interval !== "number") {
|
|
5641
5663
|
interval = this.options.waitforInterval;
|
|
5642
5664
|
}
|
|
5643
|
-
const
|
|
5665
|
+
const browser = getBrowserObject10(this);
|
|
5644
5666
|
const abort = new AbortController();
|
|
5645
5667
|
const abortOnSessionEnd = (result) => {
|
|
5646
5668
|
if (result.command === "deleteSession") {
|
|
5647
5669
|
abort.abort();
|
|
5648
5670
|
}
|
|
5649
5671
|
};
|
|
5650
|
-
|
|
5672
|
+
browser.on("result", abortOnSessionEnd);
|
|
5651
5673
|
const fn = condition.bind(this);
|
|
5652
5674
|
const timer = new Timer_default(interval, timeout, fn, true, abort.signal);
|
|
5653
5675
|
return timer.catch((e) => {
|
|
@@ -5671,7 +5693,7 @@ function waitUntil(condition, {
|
|
|
5671
5693
|
].filter((errorLine) => !errorLine.includes("/node_modules/webdriverio/") && !errorLine.includes("/node_modules/@wdio/")).join("\n");
|
|
5672
5694
|
throw err;
|
|
5673
5695
|
}).finally(() => {
|
|
5674
|
-
|
|
5696
|
+
browser.off("result", abortOnSessionEnd);
|
|
5675
5697
|
});
|
|
5676
5698
|
}
|
|
5677
5699
|
|
|
@@ -5695,8 +5717,8 @@ var SWIPE_DEFAULTS = {
|
|
|
5695
5717
|
PERCENT: 0.95
|
|
5696
5718
|
};
|
|
5697
5719
|
async function swipe(options) {
|
|
5698
|
-
const
|
|
5699
|
-
if (!
|
|
5720
|
+
const browser = this;
|
|
5721
|
+
if (!browser.isNativeContext) {
|
|
5700
5722
|
throw new Error("The swipe command is only available for mobile platforms in the NATIVE context.");
|
|
5701
5723
|
}
|
|
5702
5724
|
let { scrollableElement, from, to } = options || {};
|
|
@@ -5704,18 +5726,18 @@ async function swipe(options) {
|
|
|
5704
5726
|
log16.warn("`scrollableElement` is provided, so `from` and `to` will be ignored.");
|
|
5705
5727
|
}
|
|
5706
5728
|
if (!from || !to) {
|
|
5707
|
-
scrollableElement = scrollableElement || await getScrollableElement(
|
|
5729
|
+
scrollableElement = scrollableElement || await getScrollableElement(browser);
|
|
5708
5730
|
({ from, to } = await calculateFromTo({
|
|
5709
|
-
browser
|
|
5731
|
+
browser,
|
|
5710
5732
|
direction: (options == null ? void 0 : options.direction) || SWIPE_DEFAULTS.DIRECTION,
|
|
5711
5733
|
percentage: options == null ? void 0 : options.percent,
|
|
5712
5734
|
scrollableElement
|
|
5713
5735
|
}));
|
|
5714
5736
|
}
|
|
5715
|
-
return w3cSwipe({ browser
|
|
5737
|
+
return w3cSwipe({ browser, duration: (options == null ? void 0 : options.duration) || SWIPE_DEFAULTS.DURATION, from, to });
|
|
5716
5738
|
}
|
|
5717
5739
|
async function calculateFromTo({
|
|
5718
|
-
browser
|
|
5740
|
+
browser,
|
|
5719
5741
|
direction,
|
|
5720
5742
|
percentage,
|
|
5721
5743
|
scrollableElement
|
|
@@ -5730,7 +5752,7 @@ async function calculateFromTo({
|
|
|
5730
5752
|
swipePercentage = percentage;
|
|
5731
5753
|
}
|
|
5732
5754
|
}
|
|
5733
|
-
const { x, y, width, height } = await
|
|
5755
|
+
const { x, y, width, height } = await browser.getElementRect(await (scrollableElement == null ? void 0 : scrollableElement.elementId));
|
|
5734
5756
|
const verticalOffset = height - height * swipePercentage;
|
|
5735
5757
|
const horizontalOffset = width - width * swipePercentage;
|
|
5736
5758
|
const scrollRectangles = {
|
|
@@ -5763,31 +5785,31 @@ async function calculateFromTo({
|
|
|
5763
5785
|
}
|
|
5764
5786
|
return { from, to };
|
|
5765
5787
|
}
|
|
5766
|
-
async function getScrollableElement(
|
|
5788
|
+
async function getScrollableElement(browser) {
|
|
5767
5789
|
const defaultAndroidSelector = "//android.widget.ScrollView";
|
|
5768
5790
|
const defaultIosSelector = '-ios predicate string:type == "XCUIElementTypeApplication"';
|
|
5769
|
-
const selector =
|
|
5791
|
+
const selector = browser.isIOS ? (
|
|
5770
5792
|
// For iOS, we need to find the application element, if we can't find it, we should throw an error
|
|
5771
5793
|
defaultIosSelector
|
|
5772
5794
|
) : (
|
|
5773
5795
|
// There is always a scrollview for Android or, if this fails we should throw an error
|
|
5774
5796
|
defaultAndroidSelector
|
|
5775
5797
|
);
|
|
5776
|
-
const scrollableElements = await
|
|
5798
|
+
const scrollableElements = await browser.$$(
|
|
5777
5799
|
selector
|
|
5778
5800
|
);
|
|
5779
5801
|
if (scrollableElements.length > 0) {
|
|
5780
5802
|
return scrollableElements[0];
|
|
5781
5803
|
}
|
|
5782
5804
|
throw new Error(
|
|
5783
|
-
"Default scrollable element '".concat(
|
|
5805
|
+
"Default scrollable element '".concat(browser.isIOS ? defaultIosSelector : defaultAndroidSelector, "' was not found. Our advice is to provide a scrollable element like this:\n\nawait browser.swipe({ scrollableElement: $('#scrollable') });\n\n ")
|
|
5784
5806
|
);
|
|
5785
5807
|
}
|
|
5786
|
-
async function w3cSwipe({ browser
|
|
5787
|
-
await
|
|
5788
|
-
parameters: { pointerType:
|
|
5808
|
+
async function w3cSwipe({ browser, duration, from, to }) {
|
|
5809
|
+
await browser.action("pointer", {
|
|
5810
|
+
parameters: { pointerType: browser.isMobile ? "touch" : "mouse" }
|
|
5789
5811
|
}).move(from.x, from.y).down().pause(10).move({ duration, x: to.x, y: to.y }).up().perform();
|
|
5790
|
-
return
|
|
5812
|
+
return browser.pause(500);
|
|
5791
5813
|
}
|
|
5792
5814
|
|
|
5793
5815
|
// src/commands/mobile/tap.ts
|
|
@@ -5797,18 +5819,18 @@ var log17 = logger17("webdriver");
|
|
|
5797
5819
|
async function tap(options) {
|
|
5798
5820
|
const isElement2 = this.selector !== void 0;
|
|
5799
5821
|
const element = isElement2 ? this : null;
|
|
5800
|
-
const
|
|
5801
|
-
if (!
|
|
5822
|
+
const browser = isElement2 ? getBrowserObject11(this) : this;
|
|
5823
|
+
if (!browser.isMobile) {
|
|
5802
5824
|
throw new Error("The tap command is only available for mobile platforms.");
|
|
5803
5825
|
}
|
|
5804
5826
|
validateTapOptions(options);
|
|
5805
5827
|
if (element) {
|
|
5806
|
-
return await elementTap(
|
|
5828
|
+
return await elementTap(browser, element, options);
|
|
5807
5829
|
}
|
|
5808
5830
|
if (!options || options.x === void 0 || options.y === void 0) {
|
|
5809
5831
|
throw new Error("The tap command requires x and y coordinates to be set for screen taps.");
|
|
5810
5832
|
}
|
|
5811
|
-
return await screenTap(
|
|
5833
|
+
return await screenTap(browser, options);
|
|
5812
5834
|
}
|
|
5813
5835
|
function validateTapOptions(options) {
|
|
5814
5836
|
if (options) {
|
|
@@ -5834,9 +5856,9 @@ function validateTapOptions(options) {
|
|
|
5834
5856
|
}
|
|
5835
5857
|
}
|
|
5836
5858
|
}
|
|
5837
|
-
async function elementTap(
|
|
5838
|
-
if (
|
|
5839
|
-
return await nativeTap(element,
|
|
5859
|
+
async function elementTap(browser, element, options) {
|
|
5860
|
+
if (browser.isNativeContext) {
|
|
5861
|
+
return await nativeTap(element, browser, options);
|
|
5840
5862
|
}
|
|
5841
5863
|
if (options) {
|
|
5842
5864
|
log17.warn("The options object is not supported in Web environments and will be ignored.");
|
|
@@ -5846,18 +5868,18 @@ async function elementTap(browser2, element, options) {
|
|
|
5846
5868
|
async function webTap(element) {
|
|
5847
5869
|
return element.click();
|
|
5848
5870
|
}
|
|
5849
|
-
async function executeNativeTap(
|
|
5850
|
-
return await
|
|
5851
|
-
"mobile: ".concat(
|
|
5852
|
-
{ ...
|
|
5871
|
+
async function executeNativeTap(browser, options) {
|
|
5872
|
+
return await browser.execute(
|
|
5873
|
+
"mobile: ".concat(browser.isIOS ? "tap" : "clickGesture"),
|
|
5874
|
+
{ ...browser.isIOS ? { x: 0, y: 0 } : {}, ...options }
|
|
5853
5875
|
);
|
|
5854
5876
|
}
|
|
5855
|
-
async function nativeTap(element,
|
|
5877
|
+
async function nativeTap(element, browser, options = {}) {
|
|
5856
5878
|
try {
|
|
5857
5879
|
if (!element.elementId) {
|
|
5858
5880
|
throw new Error("no such element");
|
|
5859
5881
|
}
|
|
5860
|
-
return await executeNativeTap(
|
|
5882
|
+
return await executeNativeTap(browser, { elementId: element.elementId });
|
|
5861
5883
|
} catch (error) {
|
|
5862
5884
|
let err = error;
|
|
5863
5885
|
if (typeof error === "string") {
|
|
@@ -5875,7 +5897,7 @@ async function nativeTap(element, browser2, options = {}) {
|
|
|
5875
5897
|
);
|
|
5876
5898
|
try {
|
|
5877
5899
|
await element.scrollIntoView(scrollIntoViewOptions);
|
|
5878
|
-
return await executeNativeTap(
|
|
5900
|
+
return await executeNativeTap(browser, { elementId: element.elementId });
|
|
5879
5901
|
} catch (scrollError) {
|
|
5880
5902
|
let err2 = scrollError;
|
|
5881
5903
|
if (typeof scrollError === "string") {
|
|
@@ -5892,12 +5914,12 @@ async function nativeTap(element, browser2, options = {}) {
|
|
|
5892
5914
|
}
|
|
5893
5915
|
}
|
|
5894
5916
|
}
|
|
5895
|
-
async function screenTap(
|
|
5917
|
+
async function screenTap(browser, options) {
|
|
5896
5918
|
const { x, y } = options;
|
|
5897
|
-
if (
|
|
5898
|
-
return await executeNativeTap(
|
|
5919
|
+
if (browser.isNativeContext) {
|
|
5920
|
+
return await executeNativeTap(browser, options);
|
|
5899
5921
|
}
|
|
5900
|
-
return await
|
|
5922
|
+
return await browser.action(
|
|
5901
5923
|
"pointer",
|
|
5902
5924
|
{
|
|
5903
5925
|
parameters: { pointerType: "touch" }
|
|
@@ -5909,19 +5931,19 @@ async function screenTap(browser2, options) {
|
|
|
5909
5931
|
import logger18 from "@wdio/logger";
|
|
5910
5932
|
var log18 = logger18("webdriver");
|
|
5911
5933
|
async function getContext(options) {
|
|
5912
|
-
const
|
|
5913
|
-
if (!
|
|
5934
|
+
const browser = this;
|
|
5935
|
+
if (!browser.isMobile) {
|
|
5914
5936
|
throw new Error("The `getContext` command is only available for mobile platforms.");
|
|
5915
5937
|
}
|
|
5916
|
-
const currentAppiumContext = await
|
|
5938
|
+
const currentAppiumContext = await browser.getAppiumContext();
|
|
5917
5939
|
if (!options || !(options == null ? void 0 : options.returnDetailedContext) || currentAppiumContext === "NATIVE_APP") {
|
|
5918
5940
|
return currentAppiumContext;
|
|
5919
5941
|
}
|
|
5920
5942
|
delete options.returnDetailedContext;
|
|
5921
|
-
return getDetailedContext(
|
|
5943
|
+
return getDetailedContext(browser, currentAppiumContext, options);
|
|
5922
5944
|
}
|
|
5923
|
-
async function getDetailedContext(
|
|
5924
|
-
const detailedContexts = await
|
|
5945
|
+
async function getDetailedContext(browser, currentAppiumContext, options) {
|
|
5946
|
+
const detailedContexts = await browser.getContexts({
|
|
5925
5947
|
...{ options },
|
|
5926
5948
|
// Defaults
|
|
5927
5949
|
returnDetailedContexts: true,
|
|
@@ -5948,13 +5970,13 @@ async function getDetailedContext(browser2, currentAppiumContext, options) {
|
|
|
5948
5970
|
import logger19 from "@wdio/logger";
|
|
5949
5971
|
var log19 = logger19("webdriver");
|
|
5950
5972
|
async function getContexts(options) {
|
|
5951
|
-
const
|
|
5952
|
-
if (!
|
|
5973
|
+
const browser = this;
|
|
5974
|
+
if (!browser.isMobile) {
|
|
5953
5975
|
throw new Error("The `getContexts` command is only available for mobile platforms.");
|
|
5954
5976
|
}
|
|
5955
5977
|
if (!options || !options.returnDetailedContexts) {
|
|
5956
5978
|
log19.info("The standard Appium `contexts` method is used. If you want to get more detailed data, you can set `returnDetailedContexts` to `true`.");
|
|
5957
|
-
return
|
|
5979
|
+
return browser.getAppiumContexts();
|
|
5958
5980
|
}
|
|
5959
5981
|
const defaultOptions = {
|
|
5960
5982
|
androidWebviewConnectionRetryTime: 500,
|
|
@@ -5963,7 +5985,7 @@ async function getContexts(options) {
|
|
|
5963
5985
|
isAndroidWebviewVisible: true,
|
|
5964
5986
|
returnAndroidDescriptionData: false
|
|
5965
5987
|
};
|
|
5966
|
-
return getCurrentContexts({ browser
|
|
5988
|
+
return getCurrentContexts({ browser, ...{ ...defaultOptions, ...options } });
|
|
5967
5989
|
}
|
|
5968
5990
|
var CHROME_PACKAGE_NAME = "com.android.chrome";
|
|
5969
5991
|
async function parsedAndroidContexts({
|
|
@@ -6033,7 +6055,7 @@ async function parsedAndroidContexts({
|
|
|
6033
6055
|
return result;
|
|
6034
6056
|
}
|
|
6035
6057
|
async function getCurrentContexts({
|
|
6036
|
-
browser
|
|
6058
|
+
browser,
|
|
6037
6059
|
androidWebviewConnectionRetryTime,
|
|
6038
6060
|
androidWebviewConnectTimeout,
|
|
6039
6061
|
filterByCurrentAndroidApp,
|
|
@@ -6041,11 +6063,11 @@ async function getCurrentContexts({
|
|
|
6041
6063
|
returnAndroidDescriptionData
|
|
6042
6064
|
}) {
|
|
6043
6065
|
var _a;
|
|
6044
|
-
const contexts = await
|
|
6045
|
-
if (
|
|
6066
|
+
const contexts = await browser.execute("mobile: getContexts");
|
|
6067
|
+
if (browser.isIOS) {
|
|
6046
6068
|
return contexts;
|
|
6047
6069
|
}
|
|
6048
|
-
const packageName = await
|
|
6070
|
+
const packageName = await browser.getCurrentPackage();
|
|
6049
6071
|
const startTime = Date.now();
|
|
6050
6072
|
const retryInterval = androidWebviewConnectionRetryTime;
|
|
6051
6073
|
let isPackageNameMissing = false;
|
|
@@ -6084,8 +6106,8 @@ async function getCurrentContexts({
|
|
|
6084
6106
|
import logger20 from "@wdio/logger";
|
|
6085
6107
|
var log20 = logger20("webdriver");
|
|
6086
6108
|
async function switchContext(options) {
|
|
6087
|
-
const
|
|
6088
|
-
if (!
|
|
6109
|
+
const browser = this;
|
|
6110
|
+
if (!browser.isMobile) {
|
|
6089
6111
|
throw new Error("The `switchContext` command is only available for mobile platforms.");
|
|
6090
6112
|
}
|
|
6091
6113
|
if (!options) {
|
|
@@ -6093,14 +6115,14 @@ async function switchContext(options) {
|
|
|
6093
6115
|
}
|
|
6094
6116
|
if (typeof options === "string") {
|
|
6095
6117
|
log20.info("The standard Appium `context`-method is used. If you want to switch to a webview with a specific title or url, please provide an object with the `title` or `url` property. See https://webdriver.io/docs/api/mobile/switchContext for more information.");
|
|
6096
|
-
return
|
|
6118
|
+
return browser.switchAppiumContext(options);
|
|
6097
6119
|
}
|
|
6098
6120
|
if (!options.title && !options.url) {
|
|
6099
6121
|
throw new Error("You need to provide at least a `title` or `url` property to use full potential of the `switchContext` command. See https://webdriver.io/docs/api/mobile/switchContext for more information.");
|
|
6100
6122
|
}
|
|
6101
|
-
return switchToContext({ browser
|
|
6123
|
+
return switchToContext({ browser, options });
|
|
6102
6124
|
}
|
|
6103
|
-
async function switchToContext({ browser
|
|
6125
|
+
async function switchToContext({ browser, options }) {
|
|
6104
6126
|
var _a;
|
|
6105
6127
|
const getContextsOptions = {
|
|
6106
6128
|
returnDetailedContexts: true,
|
|
@@ -6110,19 +6132,19 @@ async function switchToContext({ browser: browser2, options }) {
|
|
|
6110
6132
|
...(options == null ? void 0 : options.androidWebviewConnectionRetryTime) && { androidWebviewConnectionRetryTime: options.androidWebviewConnectionRetryTime },
|
|
6111
6133
|
...(options == null ? void 0 : options.androidWebviewConnectTimeout) && { androidWebviewConnectTimeout: options.androidWebviewConnectTimeout }
|
|
6112
6134
|
};
|
|
6113
|
-
const contexts = await
|
|
6114
|
-
const identifier =
|
|
6115
|
-
const { matchingContext, reasons } = findMatchingContext({ browser
|
|
6135
|
+
const contexts = await browser.getContexts(getContextsOptions);
|
|
6136
|
+
const identifier = browser.isIOS ? (_a = await browser.execute("mobile: activeAppInfo")) == null ? void 0 : _a.bundleId : await browser.getCurrentPackage();
|
|
6137
|
+
const { matchingContext, reasons } = findMatchingContext({ browser, contexts, identifier, ...(options == null ? void 0 : options.title) && { title: options.title }, ...(options == null ? void 0 : options.url) && { url: options.url } });
|
|
6116
6138
|
if (!matchingContext) {
|
|
6117
6139
|
throw new Error(reasons.join("\n"));
|
|
6118
6140
|
}
|
|
6119
6141
|
log20.info("WebdriverIO found a matching context:", JSON.stringify(matchingContext, null, 2));
|
|
6120
|
-
if (!
|
|
6142
|
+
if (!browser.isIOS) {
|
|
6121
6143
|
const webviewName = "WEBVIEW_".concat(identifier);
|
|
6122
|
-
await
|
|
6144
|
+
await browser.switchAppiumContext(webviewName);
|
|
6123
6145
|
}
|
|
6124
|
-
const switchFunction =
|
|
6125
|
-
const matchingContextId =
|
|
6146
|
+
const switchFunction = browser.isIOS ? browser.switchAppiumContext.bind(browser) : browser.switchToWindow.bind(browser);
|
|
6147
|
+
const matchingContextId = browser.isIOS ? matchingContext.id : matchingContext.webviewPageId;
|
|
6126
6148
|
return switchFunction(matchingContextId);
|
|
6127
6149
|
}
|
|
6128
6150
|
function findMatchingContext({
|
|
@@ -6164,42 +6186,42 @@ function findMatchingContext({
|
|
|
6164
6186
|
|
|
6165
6187
|
// src/commands/mobile/relaunchActiveApp.ts
|
|
6166
6188
|
async function relaunchActiveApp() {
|
|
6167
|
-
const
|
|
6168
|
-
if (!
|
|
6189
|
+
const browser = this;
|
|
6190
|
+
if (!browser.isMobile) {
|
|
6169
6191
|
throw new Error("The `relaunchActiveApp` command is only available for mobile platforms.");
|
|
6170
6192
|
}
|
|
6171
|
-
if (
|
|
6172
|
-
const { bundleId, processArguments: { args, env } } = await
|
|
6193
|
+
if (browser.isIOS) {
|
|
6194
|
+
const { bundleId, processArguments: { args, env } } = await browser.execute("mobile: activeAppInfo");
|
|
6173
6195
|
const iOSLaunchOptions = {
|
|
6174
6196
|
bundleId,
|
|
6175
6197
|
...args.length > 0 && { arguments: args },
|
|
6176
6198
|
...Object.keys(env).length > 0 && { environment: env }
|
|
6177
6199
|
};
|
|
6178
|
-
await
|
|
6179
|
-
return
|
|
6200
|
+
await browser.execute("mobile: terminateApp", { bundleId });
|
|
6201
|
+
return browser.execute("mobile:launchApp", iOSLaunchOptions);
|
|
6180
6202
|
}
|
|
6181
|
-
const packageName = await
|
|
6182
|
-
await
|
|
6183
|
-
return
|
|
6203
|
+
const packageName = await browser.getCurrentPackage();
|
|
6204
|
+
await browser.execute("mobile: terminateApp", { appId: packageName });
|
|
6205
|
+
return browser.execute("mobile: activateApp", { appId: packageName });
|
|
6184
6206
|
}
|
|
6185
6207
|
|
|
6186
6208
|
// src/commands/mobile/deepLink.ts
|
|
6187
6209
|
async function deepLink(link, appIdentifier) {
|
|
6188
|
-
const
|
|
6189
|
-
if (!
|
|
6210
|
+
const browser = this;
|
|
6211
|
+
if (!browser.isMobile) {
|
|
6190
6212
|
throw new Error("The `deepLink` command is only available for mobile platforms.");
|
|
6191
6213
|
}
|
|
6192
6214
|
if (!isDeepLinkUrl(link)) {
|
|
6193
|
-
throw new Error("The provided link is not a valid deep link URL.".concat(
|
|
6215
|
+
throw new Error("The provided link is not a valid deep link URL.".concat(browser.isIOS ? " If your url is a `universal deep link` then use the `url` command instead." : ""));
|
|
6194
6216
|
}
|
|
6195
6217
|
if (!appIdentifier) {
|
|
6196
|
-
const mobileOS =
|
|
6197
|
-
const identifierValue =
|
|
6218
|
+
const mobileOS = browser.isIOS ? "iOS" : "Android";
|
|
6219
|
+
const identifierValue = browser.isIOS ? "bundleId" : "package";
|
|
6198
6220
|
throw new Error("When using a deep link URL for ".concat(mobileOS, ", you need to provide the `").concat(identifierValue, "` of the app that the deep link should open."));
|
|
6199
6221
|
}
|
|
6200
|
-
return
|
|
6222
|
+
return browser.execute("mobile:deepLink", {
|
|
6201
6223
|
url: link,
|
|
6202
|
-
[
|
|
6224
|
+
[browser.isIOS ? "bundleId" : "package"]: appIdentifier
|
|
6203
6225
|
});
|
|
6204
6226
|
}
|
|
6205
6227
|
function isDeepLinkUrl(link) {
|
|
@@ -6340,9 +6362,9 @@ async function actionClick(element, options) {
|
|
|
6340
6362
|
if (!buttonValue.includes(button)) {
|
|
6341
6363
|
throw new Error("Button type not supported.");
|
|
6342
6364
|
}
|
|
6343
|
-
const
|
|
6365
|
+
const browser = getBrowserObject12(element);
|
|
6344
6366
|
if (x || y) {
|
|
6345
|
-
const { width, height } = await
|
|
6367
|
+
const { width, height } = await browser.getElementRect(element.elementId);
|
|
6346
6368
|
if (x && x < -Math.floor(width / 2) || x && x > Math.floor(width / 2)) {
|
|
6347
6369
|
log21.warn("x would cause a out of bounds error as it goes outside of element");
|
|
6348
6370
|
}
|
|
@@ -6351,8 +6373,8 @@ async function actionClick(element, options) {
|
|
|
6351
6373
|
}
|
|
6352
6374
|
}
|
|
6353
6375
|
const clickNested = async () => {
|
|
6354
|
-
await
|
|
6355
|
-
parameters: { pointerType:
|
|
6376
|
+
await browser.action("pointer", {
|
|
6377
|
+
parameters: { pointerType: browser.isMobile ? "touch" : "mouse" }
|
|
6356
6378
|
}).move({ origin: element, x, y }).down({ button }).pause(duration).up({ button }).perform(skipRelease);
|
|
6357
6379
|
};
|
|
6358
6380
|
try {
|
|
@@ -6411,8 +6433,8 @@ async function custom$2(strategyName, ...strategyArguments) {
|
|
|
6411
6433
|
// src/commands/element/doubleClick.ts
|
|
6412
6434
|
import { getBrowserObject as getBrowserObject15 } from "@wdio/utils";
|
|
6413
6435
|
async function doubleClick() {
|
|
6414
|
-
const
|
|
6415
|
-
return
|
|
6436
|
+
const browser = getBrowserObject15(this);
|
|
6437
|
+
return browser.action("pointer", { parameters: { pointerType: "mouse" } }).move({ origin: this }).down().up().pause(10).down().up().perform();
|
|
6416
6438
|
}
|
|
6417
6439
|
|
|
6418
6440
|
// src/commands/element/dragAndDrop.ts
|
|
@@ -6436,8 +6458,8 @@ async function dragAndDrop(target, options = {}) {
|
|
|
6436
6458
|
throw new Error('command dragAndDrop requires an WebdriverIO Element or and object with "x" and "y" variables as first parameter');
|
|
6437
6459
|
}
|
|
6438
6460
|
const ACTION_BUTTON = 0;
|
|
6439
|
-
const
|
|
6440
|
-
const defaultOptions = { duration:
|
|
6461
|
+
const browser = getBrowserObject16(this);
|
|
6462
|
+
const defaultOptions = { duration: browser.isMobile ? 250 : 10 };
|
|
6441
6463
|
const { duration } = { ...defaultOptions, ...options };
|
|
6442
6464
|
const isMovingToElement = moveToElement.constructor.name === "Element";
|
|
6443
6465
|
const sourceRef = { [ELEMENT_KEY11]: this[ELEMENT_KEY11] };
|
|
@@ -6446,8 +6468,8 @@ async function dragAndDrop(target, options = {}) {
|
|
|
6446
6468
|
const targetOrigin = isMovingToElement ? targetRef : "pointer";
|
|
6447
6469
|
const targetX = isMovingToElement ? 0 : moveToCoordinates.x;
|
|
6448
6470
|
const targetY = isMovingToElement ? 0 : moveToCoordinates.y;
|
|
6449
|
-
return
|
|
6450
|
-
parameters: { pointerType:
|
|
6471
|
+
return browser.action("pointer", {
|
|
6472
|
+
parameters: { pointerType: browser.isMobile ? "touch" : "mouse" }
|
|
6451
6473
|
}).move({ duration: 0, origin, x: 0, y: 0 }).down({ button: ACTION_BUTTON }).pause(10).move({ duration, origin: targetOrigin, x: targetX, y: targetY }).up({ button: ACTION_BUTTON }).perform();
|
|
6452
6474
|
}
|
|
6453
6475
|
|
|
@@ -6455,17 +6477,17 @@ async function dragAndDrop(target, options = {}) {
|
|
|
6455
6477
|
import { getBrowserObject as getBrowserObject17 } from "@wdio/utils";
|
|
6456
6478
|
async function execute2(script, ...args) {
|
|
6457
6479
|
const scope = this;
|
|
6458
|
-
const
|
|
6480
|
+
const browser = getBrowserObject17(scope);
|
|
6459
6481
|
await scope.waitForExist();
|
|
6460
|
-
return
|
|
6482
|
+
return browser.execute(script, scope, ...args);
|
|
6461
6483
|
}
|
|
6462
6484
|
|
|
6463
6485
|
// src/commands/element/executeAsync.ts
|
|
6464
6486
|
import { getBrowserObject as getBrowserObject18 } from "@wdio/utils";
|
|
6465
6487
|
async function executeAsync2(script, ...args) {
|
|
6466
6488
|
const scope = this;
|
|
6467
|
-
const
|
|
6468
|
-
return
|
|
6489
|
+
const browser = getBrowserObject18(scope);
|
|
6490
|
+
return browser.executeAsync(script, scope, ...args);
|
|
6469
6491
|
}
|
|
6470
6492
|
|
|
6471
6493
|
// src/commands/element/getAttribute.ts
|
|
@@ -6539,9 +6561,9 @@ function mergeEqualSymmetricalValue(cssValues) {
|
|
|
6539
6561
|
return newCssValues.join(" ");
|
|
6540
6562
|
}
|
|
6541
6563
|
async function getPseudoElementCSSValue(elem, options) {
|
|
6542
|
-
const
|
|
6564
|
+
const browser = getBrowserObject19(elem);
|
|
6543
6565
|
const { cssProperty, pseudoElement } = options;
|
|
6544
|
-
const cssValue2 = await
|
|
6566
|
+
const cssValue2 = await browser.execute(
|
|
6545
6567
|
(elem2, pseudoElement2, cssProperty2) => window.getComputedStyle(elem2, pseudoElement2)[cssProperty2],
|
|
6546
6568
|
elem,
|
|
6547
6569
|
pseudoElement,
|
|
@@ -6602,7 +6624,7 @@ function getHTMLShadow(element, includeSelectorTag, shadowElementIds = []) {
|
|
|
6602
6624
|
var SHADOW_ID_ATTR_NAME = "data-wdio-shadow-id";
|
|
6603
6625
|
var SHADOW_ID_ATTR = "[".concat(SHADOW_ID_ATTR_NAME, "]");
|
|
6604
6626
|
async function getHTML2(options = {}) {
|
|
6605
|
-
const
|
|
6627
|
+
const browser = getBrowserObject20(this);
|
|
6606
6628
|
if (typeof options !== "object" && typeof options === "boolean") {
|
|
6607
6629
|
options = { includeSelectorTag: options };
|
|
6608
6630
|
} else if (typeof options !== "object") {
|
|
@@ -6616,7 +6638,7 @@ async function getHTML2(options = {}) {
|
|
|
6616
6638
|
excludeElements: []
|
|
6617
6639
|
}, options);
|
|
6618
6640
|
const basicGetHTML = (elementId, includeSelectorTag2) => {
|
|
6619
|
-
return
|
|
6641
|
+
return browser.execute(getHTML, {
|
|
6620
6642
|
[ELEMENT_KEY12]: elementId,
|
|
6621
6643
|
// w3c compatible
|
|
6622
6644
|
ELEMENT: elementId
|
|
@@ -6632,12 +6654,12 @@ async function getHTML2(options = {}) {
|
|
|
6632
6654
|
);
|
|
6633
6655
|
}
|
|
6634
6656
|
const { load } = await import("cheerio");
|
|
6635
|
-
const shadowRootManager = getShadowRootManager(
|
|
6636
|
-
const contextManager = getContextManager(
|
|
6657
|
+
const shadowRootManager = getShadowRootManager(browser);
|
|
6658
|
+
const contextManager = getContextManager(browser);
|
|
6637
6659
|
const context = await contextManager.getCurrentContext();
|
|
6638
6660
|
const shadowRootElementPairs = shadowRootManager.getShadowElementPairsByContextId(context, this.elementId);
|
|
6639
6661
|
const elementsWithShadowRootAndIdVerified = (await Promise.all(
|
|
6640
|
-
shadowRootElementPairs.map(([elemId, elem]) =>
|
|
6662
|
+
shadowRootElementPairs.map(([elemId, elem]) => browser.execute((elem2) => elem2.tagName, { [ELEMENT_KEY12]: elemId }).then(
|
|
6641
6663
|
() => [elemId, elem],
|
|
6642
6664
|
() => void 0
|
|
6643
6665
|
))
|
|
@@ -6689,10 +6711,15 @@ function sanitizeHTML($3, options = {}) {
|
|
|
6689
6711
|
for (const elemToRemove of options.excludeElements || []) {
|
|
6690
6712
|
$3(elemToRemove).remove();
|
|
6691
6713
|
}
|
|
6714
|
+
if (options.removeCommentNodes) {
|
|
6715
|
+
$3("*").contents().filter(function() {
|
|
6716
|
+
return this.type === "comment";
|
|
6717
|
+
}).remove();
|
|
6718
|
+
}
|
|
6692
6719
|
}
|
|
6693
6720
|
let returnHTML = isCheerioObject ? $3("body").html() : $3;
|
|
6694
|
-
if (options.removeCommentNodes) {
|
|
6695
|
-
returnHTML = returnHTML
|
|
6721
|
+
if (!isCheerioObject && options.removeCommentNodes && returnHTML) {
|
|
6722
|
+
returnHTML = returnHTML.replace(/<!--[\s\S]*?-->/g, "");
|
|
6696
6723
|
}
|
|
6697
6724
|
return options.prettify ? prettifyFn(returnHTML) : returnHTML;
|
|
6698
6725
|
}
|
|
@@ -6863,8 +6890,8 @@ async function isClickable() {
|
|
|
6863
6890
|
if (this.isMobile && this.isNativeContext) {
|
|
6864
6891
|
throw new Error("Method not supported in mobile native environment. It is unlikely that you need to use this command.");
|
|
6865
6892
|
}
|
|
6866
|
-
const
|
|
6867
|
-
return
|
|
6893
|
+
const browser = getBrowserObject21(this);
|
|
6894
|
+
return browser.execute(isElementClickable, {
|
|
6868
6895
|
[ELEMENT_KEY13]: this.elementId,
|
|
6869
6896
|
// w3c compatible
|
|
6870
6897
|
ELEMENT: this.elementId
|
|
@@ -7056,11 +7083,11 @@ function isElementInViewport(elem) {
|
|
|
7056
7083
|
|
|
7057
7084
|
// src/commands/element/isDisplayed.ts
|
|
7058
7085
|
async function isDisplayed(commandParams = DEFAULT_PARAMS) {
|
|
7059
|
-
const
|
|
7086
|
+
const browser = getBrowserObject22(this);
|
|
7060
7087
|
if (!await hasElementId(this)) {
|
|
7061
7088
|
return false;
|
|
7062
7089
|
}
|
|
7063
|
-
if (
|
|
7090
|
+
if (browser.isMobile && (browser.isNativeContext || browser.isWindowsApp || browser.isMacApp)) {
|
|
7064
7091
|
if (commandParams == null ? void 0 : commandParams.withinViewport) {
|
|
7065
7092
|
throw new Error(
|
|
7066
7093
|
"Cannot determine element visibility within viewport for native mobile apps as it is not feasible to determine full vertical and horizontal application bounds. In most cases a basic visibility check should suffice."
|
|
@@ -7070,7 +7097,7 @@ async function isDisplayed(commandParams = DEFAULT_PARAMS) {
|
|
|
7070
7097
|
}
|
|
7071
7098
|
let hadToFallback = false;
|
|
7072
7099
|
const [isDisplayed2, displayProperty] = await Promise.all([
|
|
7073
|
-
|
|
7100
|
+
browser.execute(function checkVisibility(elem, params) {
|
|
7074
7101
|
if (typeof elem.checkVisibility === "function") {
|
|
7075
7102
|
return elem.checkVisibility(params);
|
|
7076
7103
|
}
|
|
@@ -7081,7 +7108,7 @@ async function isDisplayed(commandParams = DEFAULT_PARAMS) {
|
|
|
7081
7108
|
}).then((result) => {
|
|
7082
7109
|
if (result === null) {
|
|
7083
7110
|
hadToFallback = true;
|
|
7084
|
-
return
|
|
7111
|
+
return browser.execute(isElementDisplayed, this);
|
|
7085
7112
|
}
|
|
7086
7113
|
return result;
|
|
7087
7114
|
}),
|
|
@@ -7092,9 +7119,9 @@ async function isDisplayed(commandParams = DEFAULT_PARAMS) {
|
|
|
7092
7119
|
]);
|
|
7093
7120
|
const hasDisplayContentsCSSProperty = displayProperty.value === "contents";
|
|
7094
7121
|
const shouldRecheckContentVisibility = !hadToFallback && hasDisplayContentsCSSProperty;
|
|
7095
|
-
const finalResponse = shouldRecheckContentVisibility ? await
|
|
7122
|
+
const finalResponse = shouldRecheckContentVisibility ? await browser.execute(isElementDisplayed, this).catch(() => false) : isDisplayed2;
|
|
7096
7123
|
if (finalResponse && (commandParams == null ? void 0 : commandParams.withinViewport)) {
|
|
7097
|
-
return
|
|
7124
|
+
return browser.execute(isElementInViewport, this);
|
|
7098
7125
|
}
|
|
7099
7126
|
return finalResponse;
|
|
7100
7127
|
}
|
|
@@ -7120,9 +7147,9 @@ var getWebElement = (el) => ({
|
|
|
7120
7147
|
// jsonwp compatible
|
|
7121
7148
|
});
|
|
7122
7149
|
async function isEqual(el) {
|
|
7123
|
-
const
|
|
7124
|
-
if (
|
|
7125
|
-
const context = await
|
|
7150
|
+
const browser = getBrowserObject23(this);
|
|
7151
|
+
if (browser.isMobile) {
|
|
7152
|
+
const context = await browser.getContext().catch(() => void 0);
|
|
7126
7153
|
const contextId = typeof context === "string" ? context : context == null ? void 0 : context.id;
|
|
7127
7154
|
if (contextId && contextId.toLowerCase().includes("native")) {
|
|
7128
7155
|
return this.elementId === el.elementId;
|
|
@@ -7130,7 +7157,7 @@ async function isEqual(el) {
|
|
|
7130
7157
|
}
|
|
7131
7158
|
let result;
|
|
7132
7159
|
try {
|
|
7133
|
-
result = await
|
|
7160
|
+
result = await browser.execute(
|
|
7134
7161
|
/* istanbul ignore next */
|
|
7135
7162
|
function(el1, el2) {
|
|
7136
7163
|
return el1 === el2;
|
|
@@ -7167,8 +7194,8 @@ function isFocused(elem) {
|
|
|
7167
7194
|
|
|
7168
7195
|
// src/commands/element/isFocused.ts
|
|
7169
7196
|
async function isFocused2() {
|
|
7170
|
-
const
|
|
7171
|
-
return
|
|
7197
|
+
const browser = await getBrowserObject24(this);
|
|
7198
|
+
return browser.execute(isFocused, {
|
|
7172
7199
|
[ELEMENT_KEY15]: this.elementId,
|
|
7173
7200
|
// w3c compatible
|
|
7174
7201
|
ELEMENT: this.elementId
|
|
@@ -7210,8 +7237,8 @@ function isElementStable(elem, done) {
|
|
|
7210
7237
|
|
|
7211
7238
|
// src/commands/element/isStable.ts
|
|
7212
7239
|
async function isStable() {
|
|
7213
|
-
const
|
|
7214
|
-
return await
|
|
7240
|
+
const browser = getBrowserObject25(this);
|
|
7241
|
+
return await browser.executeAsync(isElementStable, {
|
|
7215
7242
|
[ELEMENT_KEY16]: this.elementId,
|
|
7216
7243
|
// w3c compatible
|
|
7217
7244
|
ELEMENT: this.elementId
|
|
@@ -7224,9 +7251,9 @@ import logger22 from "@wdio/logger";
|
|
|
7224
7251
|
import { getBrowserObject as getBrowserObject26 } from "@wdio/utils";
|
|
7225
7252
|
var log22 = logger22("webdriver");
|
|
7226
7253
|
async function moveTo({ xOffset, yOffset } = {}) {
|
|
7227
|
-
const
|
|
7254
|
+
const browser = getBrowserObject26(this);
|
|
7228
7255
|
if (xOffset || yOffset) {
|
|
7229
|
-
const { width, height } = await
|
|
7256
|
+
const { width, height } = await browser.getElementRect(this.elementId);
|
|
7230
7257
|
if (xOffset && xOffset < -Math.floor(width / 2) || xOffset && xOffset > Math.floor(width / 2)) {
|
|
7231
7258
|
log22.warn("xOffset would cause a out of bounds error as it goes outside of element");
|
|
7232
7259
|
}
|
|
@@ -7235,7 +7262,7 @@ async function moveTo({ xOffset, yOffset } = {}) {
|
|
|
7235
7262
|
}
|
|
7236
7263
|
}
|
|
7237
7264
|
const moveToNested = async () => {
|
|
7238
|
-
await
|
|
7265
|
+
await browser.action("pointer", { parameters: { pointerType: "mouse" } }).move({ origin: this, x: xOffset || 0, y: yOffset || 0 }).perform();
|
|
7239
7266
|
};
|
|
7240
7267
|
try {
|
|
7241
7268
|
await moveToNested();
|
|
@@ -7278,10 +7305,10 @@ function previousElement() {
|
|
|
7278
7305
|
// src/commands/element/react$$.ts
|
|
7279
7306
|
import { getBrowserObject as getBrowserObject27 } from "@wdio/utils";
|
|
7280
7307
|
async function react$$4(selector, { props = {}, state = {} } = {}) {
|
|
7281
|
-
const
|
|
7308
|
+
const browser = await getBrowserObject27(this);
|
|
7282
7309
|
await this.executeScript(resqScript.toString(), []);
|
|
7283
|
-
await
|
|
7284
|
-
const res = await
|
|
7310
|
+
await browser.execute(waitToLoadReact);
|
|
7311
|
+
const res = await browser.execute(
|
|
7285
7312
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7286
7313
|
react$$,
|
|
7287
7314
|
selector,
|
|
@@ -7296,10 +7323,10 @@ async function react$$4(selector, { props = {}, state = {} } = {}) {
|
|
|
7296
7323
|
// src/commands/element/react$.ts
|
|
7297
7324
|
import { getBrowserObject as getBrowserObject28 } from "@wdio/utils";
|
|
7298
7325
|
async function react$4(selector, { props = {}, state = {} } = {}) {
|
|
7299
|
-
const
|
|
7326
|
+
const browser = await getBrowserObject28(this);
|
|
7300
7327
|
await this.executeScript(resqScript.toString(), []);
|
|
7301
|
-
await
|
|
7302
|
-
const res = await
|
|
7328
|
+
await browser.execute(waitToLoadReact);
|
|
7329
|
+
const res = await browser.execute(
|
|
7303
7330
|
react$,
|
|
7304
7331
|
selector,
|
|
7305
7332
|
props,
|
|
@@ -7320,11 +7347,11 @@ import { ELEMENT_KEY as ELEMENT_KEY17 } from "webdriver";
|
|
|
7320
7347
|
import { getBrowserObject as getBrowserObject29 } from "@wdio/utils";
|
|
7321
7348
|
var log23 = logger23("webdriverio");
|
|
7322
7349
|
async function scrollIntoView(options = { block: "start", inline: "nearest" }) {
|
|
7323
|
-
const
|
|
7324
|
-
if (
|
|
7325
|
-
if (await
|
|
7350
|
+
const browser = getBrowserObject29(this);
|
|
7351
|
+
if (browser.isMobile) {
|
|
7352
|
+
if (await browser.isNativeContext) {
|
|
7326
7353
|
return nativeMobileScrollIntoView({
|
|
7327
|
-
browser
|
|
7354
|
+
browser,
|
|
7328
7355
|
element: this,
|
|
7329
7356
|
options: options || {}
|
|
7330
7357
|
});
|
|
@@ -7332,9 +7359,9 @@ async function scrollIntoView(options = { block: "start", inline: "nearest" }) {
|
|
|
7332
7359
|
return scrollIntoViewWeb.call(this, options);
|
|
7333
7360
|
}
|
|
7334
7361
|
try {
|
|
7335
|
-
const elemRect = await
|
|
7336
|
-
const viewport = await
|
|
7337
|
-
let [scrollX, scrollY] = await
|
|
7362
|
+
const elemRect = await browser.getElementRect(this.elementId);
|
|
7363
|
+
const viewport = await browser.getWindowSize();
|
|
7364
|
+
let [scrollX, scrollY] = await browser.execute(() => [
|
|
7338
7365
|
window.scrollX,
|
|
7339
7366
|
window.scrollY
|
|
7340
7367
|
]);
|
|
@@ -7369,7 +7396,7 @@ async function scrollIntoView(options = { block: "start", inline: "nearest" }) {
|
|
|
7369
7396
|
}
|
|
7370
7397
|
deltaX = Math.round(deltaX - scrollX);
|
|
7371
7398
|
deltaY = Math.round(deltaY - scrollY);
|
|
7372
|
-
await
|
|
7399
|
+
await browser.action("wheel").scroll({ duration: 0, x: deltaX, y: deltaY, origin: this }).perform();
|
|
7373
7400
|
} catch (err) {
|
|
7374
7401
|
log23.warn(
|
|
7375
7402
|
'Failed to execute "scrollIntoView" using WebDriver Actions API: '.concat(err.message, "!\n") + "Re-attempting using `Element.scrollIntoView` via Web API."
|
|
@@ -7378,7 +7405,7 @@ async function scrollIntoView(options = { block: "start", inline: "nearest" }) {
|
|
|
7378
7405
|
}
|
|
7379
7406
|
}
|
|
7380
7407
|
async function mobileScrollUntilVisible({
|
|
7381
|
-
browser
|
|
7408
|
+
browser,
|
|
7382
7409
|
direction,
|
|
7383
7410
|
duration,
|
|
7384
7411
|
element,
|
|
@@ -7398,7 +7425,7 @@ async function mobileScrollUntilVisible({
|
|
|
7398
7425
|
if (isVisible) {
|
|
7399
7426
|
break;
|
|
7400
7427
|
}
|
|
7401
|
-
await
|
|
7428
|
+
await browser.swipe({
|
|
7402
7429
|
direction,
|
|
7403
7430
|
...duration ? { duration } : {},
|
|
7404
7431
|
...percent ? { percent } : {},
|
|
@@ -7410,7 +7437,7 @@ async function mobileScrollUntilVisible({
|
|
|
7410
7437
|
return { hasScrolled, isVisible };
|
|
7411
7438
|
}
|
|
7412
7439
|
async function nativeMobileScrollIntoView({
|
|
7413
|
-
browser
|
|
7440
|
+
browser,
|
|
7414
7441
|
element,
|
|
7415
7442
|
options
|
|
7416
7443
|
}) {
|
|
@@ -7423,7 +7450,7 @@ async function nativeMobileScrollIntoView({
|
|
|
7423
7450
|
...options || {}
|
|
7424
7451
|
};
|
|
7425
7452
|
const { hasScrolled, isVisible } = await mobileScrollUntilVisible({
|
|
7426
|
-
browser
|
|
7453
|
+
browser,
|
|
7427
7454
|
element,
|
|
7428
7455
|
maxScrolls: mobileOptions.maxScrolls,
|
|
7429
7456
|
direction: mobileOptions.direction,
|
|
@@ -7432,15 +7459,15 @@ async function nativeMobileScrollIntoView({
|
|
|
7432
7459
|
...(mobileOptions == null ? void 0 : mobileOptions.scrollableElement) ? { scrollableElement: mobileOptions.scrollableElement } : {}
|
|
7433
7460
|
});
|
|
7434
7461
|
if (hasScrolled && isVisible) {
|
|
7435
|
-
return
|
|
7462
|
+
return browser.pause(1e3);
|
|
7436
7463
|
} else if (isVisible) {
|
|
7437
7464
|
return;
|
|
7438
7465
|
}
|
|
7439
7466
|
throw new Error("Element not found within scroll limit of ".concat(mobileOptions.maxScrolls, ' scrolls by scrolling "').concat(mobileOptions.direction, '". ') + "Are you sure the element is within the scrollable element or the direction is correct? You can change the scrollable element or direction like this:\n\nawait elem.scrollIntoView({\n direction: 'left' // possible options are: 'up|down|left|right'\n scrollableElement: $('#scrollable'),\n});\n\n ");
|
|
7440
7467
|
}
|
|
7441
7468
|
function scrollIntoViewWeb(options = { block: "start", inline: "nearest" }) {
|
|
7442
|
-
const
|
|
7443
|
-
return
|
|
7469
|
+
const browser = getBrowserObject29(this);
|
|
7470
|
+
return browser.execute(
|
|
7444
7471
|
(elem, options2) => elem.scrollIntoView(options2),
|
|
7445
7472
|
{
|
|
7446
7473
|
[ELEMENT_KEY17]: this.elementId,
|
|
@@ -7559,7 +7586,7 @@ var XPATH_SELECTOR_REGEXP = [
|
|
|
7559
7586
|
// optional . or # + class or id
|
|
7560
7587
|
/(?:(\.|#)(-?[_a-zA-Z]+[_a-zA-Z0-9-]*))?/,
|
|
7561
7588
|
// optional [attribute-name="attribute-selector"]
|
|
7562
|
-
/(?:\[(-?[_a-zA-Z]+[_a-zA-Z0-9-]*)(?:=(?:"|')([a-zA-
|
|
7589
|
+
/(?:\[(-?[_a-zA-Z]+[_a-zA-Z0-9-]*)(?:=(?:"|')([a-zA-Z0-9\-_. ]+)(?:"|'))?\])?/,
|
|
7563
7590
|
// optional case insensitive
|
|
7564
7591
|
/(\.)?/,
|
|
7565
7592
|
// *=query or =query
|
|
@@ -7860,11 +7887,11 @@ var createRoleBaseXpathSelector = (role) => {
|
|
|
7860
7887
|
// src/commands/element/shadow$$.ts
|
|
7861
7888
|
var log24 = logger24("webdriverio");
|
|
7862
7889
|
async function shadow$$(selector) {
|
|
7863
|
-
const
|
|
7890
|
+
const browser = getBrowserObject30(this);
|
|
7864
7891
|
try {
|
|
7865
|
-
const shadowRoot = await
|
|
7892
|
+
const shadowRoot = await browser.getElementShadowRoot(this.elementId);
|
|
7866
7893
|
const { using, value } = findStrategy(selector, this.isW3C, this.isMobile);
|
|
7867
|
-
const res = await
|
|
7894
|
+
const res = await browser.findElementsFromShadowRoot(shadowRoot[SHADOW_ELEMENT_KEY], using, value);
|
|
7868
7895
|
const elements = await getElements.call(this, selector, res, { isShadowElement: true });
|
|
7869
7896
|
return enhanceElementsArray(elements, this, selector);
|
|
7870
7897
|
} catch (err) {
|
|
@@ -7881,11 +7908,11 @@ import { SHADOW_ELEMENT_KEY as SHADOW_ELEMENT_KEY2 } from "webdriver";
|
|
|
7881
7908
|
import { getBrowserObject as getBrowserObject31 } from "@wdio/utils";
|
|
7882
7909
|
var log25 = logger25("webdriverio");
|
|
7883
7910
|
async function shadow$(selector) {
|
|
7884
|
-
const
|
|
7911
|
+
const browser = getBrowserObject31(this);
|
|
7885
7912
|
try {
|
|
7886
|
-
const shadowRoot = await
|
|
7913
|
+
const shadowRoot = await browser.getElementShadowRoot(this.elementId);
|
|
7887
7914
|
const { using, value } = findStrategy(selector, this.isW3C, this.isMobile);
|
|
7888
|
-
const res = await
|
|
7915
|
+
const res = await browser.findElementFromShadowRoot(shadowRoot[SHADOW_ELEMENT_KEY2], using, value);
|
|
7889
7916
|
return getElement.call(this, selector, res, { isShadowElement: true });
|
|
7890
7917
|
} catch (err) {
|
|
7891
7918
|
log25.warn(
|
|
@@ -7999,8 +8026,8 @@ var waitUntil2 = waitUntil;
|
|
|
7999
8026
|
// src/commands/mobile/longPress.ts
|
|
8000
8027
|
import { getBrowserObject as getBrowserObject32 } from "@wdio/utils";
|
|
8001
8028
|
function longPress(options) {
|
|
8002
|
-
const
|
|
8003
|
-
if (!
|
|
8029
|
+
const browser = getBrowserObject32(this);
|
|
8030
|
+
if (!browser.isMobile) {
|
|
8004
8031
|
throw new Error("The longPress command is only available for mobile platforms.");
|
|
8005
8032
|
}
|
|
8006
8033
|
if (typeof options !== "undefined" && (typeof options !== "object" || Array.isArray(options))) {
|
|
@@ -8018,12 +8045,12 @@ function longPress(options) {
|
|
|
8018
8045
|
// src/commands/mobile/pinch.ts
|
|
8019
8046
|
import { getBrowserObject as getBrowserObject33 } from "@wdio/utils";
|
|
8020
8047
|
async function pinch(options = {}) {
|
|
8021
|
-
const
|
|
8022
|
-
if (!
|
|
8048
|
+
const browser = getBrowserObject33(this);
|
|
8049
|
+
if (!browser.isMobile) {
|
|
8023
8050
|
throw new Error("The pinch command is only available for mobile platforms.");
|
|
8024
8051
|
}
|
|
8025
|
-
const { duration, scale } = validatePinchAndZoomOptions({ browser
|
|
8026
|
-
const gestureConfig =
|
|
8052
|
+
const { duration, scale } = validatePinchAndZoomOptions({ browser, gesture: "pinch", options });
|
|
8053
|
+
const gestureConfig = browser.isIOS ? {
|
|
8027
8054
|
elementId: await this.elementId,
|
|
8028
8055
|
scale,
|
|
8029
8056
|
velocity: -Math.abs(duration)
|
|
@@ -8031,29 +8058,29 @@ async function pinch(options = {}) {
|
|
|
8031
8058
|
} : {
|
|
8032
8059
|
elementId: await this.elementId,
|
|
8033
8060
|
percent: scale,
|
|
8034
|
-
speed: calculateAndroidPinchAndZoomSpeed({ browser
|
|
8061
|
+
speed: calculateAndroidPinchAndZoomSpeed({ browser, duration, scale })
|
|
8035
8062
|
};
|
|
8036
|
-
return
|
|
8063
|
+
return browser.execute(browser.isIOS ? "mobile: pinch" : "mobile: pinchCloseGesture", gestureConfig);
|
|
8037
8064
|
}
|
|
8038
8065
|
|
|
8039
8066
|
// src/commands/mobile/zoom.ts
|
|
8040
8067
|
import { getBrowserObject as getBrowserObject34 } from "@wdio/utils";
|
|
8041
8068
|
async function zoom(options = {}) {
|
|
8042
|
-
const
|
|
8043
|
-
if (!
|
|
8069
|
+
const browser = getBrowserObject34(this);
|
|
8070
|
+
if (!browser.isMobile) {
|
|
8044
8071
|
throw new Error("The zoom command is only available for mobile platforms.");
|
|
8045
8072
|
}
|
|
8046
|
-
const { duration, scale } = validatePinchAndZoomOptions({ browser
|
|
8047
|
-
const gestureConfig =
|
|
8073
|
+
const { duration, scale } = validatePinchAndZoomOptions({ browser, gesture: "zoom", options });
|
|
8074
|
+
const gestureConfig = browser.isIOS ? {
|
|
8048
8075
|
elementId: await this.elementId,
|
|
8049
8076
|
scale,
|
|
8050
8077
|
velocity: duration
|
|
8051
8078
|
} : {
|
|
8052
8079
|
elementId: await this.elementId,
|
|
8053
8080
|
percent: scale,
|
|
8054
|
-
speed: calculateAndroidPinchAndZoomSpeed({ browser
|
|
8081
|
+
speed: calculateAndroidPinchAndZoomSpeed({ browser, duration, scale })
|
|
8055
8082
|
};
|
|
8056
|
-
return
|
|
8083
|
+
return browser.execute(browser.isIOS ? "mobile: pinch" : "mobile: pinchOpenGesture", gestureConfig);
|
|
8057
8084
|
}
|
|
8058
8085
|
|
|
8059
8086
|
// src/scripts/elementContains.ts
|
|
@@ -8409,9 +8436,9 @@ function transformClassicToBidiSelector(using, value) {
|
|
|
8409
8436
|
throw new Error("Can't transform classic selector ".concat(using, " to Bidi selector"));
|
|
8410
8437
|
}
|
|
8411
8438
|
async function findDeepElement(selector) {
|
|
8412
|
-
const
|
|
8413
|
-
const shadowRootManager = getShadowRootManager(
|
|
8414
|
-
const contextManager = getContextManager(
|
|
8439
|
+
const browser = getBrowserObject35(this);
|
|
8440
|
+
const shadowRootManager = getShadowRootManager(browser);
|
|
8441
|
+
const contextManager = getContextManager(browser);
|
|
8415
8442
|
const context = await contextManager.getCurrentContext();
|
|
8416
8443
|
const shadowRoots = shadowRootManager.getShadowElementsByContextId(
|
|
8417
8444
|
context,
|
|
@@ -8420,7 +8447,7 @@ async function findDeepElement(selector) {
|
|
|
8420
8447
|
const { using, value } = findStrategy(selector, this.isW3C, this.isMobile);
|
|
8421
8448
|
const locator = transformClassicToBidiSelector(using, value);
|
|
8422
8449
|
const startNodes = shadowRoots.length > 0 ? shadowRoots.map((shadowRootNodeId) => ({ sharedId: shadowRootNodeId })) : this.elementId ? [{ sharedId: this.elementId }] : void 0;
|
|
8423
|
-
const deepElementResult = await
|
|
8450
|
+
const deepElementResult = await browser.browsingContextLocateNodes({ locator, context, startNodes }).then(async (result) => {
|
|
8424
8451
|
let nodes = result.nodes.filter((node) => Boolean(node.sharedId)).map((node) => ({
|
|
8425
8452
|
[ELEMENT_KEY20]: node.sharedId,
|
|
8426
8453
|
locator
|
|
@@ -8430,7 +8457,7 @@ async function findDeepElement(selector) {
|
|
|
8430
8457
|
return nodes[0];
|
|
8431
8458
|
}
|
|
8432
8459
|
const scopedNodes = await Promise.all(nodes.map(async (node) => {
|
|
8433
|
-
const isIn = await
|
|
8460
|
+
const isIn = await browser.execute(
|
|
8434
8461
|
elementContains,
|
|
8435
8462
|
{ [ELEMENT_KEY20]: this.elementId },
|
|
8436
8463
|
node
|
|
@@ -8440,7 +8467,7 @@ async function findDeepElement(selector) {
|
|
|
8440
8467
|
return scopedNodes[0];
|
|
8441
8468
|
}, (err) => {
|
|
8442
8469
|
log26.warn("Failed to execute browser.browsingContextLocateNodes({ ... }) due to ".concat(err, ", falling back to regular WebDriver Classic command"));
|
|
8443
|
-
return this && "elementId" in this && this.elementId ? this.findElementFromElement(this.elementId, using, value) :
|
|
8470
|
+
return this && "elementId" in this && this.elementId ? this.findElementFromElement(this.elementId, using, value) : browser.findElement(using, value);
|
|
8444
8471
|
});
|
|
8445
8472
|
if (!deepElementResult) {
|
|
8446
8473
|
return new Error("Couldn't find element with selector \"".concat(selector, '"'));
|
|
@@ -8448,9 +8475,9 @@ async function findDeepElement(selector) {
|
|
|
8448
8475
|
return deepElementResult;
|
|
8449
8476
|
}
|
|
8450
8477
|
async function findDeepElements(selector) {
|
|
8451
|
-
const
|
|
8452
|
-
const shadowRootManager = getShadowRootManager(
|
|
8453
|
-
const contextManager = getContextManager(
|
|
8478
|
+
const browser = getBrowserObject35(this);
|
|
8479
|
+
const shadowRootManager = getShadowRootManager(browser);
|
|
8480
|
+
const contextManager = getContextManager(browser);
|
|
8454
8481
|
const context = await contextManager.getCurrentContext();
|
|
8455
8482
|
const shadowRoots = shadowRootManager.getShadowElementsByContextId(
|
|
8456
8483
|
context,
|
|
@@ -8459,7 +8486,7 @@ async function findDeepElements(selector) {
|
|
|
8459
8486
|
const { using, value } = findStrategy(selector, this.isW3C, this.isMobile);
|
|
8460
8487
|
const locator = transformClassicToBidiSelector(using, value);
|
|
8461
8488
|
const startNodes = shadowRoots.length > 0 ? shadowRoots.map((shadowRootNodeId) => ({ sharedId: shadowRootNodeId })) : this.elementId ? [{ sharedId: this.elementId }] : void 0;
|
|
8462
|
-
const deepElementResult = await
|
|
8489
|
+
const deepElementResult = await browser.browsingContextLocateNodes({ locator, context, startNodes }).then(async (result) => {
|
|
8463
8490
|
let nodes = result.nodes.filter((node) => Boolean(node.sharedId)).map((node) => ({
|
|
8464
8491
|
[ELEMENT_KEY20]: node.sharedId,
|
|
8465
8492
|
locator
|
|
@@ -8469,7 +8496,7 @@ async function findDeepElements(selector) {
|
|
|
8469
8496
|
return nodes;
|
|
8470
8497
|
}
|
|
8471
8498
|
const scopedNodes = await Promise.all(nodes.map(async (node) => {
|
|
8472
|
-
const isIn = await
|
|
8499
|
+
const isIn = await browser.execute(
|
|
8473
8500
|
elementContains,
|
|
8474
8501
|
{ [ELEMENT_KEY20]: this.elementId },
|
|
8475
8502
|
node
|
|
@@ -8479,7 +8506,7 @@ async function findDeepElements(selector) {
|
|
|
8479
8506
|
return scopedNodes;
|
|
8480
8507
|
}, (err) => {
|
|
8481
8508
|
log26.warn("Failed to execute browser.browsingContextLocateNodes({ ... }) due to ".concat(err, ", falling back to regular WebDriver Classic command"));
|
|
8482
|
-
return this && "elementId" in this && this.elementId ? this.findElementsFromElement(this.elementId, using, value) :
|
|
8509
|
+
return this && "elementId" in this && this.elementId ? this.findElementsFromElement(this.elementId, using, value) : browser.findElements(using, value);
|
|
8483
8510
|
});
|
|
8484
8511
|
return deepElementResult;
|
|
8485
8512
|
}
|
|
@@ -8673,7 +8700,7 @@ function createFunctionDeclarationFromString(userScript) {
|
|
|
8673
8700
|
}
|
|
8674
8701
|
|
|
8675
8702
|
// src/middlewares.ts
|
|
8676
|
-
var COMMANDS_TO_SKIP = ["getElement", "getElements"];
|
|
8703
|
+
var COMMANDS_TO_SKIP = ["getElement", "getElements", "emit"];
|
|
8677
8704
|
var elementErrorHandler = (fn) => (commandName, commandFn) => {
|
|
8678
8705
|
return function elementErrorHandlerCallback(...args) {
|
|
8679
8706
|
return fn(commandName, async function elementErrorHandlerCallbackFn() {
|
|
@@ -8985,7 +9012,7 @@ var NOOP2 = () => {
|
|
|
8985
9012
|
var ProtocolStub = class {
|
|
8986
9013
|
static async newSession(options) {
|
|
8987
9014
|
const capabilities = emulateSessionCapabilities(options.capabilities);
|
|
8988
|
-
const
|
|
9015
|
+
const browser = {
|
|
8989
9016
|
options,
|
|
8990
9017
|
capabilities,
|
|
8991
9018
|
requestedCapabilities: capabilities,
|
|
@@ -9001,9 +9028,9 @@ var ProtocolStub = class {
|
|
|
9001
9028
|
overwriteCommand: NOOP2,
|
|
9002
9029
|
...capabilitiesEnvironmentDetector(capabilities)
|
|
9003
9030
|
};
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
return
|
|
9031
|
+
browser.addCommand = (...args) => browser.customCommands.push(args);
|
|
9032
|
+
browser.overwriteCommand = (...args) => browser.overwrittenCommands.push(args);
|
|
9033
|
+
return browser;
|
|
9007
9034
|
}
|
|
9008
9035
|
/**
|
|
9009
9036
|
* added just in case user wants to somehow reload webdriver before it was started.
|
|
@@ -9053,7 +9080,7 @@ async function getProtocolDriver(options) {
|
|
|
9053
9080
|
var Key2 = Key;
|
|
9054
9081
|
var SevereServiceError2 = SevereServiceError;
|
|
9055
9082
|
var remote = async function(params, remoteModifier) {
|
|
9056
|
-
const keysToKeep = Object.keys(
|
|
9083
|
+
const keysToKeep = Object.keys(environment.value.variables.WDIO_WORKER_ID ? params : DEFAULTS);
|
|
9057
9084
|
const config = validateConfig(WDIO_DEFAULTS, params, keysToKeep);
|
|
9058
9085
|
await enableFileLogging(config.outputDir);
|
|
9059
9086
|
logger27.setLogLevelsConfig(config.logLevels, config.logLevel);
|