webdriverio 9.16.0 → 9.17.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/environment.d.ts +6 -0
- package/build/environment.d.ts.map +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +332 -316
- package/build/middlewares.d.ts.map +1 -1
- package/build/node.d.ts.map +1 -1
- package/build/node.js +371 -353
- 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/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
|
|
|
@@ -3711,7 +3715,7 @@ function parseOverwrite(overwrite, request) {
|
|
|
3711
3715
|
const result = {};
|
|
3712
3716
|
if ("body" in overwrite && overwrite.body) {
|
|
3713
3717
|
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:
|
|
3718
|
+
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
3719
|
}
|
|
3716
3720
|
if ("headers" in overwrite) {
|
|
3717
3721
|
const headersOverwrite = typeof overwrite.headers === "function" ? overwrite.headers(request) : overwrite.headers;
|
|
@@ -3766,7 +3770,7 @@ var log6 = logger6("WebDriverInterception");
|
|
|
3766
3770
|
var hasSubscribedToEvents = false;
|
|
3767
3771
|
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
3772
|
var _WebDriverInterception = class _WebDriverInterception {
|
|
3769
|
-
constructor(pattern, mockId, filterOptions,
|
|
3773
|
+
constructor(pattern, mockId, filterOptions, browser) {
|
|
3770
3774
|
__privateAdd(this, _WebDriverInterception_instances);
|
|
3771
3775
|
__privateAdd(this, _pattern);
|
|
3772
3776
|
__privateAdd(this, _mockId);
|
|
@@ -3787,14 +3791,14 @@ var _WebDriverInterception = class _WebDriverInterception {
|
|
|
3787
3791
|
__privateSet(this, _pattern, pattern);
|
|
3788
3792
|
__privateSet(this, _mockId, mockId);
|
|
3789
3793
|
__privateSet(this, _filterOptions, filterOptions);
|
|
3790
|
-
__privateSet(this, _browser4,
|
|
3791
|
-
|
|
3792
|
-
|
|
3794
|
+
__privateSet(this, _browser4, browser);
|
|
3795
|
+
browser.on("network.beforeRequestSent", __privateMethod(this, _WebDriverInterception_instances, handleBeforeRequestSent_fn).bind(this));
|
|
3796
|
+
browser.on("network.responseStarted", __privateMethod(this, _WebDriverInterception_instances, handleResponseStarted_fn).bind(this));
|
|
3793
3797
|
}
|
|
3794
|
-
static async initiate(url2, filterOptions,
|
|
3798
|
+
static async initiate(url2, filterOptions, browser) {
|
|
3795
3799
|
const pattern = parseUrlPattern(url2);
|
|
3796
3800
|
if (!hasSubscribedToEvents) {
|
|
3797
|
-
await
|
|
3801
|
+
await browser.sessionSubscribe({
|
|
3798
3802
|
events: [
|
|
3799
3803
|
"network.beforeRequestSent",
|
|
3800
3804
|
"network.responseStarted"
|
|
@@ -3803,7 +3807,7 @@ var _WebDriverInterception = class _WebDriverInterception {
|
|
|
3803
3807
|
log6.info("subscribed to network events");
|
|
3804
3808
|
hasSubscribedToEvents = true;
|
|
3805
3809
|
}
|
|
3806
|
-
const interception = await
|
|
3810
|
+
const interception = await browser.networkAddIntercept({
|
|
3807
3811
|
phases: ["beforeRequestSent", "responseStarted"],
|
|
3808
3812
|
urlPatterns: [{
|
|
3809
3813
|
type: "pattern",
|
|
@@ -3814,7 +3818,7 @@ var _WebDriverInterception = class _WebDriverInterception {
|
|
|
3814
3818
|
search: getPatternParam(pattern, "search")
|
|
3815
3819
|
}]
|
|
3816
3820
|
});
|
|
3817
|
-
return new _WebDriverInterception(pattern, interception.intercept, filterOptions,
|
|
3821
|
+
return new _WebDriverInterception(pattern, interception.intercept, filterOptions, browser);
|
|
3818
3822
|
}
|
|
3819
3823
|
/**
|
|
3820
3824
|
* Get the raw binary data for a mock response by request ID
|
|
@@ -4150,8 +4154,8 @@ async function mock(url2, filterOptions) {
|
|
|
4150
4154
|
if (!this.isBidi) {
|
|
4151
4155
|
throw new Error("Mocking is only supported when running tests using WebDriver Bidi");
|
|
4152
4156
|
}
|
|
4153
|
-
const
|
|
4154
|
-
const contextManager = getContextManager(
|
|
4157
|
+
const browser = getBrowserObject6(this);
|
|
4158
|
+
const contextManager = getContextManager(browser);
|
|
4155
4159
|
const context = await contextManager.getCurrentContext();
|
|
4156
4160
|
if (!SESSION_MOCKS[context]) {
|
|
4157
4161
|
SESSION_MOCKS[context] = /* @__PURE__ */ new Set();
|
|
@@ -4314,19 +4318,19 @@ import logger12 from "@wdio/logger";
|
|
|
4314
4318
|
|
|
4315
4319
|
// src/session/polyfill.ts
|
|
4316
4320
|
import logger10 from "@wdio/logger";
|
|
4317
|
-
function getPolyfillManager(
|
|
4318
|
-
return SessionManager.getSessionManager(
|
|
4321
|
+
function getPolyfillManager(browser) {
|
|
4322
|
+
return SessionManager.getSessionManager(browser, PolyfillManager);
|
|
4319
4323
|
}
|
|
4320
4324
|
var log10 = logger10("webdriverio:PolyfillManager");
|
|
4321
4325
|
var _initialize, _browser5, _scriptsRegisteredInContexts, _PolyfillManager_instances, registerScripts_fn;
|
|
4322
4326
|
var _PolyfillManager = class _PolyfillManager extends SessionManager {
|
|
4323
|
-
constructor(
|
|
4324
|
-
super(
|
|
4327
|
+
constructor(browser) {
|
|
4328
|
+
super(browser, _PolyfillManager.name);
|
|
4325
4329
|
__privateAdd(this, _PolyfillManager_instances);
|
|
4326
4330
|
__privateAdd(this, _initialize);
|
|
4327
4331
|
__privateAdd(this, _browser5);
|
|
4328
4332
|
__privateAdd(this, _scriptsRegisteredInContexts, /* @__PURE__ */ new Set());
|
|
4329
|
-
__privateSet(this, _browser5,
|
|
4333
|
+
__privateSet(this, _browser5, browser);
|
|
4330
4334
|
if (!this.isEnabled()) {
|
|
4331
4335
|
__privateSet(this, _initialize, Promise.resolve(true));
|
|
4332
4336
|
return;
|
|
@@ -4413,20 +4417,20 @@ function customElementWrapper() {
|
|
|
4413
4417
|
|
|
4414
4418
|
// src/session/shadowRoot.ts
|
|
4415
4419
|
var log11 = logger11("webdriverio:ShadowRootManager");
|
|
4416
|
-
function getShadowRootManager(
|
|
4417
|
-
return SessionManager.getSessionManager(
|
|
4420
|
+
function getShadowRootManager(browser) {
|
|
4421
|
+
return SessionManager.getSessionManager(browser, ShadowRootManager);
|
|
4418
4422
|
}
|
|
4419
4423
|
var _browser6, _initialize2, _shadowRoots, _documentElement, _frameDepth, _ShadowRootManager_instances, handleBidiCommand_fn, commandResultHandler_fn;
|
|
4420
4424
|
var _ShadowRootManager = class _ShadowRootManager extends SessionManager {
|
|
4421
|
-
constructor(
|
|
4422
|
-
super(
|
|
4425
|
+
constructor(browser) {
|
|
4426
|
+
super(browser, _ShadowRootManager.name);
|
|
4423
4427
|
__privateAdd(this, _ShadowRootManager_instances);
|
|
4424
4428
|
__privateAdd(this, _browser6);
|
|
4425
4429
|
__privateAdd(this, _initialize2);
|
|
4426
4430
|
__privateAdd(this, _shadowRoots, /* @__PURE__ */ new Map());
|
|
4427
4431
|
__privateAdd(this, _documentElement);
|
|
4428
4432
|
__privateAdd(this, _frameDepth, 0);
|
|
4429
|
-
__privateSet(this, _browser6,
|
|
4433
|
+
__privateSet(this, _browser6, browser);
|
|
4430
4434
|
if (!this.isEnabled()) {
|
|
4431
4435
|
__privateSet(this, _initialize2, Promise.resolve(true));
|
|
4432
4436
|
return;
|
|
@@ -4691,21 +4695,21 @@ var ShadowRootTree = class _ShadowRootTree {
|
|
|
4691
4695
|
};
|
|
4692
4696
|
|
|
4693
4697
|
// src/session/networkManager.ts
|
|
4694
|
-
function getNetworkManager(
|
|
4695
|
-
return SessionManager.getSessionManager(
|
|
4698
|
+
function getNetworkManager(browser) {
|
|
4699
|
+
return SessionManager.getSessionManager(browser, NetworkManager);
|
|
4696
4700
|
}
|
|
4697
4701
|
var UNKNOWN_NAVIGATION_ID = "UNKNOWN_NAVIGATION_ID";
|
|
4698
4702
|
var SUPPORTED_NAVIGATION_PROTOCOLS = ["http", "https", "data", "file"];
|
|
4699
4703
|
var _browser7, _initialize3, _requests, _lastNetworkId, _NetworkManager_instances, beforeRequestSent_fn, navigationStarted_fn, fetchError_fn, findRootRequest_fn, responseCompleted_fn;
|
|
4700
4704
|
var _NetworkManager = class _NetworkManager extends SessionManager {
|
|
4701
|
-
constructor(
|
|
4702
|
-
super(
|
|
4705
|
+
constructor(browser) {
|
|
4706
|
+
super(browser, _NetworkManager.name);
|
|
4703
4707
|
__privateAdd(this, _NetworkManager_instances);
|
|
4704
4708
|
__privateAdd(this, _browser7);
|
|
4705
4709
|
__privateAdd(this, _initialize3);
|
|
4706
4710
|
__privateAdd(this, _requests, /* @__PURE__ */ new Map());
|
|
4707
4711
|
__privateAdd(this, _lastNetworkId);
|
|
4708
|
-
__privateSet(this, _browser7,
|
|
4712
|
+
__privateSet(this, _browser7, browser);
|
|
4709
4713
|
if (!this.isEnabled()) {
|
|
4710
4714
|
__privateSet(this, _initialize3, Promise.resolve(true));
|
|
4711
4715
|
return;
|
|
@@ -4892,18 +4896,18 @@ function headerListToObject(headers) {
|
|
|
4892
4896
|
}
|
|
4893
4897
|
|
|
4894
4898
|
// src/session/dialog.ts
|
|
4895
|
-
function getDialogManager(
|
|
4896
|
-
return SessionManager.getSessionManager(
|
|
4899
|
+
function getDialogManager(browser) {
|
|
4900
|
+
return SessionManager.getSessionManager(browser, DialogManager);
|
|
4897
4901
|
}
|
|
4898
4902
|
var _browser8, _initialize4, _autoHandleDialog, _DialogManager_instances, handleUserPrompt_fn, switchListenerFlag_fn;
|
|
4899
4903
|
var _DialogManager = class _DialogManager extends SessionManager {
|
|
4900
|
-
constructor(
|
|
4901
|
-
super(
|
|
4904
|
+
constructor(browser) {
|
|
4905
|
+
super(browser, _DialogManager.name);
|
|
4902
4906
|
__privateAdd(this, _DialogManager_instances);
|
|
4903
4907
|
__privateAdd(this, _browser8);
|
|
4904
4908
|
__privateAdd(this, _initialize4);
|
|
4905
4909
|
__privateAdd(this, _autoHandleDialog, true);
|
|
4906
|
-
__privateSet(this, _browser8,
|
|
4910
|
+
__privateSet(this, _browser8, browser);
|
|
4907
4911
|
if (!this.isEnabled()) {
|
|
4908
4912
|
__privateSet(this, _initialize4, Promise.resolve(true));
|
|
4909
4913
|
return;
|
|
@@ -4950,7 +4954,7 @@ switchListenerFlag_fn = function(value) {
|
|
|
4950
4954
|
var DialogManager = _DialogManager;
|
|
4951
4955
|
var _browser9, _context, _message, _defaultValue, _type2;
|
|
4952
4956
|
var Dialog = class {
|
|
4953
|
-
constructor(event,
|
|
4957
|
+
constructor(event, browser) {
|
|
4954
4958
|
__privateAdd(this, _browser9);
|
|
4955
4959
|
__privateAdd(this, _context);
|
|
4956
4960
|
__privateAdd(this, _message);
|
|
@@ -4960,7 +4964,7 @@ var Dialog = class {
|
|
|
4960
4964
|
__privateSet(this, _defaultValue, event.defaultValue);
|
|
4961
4965
|
__privateSet(this, _type2, event.type);
|
|
4962
4966
|
__privateSet(this, _context, event.context);
|
|
4963
|
-
__privateSet(this, _browser9,
|
|
4967
|
+
__privateSet(this, _browser9, browser);
|
|
4964
4968
|
}
|
|
4965
4969
|
message() {
|
|
4966
4970
|
return __privateGet(this, _message);
|
|
@@ -5177,8 +5181,8 @@ async function setWindowSize(width, height) {
|
|
|
5177
5181
|
if (width < minWindowSize2 || width > maxWindowSize2 || height < minWindowSize2 || height > maxWindowSize2) {
|
|
5178
5182
|
throw new Error("setWindowSize expects width and height to be a number in the 0 to 2^31 \u2212 1 range");
|
|
5179
5183
|
}
|
|
5180
|
-
const
|
|
5181
|
-
await
|
|
5184
|
+
const browser = getBrowserObject7(this);
|
|
5185
|
+
await browser.setWindowRect(null, null, width, height);
|
|
5182
5186
|
}
|
|
5183
5187
|
|
|
5184
5188
|
// src/commands/browser/switchWindow.ts
|
|
@@ -5257,28 +5261,31 @@ async function switchFrame(context) {
|
|
|
5257
5261
|
return handle;
|
|
5258
5262
|
}
|
|
5259
5263
|
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
|
-
|
|
5264
|
+
const newContextId = await this.waitUntil(async () => {
|
|
5265
|
+
const tree = await this.browsingContextGetTree({});
|
|
5266
|
+
const urlContext = sessionContext.findContext(context, tree.contexts, "byUrl") || /**
|
|
5267
|
+
* In case the user provides an url without `/` at the end, e.g. `https://example.com`,
|
|
5268
|
+
* the `browsingContextGetTree` command may return a context with the url `https://example.com/`.
|
|
5269
|
+
*/
|
|
5270
|
+
sessionContext.findContext("".concat(context, "/"), tree.contexts, "byUrl");
|
|
5271
|
+
const urlContextContaining = sessionContext.findContext(context, tree.contexts, "byUrlContaining");
|
|
5272
|
+
const contextIdContext = sessionContext.findContext(context, tree.contexts, "byContextId");
|
|
5273
|
+
if (urlContext) {
|
|
5274
|
+
log14.info('Found context by url "'.concat(urlContext.url, '" with context id "').concat(urlContext.context, '"'));
|
|
5275
|
+
return urlContext.context;
|
|
5276
|
+
} else if (urlContextContaining) {
|
|
5277
|
+
log14.info('Found context by url containing "'.concat(urlContextContaining.url, '" with context id "').concat(urlContextContaining.context, '"'));
|
|
5278
|
+
return urlContextContaining.context;
|
|
5279
|
+
} else if (contextIdContext) {
|
|
5280
|
+
log14.info('Found context by id "'.concat(contextIdContext, '" with url "').concat(contextIdContext.url, '"'));
|
|
5281
|
+
return contextIdContext.context;
|
|
5282
|
+
}
|
|
5283
|
+
return false;
|
|
5284
|
+
}, {
|
|
5285
|
+
timeout: this.options.waitforTimeout,
|
|
5286
|
+
interval: this.options.waitforInterval,
|
|
5287
|
+
timeoutMsg: 'No frame with url or id "'.concat(context, '" found within the timeout')
|
|
5288
|
+
});
|
|
5282
5289
|
const currentContext = await sessionContext.getCurrentContext();
|
|
5283
5290
|
const allContexts = await sessionContext.getFlatContextTree();
|
|
5284
5291
|
const allFrames = (await Promise.all(Object.keys(allContexts).map(async (id) => {
|
|
@@ -5358,48 +5365,57 @@ async function switchFrame(context) {
|
|
|
5358
5365
|
return switchToFrameUsingElement(this, element);
|
|
5359
5366
|
}
|
|
5360
5367
|
if (typeof context === "function") {
|
|
5361
|
-
const
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
const
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5368
|
+
const foundContextId = await this.waitUntil(async () => {
|
|
5369
|
+
const allContexts = await sessionContext.getFlatContextTree();
|
|
5370
|
+
const allContextIds = Object.keys(allContexts);
|
|
5371
|
+
for (const contextId of allContextIds) {
|
|
5372
|
+
const functionDeclaration = new Function("\n return (".concat(SCRIPT_PREFIX).concat(context.toString()).concat(SCRIPT_SUFFIX, ").apply(this, arguments);\n ")).toString();
|
|
5373
|
+
const params = {
|
|
5374
|
+
functionDeclaration,
|
|
5375
|
+
awaitPromise: false,
|
|
5376
|
+
arguments: [],
|
|
5377
|
+
target: { context: contextId }
|
|
5378
|
+
};
|
|
5379
|
+
const result = await this.scriptCallFunction(params).catch((err) => {
|
|
5380
|
+
log14.warn("switchFrame context callback threw error: ".concat(err.message));
|
|
5381
|
+
return void 0;
|
|
5382
|
+
});
|
|
5383
|
+
if (result && result.type === "success" && result.result.type === "boolean" && result.result.value) {
|
|
5384
|
+
return contextId;
|
|
5385
|
+
}
|
|
5374
5386
|
}
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5387
|
+
return false;
|
|
5388
|
+
}, {
|
|
5389
|
+
timeout: this.options.waitforTimeout,
|
|
5390
|
+
interval: this.options.waitforInterval,
|
|
5391
|
+
timeoutMsg: "Could not find the desired frame within the timeout"
|
|
5392
|
+
});
|
|
5393
|
+
await this.switchFrame(null);
|
|
5394
|
+
await this.switchFrame(foundContextId);
|
|
5395
|
+
return foundContextId;
|
|
5380
5396
|
}
|
|
5381
5397
|
throw new Error(
|
|
5382
5398
|
"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
5399
|
);
|
|
5384
5400
|
}
|
|
5385
|
-
function switchToFrameHelper(
|
|
5386
|
-
const sessionContext = getContextManager(
|
|
5401
|
+
function switchToFrameHelper(browser, context) {
|
|
5402
|
+
const sessionContext = getContextManager(browser);
|
|
5387
5403
|
sessionContext.setCurrentContext(context);
|
|
5388
5404
|
}
|
|
5389
|
-
async function switchToFrameUsingElement(
|
|
5390
|
-
const frame = await
|
|
5405
|
+
async function switchToFrameUsingElement(browser, element) {
|
|
5406
|
+
const frame = await browser.execute(
|
|
5391
5407
|
(iframe) => iframe.contentWindow,
|
|
5392
5408
|
element
|
|
5393
5409
|
);
|
|
5394
|
-
switchToFrameHelper(
|
|
5410
|
+
switchToFrameHelper(browser, frame.context);
|
|
5395
5411
|
const elementId = element[ELEMENT_KEY8];
|
|
5396
|
-
await switchToFrame(
|
|
5412
|
+
await switchToFrame(browser, { [ELEMENT_KEY8]: elementId });
|
|
5397
5413
|
return frame.context;
|
|
5398
5414
|
}
|
|
5399
|
-
function switchToFrame(
|
|
5400
|
-
|
|
5401
|
-
return
|
|
5402
|
-
delete
|
|
5415
|
+
function switchToFrame(browser, frame) {
|
|
5416
|
+
environment.value.variables.DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS = "true";
|
|
5417
|
+
return browser.switchToFrame(frame).finally(async () => {
|
|
5418
|
+
delete environment.value.variables.DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS;
|
|
5403
5419
|
});
|
|
5404
5420
|
}
|
|
5405
5421
|
|
|
@@ -5409,8 +5425,8 @@ import { getBrowserObject as getBrowserObject8 } from "@wdio/utils";
|
|
|
5409
5425
|
var log15 = logger15("webdriverio:throttle");
|
|
5410
5426
|
async function throttle(params) {
|
|
5411
5427
|
log15.warn('Command "throttle" is deprecated and will be removed with the next major version release! Use `throttleNetwork` instead.');
|
|
5412
|
-
const
|
|
5413
|
-
await
|
|
5428
|
+
const browser = getBrowserObject8(this);
|
|
5429
|
+
await browser.throttleNetwork(params);
|
|
5414
5430
|
}
|
|
5415
5431
|
|
|
5416
5432
|
// src/commands/browser/throttleCPU.ts
|
|
@@ -5509,8 +5525,8 @@ async function throttleNetwork(params) {
|
|
|
5509
5525
|
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
5526
|
}
|
|
5511
5527
|
if (this.isSauce) {
|
|
5512
|
-
const
|
|
5513
|
-
await
|
|
5528
|
+
const browser = getBrowserObject9(this);
|
|
5529
|
+
await browser.sauceThrottleNetwork(params);
|
|
5514
5530
|
return;
|
|
5515
5531
|
}
|
|
5516
5532
|
const failedConnectionMessage = "No Puppeteer connection could be established which is required to use this command";
|
|
@@ -5640,14 +5656,14 @@ function waitUntil(condition, {
|
|
|
5640
5656
|
if (typeof interval !== "number") {
|
|
5641
5657
|
interval = this.options.waitforInterval;
|
|
5642
5658
|
}
|
|
5643
|
-
const
|
|
5659
|
+
const browser = getBrowserObject10(this);
|
|
5644
5660
|
const abort = new AbortController();
|
|
5645
5661
|
const abortOnSessionEnd = (result) => {
|
|
5646
5662
|
if (result.command === "deleteSession") {
|
|
5647
5663
|
abort.abort();
|
|
5648
5664
|
}
|
|
5649
5665
|
};
|
|
5650
|
-
|
|
5666
|
+
browser.on("result", abortOnSessionEnd);
|
|
5651
5667
|
const fn = condition.bind(this);
|
|
5652
5668
|
const timer = new Timer_default(interval, timeout, fn, true, abort.signal);
|
|
5653
5669
|
return timer.catch((e) => {
|
|
@@ -5671,7 +5687,7 @@ function waitUntil(condition, {
|
|
|
5671
5687
|
].filter((errorLine) => !errorLine.includes("/node_modules/webdriverio/") && !errorLine.includes("/node_modules/@wdio/")).join("\n");
|
|
5672
5688
|
throw err;
|
|
5673
5689
|
}).finally(() => {
|
|
5674
|
-
|
|
5690
|
+
browser.off("result", abortOnSessionEnd);
|
|
5675
5691
|
});
|
|
5676
5692
|
}
|
|
5677
5693
|
|
|
@@ -5695,8 +5711,8 @@ var SWIPE_DEFAULTS = {
|
|
|
5695
5711
|
PERCENT: 0.95
|
|
5696
5712
|
};
|
|
5697
5713
|
async function swipe(options) {
|
|
5698
|
-
const
|
|
5699
|
-
if (!
|
|
5714
|
+
const browser = this;
|
|
5715
|
+
if (!browser.isNativeContext) {
|
|
5700
5716
|
throw new Error("The swipe command is only available for mobile platforms in the NATIVE context.");
|
|
5701
5717
|
}
|
|
5702
5718
|
let { scrollableElement, from, to } = options || {};
|
|
@@ -5704,18 +5720,18 @@ async function swipe(options) {
|
|
|
5704
5720
|
log16.warn("`scrollableElement` is provided, so `from` and `to` will be ignored.");
|
|
5705
5721
|
}
|
|
5706
5722
|
if (!from || !to) {
|
|
5707
|
-
scrollableElement = scrollableElement || await getScrollableElement(
|
|
5723
|
+
scrollableElement = scrollableElement || await getScrollableElement(browser);
|
|
5708
5724
|
({ from, to } = await calculateFromTo({
|
|
5709
|
-
browser
|
|
5725
|
+
browser,
|
|
5710
5726
|
direction: (options == null ? void 0 : options.direction) || SWIPE_DEFAULTS.DIRECTION,
|
|
5711
5727
|
percentage: options == null ? void 0 : options.percent,
|
|
5712
5728
|
scrollableElement
|
|
5713
5729
|
}));
|
|
5714
5730
|
}
|
|
5715
|
-
return w3cSwipe({ browser
|
|
5731
|
+
return w3cSwipe({ browser, duration: (options == null ? void 0 : options.duration) || SWIPE_DEFAULTS.DURATION, from, to });
|
|
5716
5732
|
}
|
|
5717
5733
|
async function calculateFromTo({
|
|
5718
|
-
browser
|
|
5734
|
+
browser,
|
|
5719
5735
|
direction,
|
|
5720
5736
|
percentage,
|
|
5721
5737
|
scrollableElement
|
|
@@ -5730,7 +5746,7 @@ async function calculateFromTo({
|
|
|
5730
5746
|
swipePercentage = percentage;
|
|
5731
5747
|
}
|
|
5732
5748
|
}
|
|
5733
|
-
const { x, y, width, height } = await
|
|
5749
|
+
const { x, y, width, height } = await browser.getElementRect(await (scrollableElement == null ? void 0 : scrollableElement.elementId));
|
|
5734
5750
|
const verticalOffset = height - height * swipePercentage;
|
|
5735
5751
|
const horizontalOffset = width - width * swipePercentage;
|
|
5736
5752
|
const scrollRectangles = {
|
|
@@ -5763,31 +5779,31 @@ async function calculateFromTo({
|
|
|
5763
5779
|
}
|
|
5764
5780
|
return { from, to };
|
|
5765
5781
|
}
|
|
5766
|
-
async function getScrollableElement(
|
|
5782
|
+
async function getScrollableElement(browser) {
|
|
5767
5783
|
const defaultAndroidSelector = "//android.widget.ScrollView";
|
|
5768
5784
|
const defaultIosSelector = '-ios predicate string:type == "XCUIElementTypeApplication"';
|
|
5769
|
-
const selector =
|
|
5785
|
+
const selector = browser.isIOS ? (
|
|
5770
5786
|
// For iOS, we need to find the application element, if we can't find it, we should throw an error
|
|
5771
5787
|
defaultIosSelector
|
|
5772
5788
|
) : (
|
|
5773
5789
|
// There is always a scrollview for Android or, if this fails we should throw an error
|
|
5774
5790
|
defaultAndroidSelector
|
|
5775
5791
|
);
|
|
5776
|
-
const scrollableElements = await
|
|
5792
|
+
const scrollableElements = await browser.$$(
|
|
5777
5793
|
selector
|
|
5778
5794
|
);
|
|
5779
5795
|
if (scrollableElements.length > 0) {
|
|
5780
5796
|
return scrollableElements[0];
|
|
5781
5797
|
}
|
|
5782
5798
|
throw new Error(
|
|
5783
|
-
"Default scrollable element '".concat(
|
|
5799
|
+
"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
5800
|
);
|
|
5785
5801
|
}
|
|
5786
|
-
async function w3cSwipe({ browser
|
|
5787
|
-
await
|
|
5788
|
-
parameters: { pointerType:
|
|
5802
|
+
async function w3cSwipe({ browser, duration, from, to }) {
|
|
5803
|
+
await browser.action("pointer", {
|
|
5804
|
+
parameters: { pointerType: browser.isMobile ? "touch" : "mouse" }
|
|
5789
5805
|
}).move(from.x, from.y).down().pause(10).move({ duration, x: to.x, y: to.y }).up().perform();
|
|
5790
|
-
return
|
|
5806
|
+
return browser.pause(500);
|
|
5791
5807
|
}
|
|
5792
5808
|
|
|
5793
5809
|
// src/commands/mobile/tap.ts
|
|
@@ -5797,18 +5813,18 @@ var log17 = logger17("webdriver");
|
|
|
5797
5813
|
async function tap(options) {
|
|
5798
5814
|
const isElement2 = this.selector !== void 0;
|
|
5799
5815
|
const element = isElement2 ? this : null;
|
|
5800
|
-
const
|
|
5801
|
-
if (!
|
|
5816
|
+
const browser = isElement2 ? getBrowserObject11(this) : this;
|
|
5817
|
+
if (!browser.isMobile) {
|
|
5802
5818
|
throw new Error("The tap command is only available for mobile platforms.");
|
|
5803
5819
|
}
|
|
5804
5820
|
validateTapOptions(options);
|
|
5805
5821
|
if (element) {
|
|
5806
|
-
return await elementTap(
|
|
5822
|
+
return await elementTap(browser, element, options);
|
|
5807
5823
|
}
|
|
5808
5824
|
if (!options || options.x === void 0 || options.y === void 0) {
|
|
5809
5825
|
throw new Error("The tap command requires x and y coordinates to be set for screen taps.");
|
|
5810
5826
|
}
|
|
5811
|
-
return await screenTap(
|
|
5827
|
+
return await screenTap(browser, options);
|
|
5812
5828
|
}
|
|
5813
5829
|
function validateTapOptions(options) {
|
|
5814
5830
|
if (options) {
|
|
@@ -5834,9 +5850,9 @@ function validateTapOptions(options) {
|
|
|
5834
5850
|
}
|
|
5835
5851
|
}
|
|
5836
5852
|
}
|
|
5837
|
-
async function elementTap(
|
|
5838
|
-
if (
|
|
5839
|
-
return await nativeTap(element,
|
|
5853
|
+
async function elementTap(browser, element, options) {
|
|
5854
|
+
if (browser.isNativeContext) {
|
|
5855
|
+
return await nativeTap(element, browser, options);
|
|
5840
5856
|
}
|
|
5841
5857
|
if (options) {
|
|
5842
5858
|
log17.warn("The options object is not supported in Web environments and will be ignored.");
|
|
@@ -5846,18 +5862,18 @@ async function elementTap(browser2, element, options) {
|
|
|
5846
5862
|
async function webTap(element) {
|
|
5847
5863
|
return element.click();
|
|
5848
5864
|
}
|
|
5849
|
-
async function executeNativeTap(
|
|
5850
|
-
return await
|
|
5851
|
-
"mobile: ".concat(
|
|
5852
|
-
{ ...
|
|
5865
|
+
async function executeNativeTap(browser, options) {
|
|
5866
|
+
return await browser.execute(
|
|
5867
|
+
"mobile: ".concat(browser.isIOS ? "tap" : "clickGesture"),
|
|
5868
|
+
{ ...browser.isIOS ? { x: 0, y: 0 } : {}, ...options }
|
|
5853
5869
|
);
|
|
5854
5870
|
}
|
|
5855
|
-
async function nativeTap(element,
|
|
5871
|
+
async function nativeTap(element, browser, options = {}) {
|
|
5856
5872
|
try {
|
|
5857
5873
|
if (!element.elementId) {
|
|
5858
5874
|
throw new Error("no such element");
|
|
5859
5875
|
}
|
|
5860
|
-
return await executeNativeTap(
|
|
5876
|
+
return await executeNativeTap(browser, { elementId: element.elementId });
|
|
5861
5877
|
} catch (error) {
|
|
5862
5878
|
let err = error;
|
|
5863
5879
|
if (typeof error === "string") {
|
|
@@ -5875,7 +5891,7 @@ async function nativeTap(element, browser2, options = {}) {
|
|
|
5875
5891
|
);
|
|
5876
5892
|
try {
|
|
5877
5893
|
await element.scrollIntoView(scrollIntoViewOptions);
|
|
5878
|
-
return await executeNativeTap(
|
|
5894
|
+
return await executeNativeTap(browser, { elementId: element.elementId });
|
|
5879
5895
|
} catch (scrollError) {
|
|
5880
5896
|
let err2 = scrollError;
|
|
5881
5897
|
if (typeof scrollError === "string") {
|
|
@@ -5892,12 +5908,12 @@ async function nativeTap(element, browser2, options = {}) {
|
|
|
5892
5908
|
}
|
|
5893
5909
|
}
|
|
5894
5910
|
}
|
|
5895
|
-
async function screenTap(
|
|
5911
|
+
async function screenTap(browser, options) {
|
|
5896
5912
|
const { x, y } = options;
|
|
5897
|
-
if (
|
|
5898
|
-
return await executeNativeTap(
|
|
5913
|
+
if (browser.isNativeContext) {
|
|
5914
|
+
return await executeNativeTap(browser, options);
|
|
5899
5915
|
}
|
|
5900
|
-
return await
|
|
5916
|
+
return await browser.action(
|
|
5901
5917
|
"pointer",
|
|
5902
5918
|
{
|
|
5903
5919
|
parameters: { pointerType: "touch" }
|
|
@@ -5909,19 +5925,19 @@ async function screenTap(browser2, options) {
|
|
|
5909
5925
|
import logger18 from "@wdio/logger";
|
|
5910
5926
|
var log18 = logger18("webdriver");
|
|
5911
5927
|
async function getContext(options) {
|
|
5912
|
-
const
|
|
5913
|
-
if (!
|
|
5928
|
+
const browser = this;
|
|
5929
|
+
if (!browser.isMobile) {
|
|
5914
5930
|
throw new Error("The `getContext` command is only available for mobile platforms.");
|
|
5915
5931
|
}
|
|
5916
|
-
const currentAppiumContext = await
|
|
5932
|
+
const currentAppiumContext = await browser.getAppiumContext();
|
|
5917
5933
|
if (!options || !(options == null ? void 0 : options.returnDetailedContext) || currentAppiumContext === "NATIVE_APP") {
|
|
5918
5934
|
return currentAppiumContext;
|
|
5919
5935
|
}
|
|
5920
5936
|
delete options.returnDetailedContext;
|
|
5921
|
-
return getDetailedContext(
|
|
5937
|
+
return getDetailedContext(browser, currentAppiumContext, options);
|
|
5922
5938
|
}
|
|
5923
|
-
async function getDetailedContext(
|
|
5924
|
-
const detailedContexts = await
|
|
5939
|
+
async function getDetailedContext(browser, currentAppiumContext, options) {
|
|
5940
|
+
const detailedContexts = await browser.getContexts({
|
|
5925
5941
|
...{ options },
|
|
5926
5942
|
// Defaults
|
|
5927
5943
|
returnDetailedContexts: true,
|
|
@@ -5948,13 +5964,13 @@ async function getDetailedContext(browser2, currentAppiumContext, options) {
|
|
|
5948
5964
|
import logger19 from "@wdio/logger";
|
|
5949
5965
|
var log19 = logger19("webdriver");
|
|
5950
5966
|
async function getContexts(options) {
|
|
5951
|
-
const
|
|
5952
|
-
if (!
|
|
5967
|
+
const browser = this;
|
|
5968
|
+
if (!browser.isMobile) {
|
|
5953
5969
|
throw new Error("The `getContexts` command is only available for mobile platforms.");
|
|
5954
5970
|
}
|
|
5955
5971
|
if (!options || !options.returnDetailedContexts) {
|
|
5956
5972
|
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
|
|
5973
|
+
return browser.getAppiumContexts();
|
|
5958
5974
|
}
|
|
5959
5975
|
const defaultOptions = {
|
|
5960
5976
|
androidWebviewConnectionRetryTime: 500,
|
|
@@ -5963,7 +5979,7 @@ async function getContexts(options) {
|
|
|
5963
5979
|
isAndroidWebviewVisible: true,
|
|
5964
5980
|
returnAndroidDescriptionData: false
|
|
5965
5981
|
};
|
|
5966
|
-
return getCurrentContexts({ browser
|
|
5982
|
+
return getCurrentContexts({ browser, ...{ ...defaultOptions, ...options } });
|
|
5967
5983
|
}
|
|
5968
5984
|
var CHROME_PACKAGE_NAME = "com.android.chrome";
|
|
5969
5985
|
async function parsedAndroidContexts({
|
|
@@ -6033,7 +6049,7 @@ async function parsedAndroidContexts({
|
|
|
6033
6049
|
return result;
|
|
6034
6050
|
}
|
|
6035
6051
|
async function getCurrentContexts({
|
|
6036
|
-
browser
|
|
6052
|
+
browser,
|
|
6037
6053
|
androidWebviewConnectionRetryTime,
|
|
6038
6054
|
androidWebviewConnectTimeout,
|
|
6039
6055
|
filterByCurrentAndroidApp,
|
|
@@ -6041,11 +6057,11 @@ async function getCurrentContexts({
|
|
|
6041
6057
|
returnAndroidDescriptionData
|
|
6042
6058
|
}) {
|
|
6043
6059
|
var _a;
|
|
6044
|
-
const contexts = await
|
|
6045
|
-
if (
|
|
6060
|
+
const contexts = await browser.execute("mobile: getContexts");
|
|
6061
|
+
if (browser.isIOS) {
|
|
6046
6062
|
return contexts;
|
|
6047
6063
|
}
|
|
6048
|
-
const packageName = await
|
|
6064
|
+
const packageName = await browser.getCurrentPackage();
|
|
6049
6065
|
const startTime = Date.now();
|
|
6050
6066
|
const retryInterval = androidWebviewConnectionRetryTime;
|
|
6051
6067
|
let isPackageNameMissing = false;
|
|
@@ -6084,8 +6100,8 @@ async function getCurrentContexts({
|
|
|
6084
6100
|
import logger20 from "@wdio/logger";
|
|
6085
6101
|
var log20 = logger20("webdriver");
|
|
6086
6102
|
async function switchContext(options) {
|
|
6087
|
-
const
|
|
6088
|
-
if (!
|
|
6103
|
+
const browser = this;
|
|
6104
|
+
if (!browser.isMobile) {
|
|
6089
6105
|
throw new Error("The `switchContext` command is only available for mobile platforms.");
|
|
6090
6106
|
}
|
|
6091
6107
|
if (!options) {
|
|
@@ -6093,14 +6109,14 @@ async function switchContext(options) {
|
|
|
6093
6109
|
}
|
|
6094
6110
|
if (typeof options === "string") {
|
|
6095
6111
|
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
|
|
6112
|
+
return browser.switchAppiumContext(options);
|
|
6097
6113
|
}
|
|
6098
6114
|
if (!options.title && !options.url) {
|
|
6099
6115
|
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
6116
|
}
|
|
6101
|
-
return switchToContext({ browser
|
|
6117
|
+
return switchToContext({ browser, options });
|
|
6102
6118
|
}
|
|
6103
|
-
async function switchToContext({ browser
|
|
6119
|
+
async function switchToContext({ browser, options }) {
|
|
6104
6120
|
var _a;
|
|
6105
6121
|
const getContextsOptions = {
|
|
6106
6122
|
returnDetailedContexts: true,
|
|
@@ -6110,19 +6126,19 @@ async function switchToContext({ browser: browser2, options }) {
|
|
|
6110
6126
|
...(options == null ? void 0 : options.androidWebviewConnectionRetryTime) && { androidWebviewConnectionRetryTime: options.androidWebviewConnectionRetryTime },
|
|
6111
6127
|
...(options == null ? void 0 : options.androidWebviewConnectTimeout) && { androidWebviewConnectTimeout: options.androidWebviewConnectTimeout }
|
|
6112
6128
|
};
|
|
6113
|
-
const contexts = await
|
|
6114
|
-
const identifier =
|
|
6115
|
-
const { matchingContext, reasons } = findMatchingContext({ browser
|
|
6129
|
+
const contexts = await browser.getContexts(getContextsOptions);
|
|
6130
|
+
const identifier = browser.isIOS ? (_a = await browser.execute("mobile: activeAppInfo")) == null ? void 0 : _a.bundleId : await browser.getCurrentPackage();
|
|
6131
|
+
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
6132
|
if (!matchingContext) {
|
|
6117
6133
|
throw new Error(reasons.join("\n"));
|
|
6118
6134
|
}
|
|
6119
6135
|
log20.info("WebdriverIO found a matching context:", JSON.stringify(matchingContext, null, 2));
|
|
6120
|
-
if (!
|
|
6136
|
+
if (!browser.isIOS) {
|
|
6121
6137
|
const webviewName = "WEBVIEW_".concat(identifier);
|
|
6122
|
-
await
|
|
6138
|
+
await browser.switchAppiumContext(webviewName);
|
|
6123
6139
|
}
|
|
6124
|
-
const switchFunction =
|
|
6125
|
-
const matchingContextId =
|
|
6140
|
+
const switchFunction = browser.isIOS ? browser.switchAppiumContext.bind(browser) : browser.switchToWindow.bind(browser);
|
|
6141
|
+
const matchingContextId = browser.isIOS ? matchingContext.id : matchingContext.webviewPageId;
|
|
6126
6142
|
return switchFunction(matchingContextId);
|
|
6127
6143
|
}
|
|
6128
6144
|
function findMatchingContext({
|
|
@@ -6164,42 +6180,42 @@ function findMatchingContext({
|
|
|
6164
6180
|
|
|
6165
6181
|
// src/commands/mobile/relaunchActiveApp.ts
|
|
6166
6182
|
async function relaunchActiveApp() {
|
|
6167
|
-
const
|
|
6168
|
-
if (!
|
|
6183
|
+
const browser = this;
|
|
6184
|
+
if (!browser.isMobile) {
|
|
6169
6185
|
throw new Error("The `relaunchActiveApp` command is only available for mobile platforms.");
|
|
6170
6186
|
}
|
|
6171
|
-
if (
|
|
6172
|
-
const { bundleId, processArguments: { args, env } } = await
|
|
6187
|
+
if (browser.isIOS) {
|
|
6188
|
+
const { bundleId, processArguments: { args, env } } = await browser.execute("mobile: activeAppInfo");
|
|
6173
6189
|
const iOSLaunchOptions = {
|
|
6174
6190
|
bundleId,
|
|
6175
6191
|
...args.length > 0 && { arguments: args },
|
|
6176
6192
|
...Object.keys(env).length > 0 && { environment: env }
|
|
6177
6193
|
};
|
|
6178
|
-
await
|
|
6179
|
-
return
|
|
6194
|
+
await browser.execute("mobile: terminateApp", { bundleId });
|
|
6195
|
+
return browser.execute("mobile:launchApp", iOSLaunchOptions);
|
|
6180
6196
|
}
|
|
6181
|
-
const packageName = await
|
|
6182
|
-
await
|
|
6183
|
-
return
|
|
6197
|
+
const packageName = await browser.getCurrentPackage();
|
|
6198
|
+
await browser.execute("mobile: terminateApp", { appId: packageName });
|
|
6199
|
+
return browser.execute("mobile: activateApp", { appId: packageName });
|
|
6184
6200
|
}
|
|
6185
6201
|
|
|
6186
6202
|
// src/commands/mobile/deepLink.ts
|
|
6187
6203
|
async function deepLink(link, appIdentifier) {
|
|
6188
|
-
const
|
|
6189
|
-
if (!
|
|
6204
|
+
const browser = this;
|
|
6205
|
+
if (!browser.isMobile) {
|
|
6190
6206
|
throw new Error("The `deepLink` command is only available for mobile platforms.");
|
|
6191
6207
|
}
|
|
6192
6208
|
if (!isDeepLinkUrl(link)) {
|
|
6193
|
-
throw new Error("The provided link is not a valid deep link URL.".concat(
|
|
6209
|
+
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
6210
|
}
|
|
6195
6211
|
if (!appIdentifier) {
|
|
6196
|
-
const mobileOS =
|
|
6197
|
-
const identifierValue =
|
|
6212
|
+
const mobileOS = browser.isIOS ? "iOS" : "Android";
|
|
6213
|
+
const identifierValue = browser.isIOS ? "bundleId" : "package";
|
|
6198
6214
|
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
6215
|
}
|
|
6200
|
-
return
|
|
6216
|
+
return browser.execute("mobile:deepLink", {
|
|
6201
6217
|
url: link,
|
|
6202
|
-
[
|
|
6218
|
+
[browser.isIOS ? "bundleId" : "package"]: appIdentifier
|
|
6203
6219
|
});
|
|
6204
6220
|
}
|
|
6205
6221
|
function isDeepLinkUrl(link) {
|
|
@@ -6340,9 +6356,9 @@ async function actionClick(element, options) {
|
|
|
6340
6356
|
if (!buttonValue.includes(button)) {
|
|
6341
6357
|
throw new Error("Button type not supported.");
|
|
6342
6358
|
}
|
|
6343
|
-
const
|
|
6359
|
+
const browser = getBrowserObject12(element);
|
|
6344
6360
|
if (x || y) {
|
|
6345
|
-
const { width, height } = await
|
|
6361
|
+
const { width, height } = await browser.getElementRect(element.elementId);
|
|
6346
6362
|
if (x && x < -Math.floor(width / 2) || x && x > Math.floor(width / 2)) {
|
|
6347
6363
|
log21.warn("x would cause a out of bounds error as it goes outside of element");
|
|
6348
6364
|
}
|
|
@@ -6351,8 +6367,8 @@ async function actionClick(element, options) {
|
|
|
6351
6367
|
}
|
|
6352
6368
|
}
|
|
6353
6369
|
const clickNested = async () => {
|
|
6354
|
-
await
|
|
6355
|
-
parameters: { pointerType:
|
|
6370
|
+
await browser.action("pointer", {
|
|
6371
|
+
parameters: { pointerType: browser.isMobile ? "touch" : "mouse" }
|
|
6356
6372
|
}).move({ origin: element, x, y }).down({ button }).pause(duration).up({ button }).perform(skipRelease);
|
|
6357
6373
|
};
|
|
6358
6374
|
try {
|
|
@@ -6411,8 +6427,8 @@ async function custom$2(strategyName, ...strategyArguments) {
|
|
|
6411
6427
|
// src/commands/element/doubleClick.ts
|
|
6412
6428
|
import { getBrowserObject as getBrowserObject15 } from "@wdio/utils";
|
|
6413
6429
|
async function doubleClick() {
|
|
6414
|
-
const
|
|
6415
|
-
return
|
|
6430
|
+
const browser = getBrowserObject15(this);
|
|
6431
|
+
return browser.action("pointer", { parameters: { pointerType: "mouse" } }).move({ origin: this }).down().up().pause(10).down().up().perform();
|
|
6416
6432
|
}
|
|
6417
6433
|
|
|
6418
6434
|
// src/commands/element/dragAndDrop.ts
|
|
@@ -6436,8 +6452,8 @@ async function dragAndDrop(target, options = {}) {
|
|
|
6436
6452
|
throw new Error('command dragAndDrop requires an WebdriverIO Element or and object with "x" and "y" variables as first parameter');
|
|
6437
6453
|
}
|
|
6438
6454
|
const ACTION_BUTTON = 0;
|
|
6439
|
-
const
|
|
6440
|
-
const defaultOptions = { duration:
|
|
6455
|
+
const browser = getBrowserObject16(this);
|
|
6456
|
+
const defaultOptions = { duration: browser.isMobile ? 250 : 10 };
|
|
6441
6457
|
const { duration } = { ...defaultOptions, ...options };
|
|
6442
6458
|
const isMovingToElement = moveToElement.constructor.name === "Element";
|
|
6443
6459
|
const sourceRef = { [ELEMENT_KEY11]: this[ELEMENT_KEY11] };
|
|
@@ -6446,8 +6462,8 @@ async function dragAndDrop(target, options = {}) {
|
|
|
6446
6462
|
const targetOrigin = isMovingToElement ? targetRef : "pointer";
|
|
6447
6463
|
const targetX = isMovingToElement ? 0 : moveToCoordinates.x;
|
|
6448
6464
|
const targetY = isMovingToElement ? 0 : moveToCoordinates.y;
|
|
6449
|
-
return
|
|
6450
|
-
parameters: { pointerType:
|
|
6465
|
+
return browser.action("pointer", {
|
|
6466
|
+
parameters: { pointerType: browser.isMobile ? "touch" : "mouse" }
|
|
6451
6467
|
}).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
6468
|
}
|
|
6453
6469
|
|
|
@@ -6455,17 +6471,17 @@ async function dragAndDrop(target, options = {}) {
|
|
|
6455
6471
|
import { getBrowserObject as getBrowserObject17 } from "@wdio/utils";
|
|
6456
6472
|
async function execute2(script, ...args) {
|
|
6457
6473
|
const scope = this;
|
|
6458
|
-
const
|
|
6474
|
+
const browser = getBrowserObject17(scope);
|
|
6459
6475
|
await scope.waitForExist();
|
|
6460
|
-
return
|
|
6476
|
+
return browser.execute(script, scope, ...args);
|
|
6461
6477
|
}
|
|
6462
6478
|
|
|
6463
6479
|
// src/commands/element/executeAsync.ts
|
|
6464
6480
|
import { getBrowserObject as getBrowserObject18 } from "@wdio/utils";
|
|
6465
6481
|
async function executeAsync2(script, ...args) {
|
|
6466
6482
|
const scope = this;
|
|
6467
|
-
const
|
|
6468
|
-
return
|
|
6483
|
+
const browser = getBrowserObject18(scope);
|
|
6484
|
+
return browser.executeAsync(script, scope, ...args);
|
|
6469
6485
|
}
|
|
6470
6486
|
|
|
6471
6487
|
// src/commands/element/getAttribute.ts
|
|
@@ -6539,9 +6555,9 @@ function mergeEqualSymmetricalValue(cssValues) {
|
|
|
6539
6555
|
return newCssValues.join(" ");
|
|
6540
6556
|
}
|
|
6541
6557
|
async function getPseudoElementCSSValue(elem, options) {
|
|
6542
|
-
const
|
|
6558
|
+
const browser = getBrowserObject19(elem);
|
|
6543
6559
|
const { cssProperty, pseudoElement } = options;
|
|
6544
|
-
const cssValue2 = await
|
|
6560
|
+
const cssValue2 = await browser.execute(
|
|
6545
6561
|
(elem2, pseudoElement2, cssProperty2) => window.getComputedStyle(elem2, pseudoElement2)[cssProperty2],
|
|
6546
6562
|
elem,
|
|
6547
6563
|
pseudoElement,
|
|
@@ -6602,7 +6618,7 @@ function getHTMLShadow(element, includeSelectorTag, shadowElementIds = []) {
|
|
|
6602
6618
|
var SHADOW_ID_ATTR_NAME = "data-wdio-shadow-id";
|
|
6603
6619
|
var SHADOW_ID_ATTR = "[".concat(SHADOW_ID_ATTR_NAME, "]");
|
|
6604
6620
|
async function getHTML2(options = {}) {
|
|
6605
|
-
const
|
|
6621
|
+
const browser = getBrowserObject20(this);
|
|
6606
6622
|
if (typeof options !== "object" && typeof options === "boolean") {
|
|
6607
6623
|
options = { includeSelectorTag: options };
|
|
6608
6624
|
} else if (typeof options !== "object") {
|
|
@@ -6616,7 +6632,7 @@ async function getHTML2(options = {}) {
|
|
|
6616
6632
|
excludeElements: []
|
|
6617
6633
|
}, options);
|
|
6618
6634
|
const basicGetHTML = (elementId, includeSelectorTag2) => {
|
|
6619
|
-
return
|
|
6635
|
+
return browser.execute(getHTML, {
|
|
6620
6636
|
[ELEMENT_KEY12]: elementId,
|
|
6621
6637
|
// w3c compatible
|
|
6622
6638
|
ELEMENT: elementId
|
|
@@ -6632,12 +6648,12 @@ async function getHTML2(options = {}) {
|
|
|
6632
6648
|
);
|
|
6633
6649
|
}
|
|
6634
6650
|
const { load } = await import("cheerio");
|
|
6635
|
-
const shadowRootManager = getShadowRootManager(
|
|
6636
|
-
const contextManager = getContextManager(
|
|
6651
|
+
const shadowRootManager = getShadowRootManager(browser);
|
|
6652
|
+
const contextManager = getContextManager(browser);
|
|
6637
6653
|
const context = await contextManager.getCurrentContext();
|
|
6638
6654
|
const shadowRootElementPairs = shadowRootManager.getShadowElementPairsByContextId(context, this.elementId);
|
|
6639
6655
|
const elementsWithShadowRootAndIdVerified = (await Promise.all(
|
|
6640
|
-
shadowRootElementPairs.map(([elemId, elem]) =>
|
|
6656
|
+
shadowRootElementPairs.map(([elemId, elem]) => browser.execute((elem2) => elem2.tagName, { [ELEMENT_KEY12]: elemId }).then(
|
|
6641
6657
|
() => [elemId, elem],
|
|
6642
6658
|
() => void 0
|
|
6643
6659
|
))
|
|
@@ -6863,8 +6879,8 @@ async function isClickable() {
|
|
|
6863
6879
|
if (this.isMobile && this.isNativeContext) {
|
|
6864
6880
|
throw new Error("Method not supported in mobile native environment. It is unlikely that you need to use this command.");
|
|
6865
6881
|
}
|
|
6866
|
-
const
|
|
6867
|
-
return
|
|
6882
|
+
const browser = getBrowserObject21(this);
|
|
6883
|
+
return browser.execute(isElementClickable, {
|
|
6868
6884
|
[ELEMENT_KEY13]: this.elementId,
|
|
6869
6885
|
// w3c compatible
|
|
6870
6886
|
ELEMENT: this.elementId
|
|
@@ -7056,11 +7072,11 @@ function isElementInViewport(elem) {
|
|
|
7056
7072
|
|
|
7057
7073
|
// src/commands/element/isDisplayed.ts
|
|
7058
7074
|
async function isDisplayed(commandParams = DEFAULT_PARAMS) {
|
|
7059
|
-
const
|
|
7075
|
+
const browser = getBrowserObject22(this);
|
|
7060
7076
|
if (!await hasElementId(this)) {
|
|
7061
7077
|
return false;
|
|
7062
7078
|
}
|
|
7063
|
-
if (
|
|
7079
|
+
if (browser.isMobile && (browser.isNativeContext || browser.isWindowsApp || browser.isMacApp)) {
|
|
7064
7080
|
if (commandParams == null ? void 0 : commandParams.withinViewport) {
|
|
7065
7081
|
throw new Error(
|
|
7066
7082
|
"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 +7086,7 @@ async function isDisplayed(commandParams = DEFAULT_PARAMS) {
|
|
|
7070
7086
|
}
|
|
7071
7087
|
let hadToFallback = false;
|
|
7072
7088
|
const [isDisplayed2, displayProperty] = await Promise.all([
|
|
7073
|
-
|
|
7089
|
+
browser.execute(function checkVisibility(elem, params) {
|
|
7074
7090
|
if (typeof elem.checkVisibility === "function") {
|
|
7075
7091
|
return elem.checkVisibility(params);
|
|
7076
7092
|
}
|
|
@@ -7081,7 +7097,7 @@ async function isDisplayed(commandParams = DEFAULT_PARAMS) {
|
|
|
7081
7097
|
}).then((result) => {
|
|
7082
7098
|
if (result === null) {
|
|
7083
7099
|
hadToFallback = true;
|
|
7084
|
-
return
|
|
7100
|
+
return browser.execute(isElementDisplayed, this);
|
|
7085
7101
|
}
|
|
7086
7102
|
return result;
|
|
7087
7103
|
}),
|
|
@@ -7092,9 +7108,9 @@ async function isDisplayed(commandParams = DEFAULT_PARAMS) {
|
|
|
7092
7108
|
]);
|
|
7093
7109
|
const hasDisplayContentsCSSProperty = displayProperty.value === "contents";
|
|
7094
7110
|
const shouldRecheckContentVisibility = !hadToFallback && hasDisplayContentsCSSProperty;
|
|
7095
|
-
const finalResponse = shouldRecheckContentVisibility ? await
|
|
7111
|
+
const finalResponse = shouldRecheckContentVisibility ? await browser.execute(isElementDisplayed, this).catch(() => false) : isDisplayed2;
|
|
7096
7112
|
if (finalResponse && (commandParams == null ? void 0 : commandParams.withinViewport)) {
|
|
7097
|
-
return
|
|
7113
|
+
return browser.execute(isElementInViewport, this);
|
|
7098
7114
|
}
|
|
7099
7115
|
return finalResponse;
|
|
7100
7116
|
}
|
|
@@ -7120,9 +7136,9 @@ var getWebElement = (el) => ({
|
|
|
7120
7136
|
// jsonwp compatible
|
|
7121
7137
|
});
|
|
7122
7138
|
async function isEqual(el) {
|
|
7123
|
-
const
|
|
7124
|
-
if (
|
|
7125
|
-
const context = await
|
|
7139
|
+
const browser = getBrowserObject23(this);
|
|
7140
|
+
if (browser.isMobile) {
|
|
7141
|
+
const context = await browser.getContext().catch(() => void 0);
|
|
7126
7142
|
const contextId = typeof context === "string" ? context : context == null ? void 0 : context.id;
|
|
7127
7143
|
if (contextId && contextId.toLowerCase().includes("native")) {
|
|
7128
7144
|
return this.elementId === el.elementId;
|
|
@@ -7130,7 +7146,7 @@ async function isEqual(el) {
|
|
|
7130
7146
|
}
|
|
7131
7147
|
let result;
|
|
7132
7148
|
try {
|
|
7133
|
-
result = await
|
|
7149
|
+
result = await browser.execute(
|
|
7134
7150
|
/* istanbul ignore next */
|
|
7135
7151
|
function(el1, el2) {
|
|
7136
7152
|
return el1 === el2;
|
|
@@ -7167,8 +7183,8 @@ function isFocused(elem) {
|
|
|
7167
7183
|
|
|
7168
7184
|
// src/commands/element/isFocused.ts
|
|
7169
7185
|
async function isFocused2() {
|
|
7170
|
-
const
|
|
7171
|
-
return
|
|
7186
|
+
const browser = await getBrowserObject24(this);
|
|
7187
|
+
return browser.execute(isFocused, {
|
|
7172
7188
|
[ELEMENT_KEY15]: this.elementId,
|
|
7173
7189
|
// w3c compatible
|
|
7174
7190
|
ELEMENT: this.elementId
|
|
@@ -7210,8 +7226,8 @@ function isElementStable(elem, done) {
|
|
|
7210
7226
|
|
|
7211
7227
|
// src/commands/element/isStable.ts
|
|
7212
7228
|
async function isStable() {
|
|
7213
|
-
const
|
|
7214
|
-
return await
|
|
7229
|
+
const browser = getBrowserObject25(this);
|
|
7230
|
+
return await browser.executeAsync(isElementStable, {
|
|
7215
7231
|
[ELEMENT_KEY16]: this.elementId,
|
|
7216
7232
|
// w3c compatible
|
|
7217
7233
|
ELEMENT: this.elementId
|
|
@@ -7224,9 +7240,9 @@ import logger22 from "@wdio/logger";
|
|
|
7224
7240
|
import { getBrowserObject as getBrowserObject26 } from "@wdio/utils";
|
|
7225
7241
|
var log22 = logger22("webdriver");
|
|
7226
7242
|
async function moveTo({ xOffset, yOffset } = {}) {
|
|
7227
|
-
const
|
|
7243
|
+
const browser = getBrowserObject26(this);
|
|
7228
7244
|
if (xOffset || yOffset) {
|
|
7229
|
-
const { width, height } = await
|
|
7245
|
+
const { width, height } = await browser.getElementRect(this.elementId);
|
|
7230
7246
|
if (xOffset && xOffset < -Math.floor(width / 2) || xOffset && xOffset > Math.floor(width / 2)) {
|
|
7231
7247
|
log22.warn("xOffset would cause a out of bounds error as it goes outside of element");
|
|
7232
7248
|
}
|
|
@@ -7235,7 +7251,7 @@ async function moveTo({ xOffset, yOffset } = {}) {
|
|
|
7235
7251
|
}
|
|
7236
7252
|
}
|
|
7237
7253
|
const moveToNested = async () => {
|
|
7238
|
-
await
|
|
7254
|
+
await browser.action("pointer", { parameters: { pointerType: "mouse" } }).move({ origin: this, x: xOffset || 0, y: yOffset || 0 }).perform();
|
|
7239
7255
|
};
|
|
7240
7256
|
try {
|
|
7241
7257
|
await moveToNested();
|
|
@@ -7278,10 +7294,10 @@ function previousElement() {
|
|
|
7278
7294
|
// src/commands/element/react$$.ts
|
|
7279
7295
|
import { getBrowserObject as getBrowserObject27 } from "@wdio/utils";
|
|
7280
7296
|
async function react$$4(selector, { props = {}, state = {} } = {}) {
|
|
7281
|
-
const
|
|
7297
|
+
const browser = await getBrowserObject27(this);
|
|
7282
7298
|
await this.executeScript(resqScript.toString(), []);
|
|
7283
|
-
await
|
|
7284
|
-
const res = await
|
|
7299
|
+
await browser.execute(waitToLoadReact);
|
|
7300
|
+
const res = await browser.execute(
|
|
7285
7301
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7286
7302
|
react$$,
|
|
7287
7303
|
selector,
|
|
@@ -7296,10 +7312,10 @@ async function react$$4(selector, { props = {}, state = {} } = {}) {
|
|
|
7296
7312
|
// src/commands/element/react$.ts
|
|
7297
7313
|
import { getBrowserObject as getBrowserObject28 } from "@wdio/utils";
|
|
7298
7314
|
async function react$4(selector, { props = {}, state = {} } = {}) {
|
|
7299
|
-
const
|
|
7315
|
+
const browser = await getBrowserObject28(this);
|
|
7300
7316
|
await this.executeScript(resqScript.toString(), []);
|
|
7301
|
-
await
|
|
7302
|
-
const res = await
|
|
7317
|
+
await browser.execute(waitToLoadReact);
|
|
7318
|
+
const res = await browser.execute(
|
|
7303
7319
|
react$,
|
|
7304
7320
|
selector,
|
|
7305
7321
|
props,
|
|
@@ -7320,11 +7336,11 @@ import { ELEMENT_KEY as ELEMENT_KEY17 } from "webdriver";
|
|
|
7320
7336
|
import { getBrowserObject as getBrowserObject29 } from "@wdio/utils";
|
|
7321
7337
|
var log23 = logger23("webdriverio");
|
|
7322
7338
|
async function scrollIntoView(options = { block: "start", inline: "nearest" }) {
|
|
7323
|
-
const
|
|
7324
|
-
if (
|
|
7325
|
-
if (await
|
|
7339
|
+
const browser = getBrowserObject29(this);
|
|
7340
|
+
if (browser.isMobile) {
|
|
7341
|
+
if (await browser.isNativeContext) {
|
|
7326
7342
|
return nativeMobileScrollIntoView({
|
|
7327
|
-
browser
|
|
7343
|
+
browser,
|
|
7328
7344
|
element: this,
|
|
7329
7345
|
options: options || {}
|
|
7330
7346
|
});
|
|
@@ -7332,9 +7348,9 @@ async function scrollIntoView(options = { block: "start", inline: "nearest" }) {
|
|
|
7332
7348
|
return scrollIntoViewWeb.call(this, options);
|
|
7333
7349
|
}
|
|
7334
7350
|
try {
|
|
7335
|
-
const elemRect = await
|
|
7336
|
-
const viewport = await
|
|
7337
|
-
let [scrollX, scrollY] = await
|
|
7351
|
+
const elemRect = await browser.getElementRect(this.elementId);
|
|
7352
|
+
const viewport = await browser.getWindowSize();
|
|
7353
|
+
let [scrollX, scrollY] = await browser.execute(() => [
|
|
7338
7354
|
window.scrollX,
|
|
7339
7355
|
window.scrollY
|
|
7340
7356
|
]);
|
|
@@ -7369,7 +7385,7 @@ async function scrollIntoView(options = { block: "start", inline: "nearest" }) {
|
|
|
7369
7385
|
}
|
|
7370
7386
|
deltaX = Math.round(deltaX - scrollX);
|
|
7371
7387
|
deltaY = Math.round(deltaY - scrollY);
|
|
7372
|
-
await
|
|
7388
|
+
await browser.action("wheel").scroll({ duration: 0, x: deltaX, y: deltaY, origin: this }).perform();
|
|
7373
7389
|
} catch (err) {
|
|
7374
7390
|
log23.warn(
|
|
7375
7391
|
'Failed to execute "scrollIntoView" using WebDriver Actions API: '.concat(err.message, "!\n") + "Re-attempting using `Element.scrollIntoView` via Web API."
|
|
@@ -7378,7 +7394,7 @@ async function scrollIntoView(options = { block: "start", inline: "nearest" }) {
|
|
|
7378
7394
|
}
|
|
7379
7395
|
}
|
|
7380
7396
|
async function mobileScrollUntilVisible({
|
|
7381
|
-
browser
|
|
7397
|
+
browser,
|
|
7382
7398
|
direction,
|
|
7383
7399
|
duration,
|
|
7384
7400
|
element,
|
|
@@ -7398,7 +7414,7 @@ async function mobileScrollUntilVisible({
|
|
|
7398
7414
|
if (isVisible) {
|
|
7399
7415
|
break;
|
|
7400
7416
|
}
|
|
7401
|
-
await
|
|
7417
|
+
await browser.swipe({
|
|
7402
7418
|
direction,
|
|
7403
7419
|
...duration ? { duration } : {},
|
|
7404
7420
|
...percent ? { percent } : {},
|
|
@@ -7410,7 +7426,7 @@ async function mobileScrollUntilVisible({
|
|
|
7410
7426
|
return { hasScrolled, isVisible };
|
|
7411
7427
|
}
|
|
7412
7428
|
async function nativeMobileScrollIntoView({
|
|
7413
|
-
browser
|
|
7429
|
+
browser,
|
|
7414
7430
|
element,
|
|
7415
7431
|
options
|
|
7416
7432
|
}) {
|
|
@@ -7423,7 +7439,7 @@ async function nativeMobileScrollIntoView({
|
|
|
7423
7439
|
...options || {}
|
|
7424
7440
|
};
|
|
7425
7441
|
const { hasScrolled, isVisible } = await mobileScrollUntilVisible({
|
|
7426
|
-
browser
|
|
7442
|
+
browser,
|
|
7427
7443
|
element,
|
|
7428
7444
|
maxScrolls: mobileOptions.maxScrolls,
|
|
7429
7445
|
direction: mobileOptions.direction,
|
|
@@ -7432,15 +7448,15 @@ async function nativeMobileScrollIntoView({
|
|
|
7432
7448
|
...(mobileOptions == null ? void 0 : mobileOptions.scrollableElement) ? { scrollableElement: mobileOptions.scrollableElement } : {}
|
|
7433
7449
|
});
|
|
7434
7450
|
if (hasScrolled && isVisible) {
|
|
7435
|
-
return
|
|
7451
|
+
return browser.pause(1e3);
|
|
7436
7452
|
} else if (isVisible) {
|
|
7437
7453
|
return;
|
|
7438
7454
|
}
|
|
7439
7455
|
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
7456
|
}
|
|
7441
7457
|
function scrollIntoViewWeb(options = { block: "start", inline: "nearest" }) {
|
|
7442
|
-
const
|
|
7443
|
-
return
|
|
7458
|
+
const browser = getBrowserObject29(this);
|
|
7459
|
+
return browser.execute(
|
|
7444
7460
|
(elem, options2) => elem.scrollIntoView(options2),
|
|
7445
7461
|
{
|
|
7446
7462
|
[ELEMENT_KEY17]: this.elementId,
|
|
@@ -7860,11 +7876,11 @@ var createRoleBaseXpathSelector = (role) => {
|
|
|
7860
7876
|
// src/commands/element/shadow$$.ts
|
|
7861
7877
|
var log24 = logger24("webdriverio");
|
|
7862
7878
|
async function shadow$$(selector) {
|
|
7863
|
-
const
|
|
7879
|
+
const browser = getBrowserObject30(this);
|
|
7864
7880
|
try {
|
|
7865
|
-
const shadowRoot = await
|
|
7881
|
+
const shadowRoot = await browser.getElementShadowRoot(this.elementId);
|
|
7866
7882
|
const { using, value } = findStrategy(selector, this.isW3C, this.isMobile);
|
|
7867
|
-
const res = await
|
|
7883
|
+
const res = await browser.findElementsFromShadowRoot(shadowRoot[SHADOW_ELEMENT_KEY], using, value);
|
|
7868
7884
|
const elements = await getElements.call(this, selector, res, { isShadowElement: true });
|
|
7869
7885
|
return enhanceElementsArray(elements, this, selector);
|
|
7870
7886
|
} catch (err) {
|
|
@@ -7881,11 +7897,11 @@ import { SHADOW_ELEMENT_KEY as SHADOW_ELEMENT_KEY2 } from "webdriver";
|
|
|
7881
7897
|
import { getBrowserObject as getBrowserObject31 } from "@wdio/utils";
|
|
7882
7898
|
var log25 = logger25("webdriverio");
|
|
7883
7899
|
async function shadow$(selector) {
|
|
7884
|
-
const
|
|
7900
|
+
const browser = getBrowserObject31(this);
|
|
7885
7901
|
try {
|
|
7886
|
-
const shadowRoot = await
|
|
7902
|
+
const shadowRoot = await browser.getElementShadowRoot(this.elementId);
|
|
7887
7903
|
const { using, value } = findStrategy(selector, this.isW3C, this.isMobile);
|
|
7888
|
-
const res = await
|
|
7904
|
+
const res = await browser.findElementFromShadowRoot(shadowRoot[SHADOW_ELEMENT_KEY2], using, value);
|
|
7889
7905
|
return getElement.call(this, selector, res, { isShadowElement: true });
|
|
7890
7906
|
} catch (err) {
|
|
7891
7907
|
log25.warn(
|
|
@@ -7999,8 +8015,8 @@ var waitUntil2 = waitUntil;
|
|
|
7999
8015
|
// src/commands/mobile/longPress.ts
|
|
8000
8016
|
import { getBrowserObject as getBrowserObject32 } from "@wdio/utils";
|
|
8001
8017
|
function longPress(options) {
|
|
8002
|
-
const
|
|
8003
|
-
if (!
|
|
8018
|
+
const browser = getBrowserObject32(this);
|
|
8019
|
+
if (!browser.isMobile) {
|
|
8004
8020
|
throw new Error("The longPress command is only available for mobile platforms.");
|
|
8005
8021
|
}
|
|
8006
8022
|
if (typeof options !== "undefined" && (typeof options !== "object" || Array.isArray(options))) {
|
|
@@ -8018,12 +8034,12 @@ function longPress(options) {
|
|
|
8018
8034
|
// src/commands/mobile/pinch.ts
|
|
8019
8035
|
import { getBrowserObject as getBrowserObject33 } from "@wdio/utils";
|
|
8020
8036
|
async function pinch(options = {}) {
|
|
8021
|
-
const
|
|
8022
|
-
if (!
|
|
8037
|
+
const browser = getBrowserObject33(this);
|
|
8038
|
+
if (!browser.isMobile) {
|
|
8023
8039
|
throw new Error("The pinch command is only available for mobile platforms.");
|
|
8024
8040
|
}
|
|
8025
|
-
const { duration, scale } = validatePinchAndZoomOptions({ browser
|
|
8026
|
-
const gestureConfig =
|
|
8041
|
+
const { duration, scale } = validatePinchAndZoomOptions({ browser, gesture: "pinch", options });
|
|
8042
|
+
const gestureConfig = browser.isIOS ? {
|
|
8027
8043
|
elementId: await this.elementId,
|
|
8028
8044
|
scale,
|
|
8029
8045
|
velocity: -Math.abs(duration)
|
|
@@ -8031,29 +8047,29 @@ async function pinch(options = {}) {
|
|
|
8031
8047
|
} : {
|
|
8032
8048
|
elementId: await this.elementId,
|
|
8033
8049
|
percent: scale,
|
|
8034
|
-
speed: calculateAndroidPinchAndZoomSpeed({ browser
|
|
8050
|
+
speed: calculateAndroidPinchAndZoomSpeed({ browser, duration, scale })
|
|
8035
8051
|
};
|
|
8036
|
-
return
|
|
8052
|
+
return browser.execute(browser.isIOS ? "mobile: pinch" : "mobile: pinchCloseGesture", gestureConfig);
|
|
8037
8053
|
}
|
|
8038
8054
|
|
|
8039
8055
|
// src/commands/mobile/zoom.ts
|
|
8040
8056
|
import { getBrowserObject as getBrowserObject34 } from "@wdio/utils";
|
|
8041
8057
|
async function zoom(options = {}) {
|
|
8042
|
-
const
|
|
8043
|
-
if (!
|
|
8058
|
+
const browser = getBrowserObject34(this);
|
|
8059
|
+
if (!browser.isMobile) {
|
|
8044
8060
|
throw new Error("The zoom command is only available for mobile platforms.");
|
|
8045
8061
|
}
|
|
8046
|
-
const { duration, scale } = validatePinchAndZoomOptions({ browser
|
|
8047
|
-
const gestureConfig =
|
|
8062
|
+
const { duration, scale } = validatePinchAndZoomOptions({ browser, gesture: "zoom", options });
|
|
8063
|
+
const gestureConfig = browser.isIOS ? {
|
|
8048
8064
|
elementId: await this.elementId,
|
|
8049
8065
|
scale,
|
|
8050
8066
|
velocity: duration
|
|
8051
8067
|
} : {
|
|
8052
8068
|
elementId: await this.elementId,
|
|
8053
8069
|
percent: scale,
|
|
8054
|
-
speed: calculateAndroidPinchAndZoomSpeed({ browser
|
|
8070
|
+
speed: calculateAndroidPinchAndZoomSpeed({ browser, duration, scale })
|
|
8055
8071
|
};
|
|
8056
|
-
return
|
|
8072
|
+
return browser.execute(browser.isIOS ? "mobile: pinch" : "mobile: pinchOpenGesture", gestureConfig);
|
|
8057
8073
|
}
|
|
8058
8074
|
|
|
8059
8075
|
// src/scripts/elementContains.ts
|
|
@@ -8409,9 +8425,9 @@ function transformClassicToBidiSelector(using, value) {
|
|
|
8409
8425
|
throw new Error("Can't transform classic selector ".concat(using, " to Bidi selector"));
|
|
8410
8426
|
}
|
|
8411
8427
|
async function findDeepElement(selector) {
|
|
8412
|
-
const
|
|
8413
|
-
const shadowRootManager = getShadowRootManager(
|
|
8414
|
-
const contextManager = getContextManager(
|
|
8428
|
+
const browser = getBrowserObject35(this);
|
|
8429
|
+
const shadowRootManager = getShadowRootManager(browser);
|
|
8430
|
+
const contextManager = getContextManager(browser);
|
|
8415
8431
|
const context = await contextManager.getCurrentContext();
|
|
8416
8432
|
const shadowRoots = shadowRootManager.getShadowElementsByContextId(
|
|
8417
8433
|
context,
|
|
@@ -8420,7 +8436,7 @@ async function findDeepElement(selector) {
|
|
|
8420
8436
|
const { using, value } = findStrategy(selector, this.isW3C, this.isMobile);
|
|
8421
8437
|
const locator = transformClassicToBidiSelector(using, value);
|
|
8422
8438
|
const startNodes = shadowRoots.length > 0 ? shadowRoots.map((shadowRootNodeId) => ({ sharedId: shadowRootNodeId })) : this.elementId ? [{ sharedId: this.elementId }] : void 0;
|
|
8423
|
-
const deepElementResult = await
|
|
8439
|
+
const deepElementResult = await browser.browsingContextLocateNodes({ locator, context, startNodes }).then(async (result) => {
|
|
8424
8440
|
let nodes = result.nodes.filter((node) => Boolean(node.sharedId)).map((node) => ({
|
|
8425
8441
|
[ELEMENT_KEY20]: node.sharedId,
|
|
8426
8442
|
locator
|
|
@@ -8430,7 +8446,7 @@ async function findDeepElement(selector) {
|
|
|
8430
8446
|
return nodes[0];
|
|
8431
8447
|
}
|
|
8432
8448
|
const scopedNodes = await Promise.all(nodes.map(async (node) => {
|
|
8433
|
-
const isIn = await
|
|
8449
|
+
const isIn = await browser.execute(
|
|
8434
8450
|
elementContains,
|
|
8435
8451
|
{ [ELEMENT_KEY20]: this.elementId },
|
|
8436
8452
|
node
|
|
@@ -8440,7 +8456,7 @@ async function findDeepElement(selector) {
|
|
|
8440
8456
|
return scopedNodes[0];
|
|
8441
8457
|
}, (err) => {
|
|
8442
8458
|
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) :
|
|
8459
|
+
return this && "elementId" in this && this.elementId ? this.findElementFromElement(this.elementId, using, value) : browser.findElement(using, value);
|
|
8444
8460
|
});
|
|
8445
8461
|
if (!deepElementResult) {
|
|
8446
8462
|
return new Error("Couldn't find element with selector \"".concat(selector, '"'));
|
|
@@ -8448,9 +8464,9 @@ async function findDeepElement(selector) {
|
|
|
8448
8464
|
return deepElementResult;
|
|
8449
8465
|
}
|
|
8450
8466
|
async function findDeepElements(selector) {
|
|
8451
|
-
const
|
|
8452
|
-
const shadowRootManager = getShadowRootManager(
|
|
8453
|
-
const contextManager = getContextManager(
|
|
8467
|
+
const browser = getBrowserObject35(this);
|
|
8468
|
+
const shadowRootManager = getShadowRootManager(browser);
|
|
8469
|
+
const contextManager = getContextManager(browser);
|
|
8454
8470
|
const context = await contextManager.getCurrentContext();
|
|
8455
8471
|
const shadowRoots = shadowRootManager.getShadowElementsByContextId(
|
|
8456
8472
|
context,
|
|
@@ -8459,7 +8475,7 @@ async function findDeepElements(selector) {
|
|
|
8459
8475
|
const { using, value } = findStrategy(selector, this.isW3C, this.isMobile);
|
|
8460
8476
|
const locator = transformClassicToBidiSelector(using, value);
|
|
8461
8477
|
const startNodes = shadowRoots.length > 0 ? shadowRoots.map((shadowRootNodeId) => ({ sharedId: shadowRootNodeId })) : this.elementId ? [{ sharedId: this.elementId }] : void 0;
|
|
8462
|
-
const deepElementResult = await
|
|
8478
|
+
const deepElementResult = await browser.browsingContextLocateNodes({ locator, context, startNodes }).then(async (result) => {
|
|
8463
8479
|
let nodes = result.nodes.filter((node) => Boolean(node.sharedId)).map((node) => ({
|
|
8464
8480
|
[ELEMENT_KEY20]: node.sharedId,
|
|
8465
8481
|
locator
|
|
@@ -8469,7 +8485,7 @@ async function findDeepElements(selector) {
|
|
|
8469
8485
|
return nodes;
|
|
8470
8486
|
}
|
|
8471
8487
|
const scopedNodes = await Promise.all(nodes.map(async (node) => {
|
|
8472
|
-
const isIn = await
|
|
8488
|
+
const isIn = await browser.execute(
|
|
8473
8489
|
elementContains,
|
|
8474
8490
|
{ [ELEMENT_KEY20]: this.elementId },
|
|
8475
8491
|
node
|
|
@@ -8479,7 +8495,7 @@ async function findDeepElements(selector) {
|
|
|
8479
8495
|
return scopedNodes;
|
|
8480
8496
|
}, (err) => {
|
|
8481
8497
|
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) :
|
|
8498
|
+
return this && "elementId" in this && this.elementId ? this.findElementsFromElement(this.elementId, using, value) : browser.findElements(using, value);
|
|
8483
8499
|
});
|
|
8484
8500
|
return deepElementResult;
|
|
8485
8501
|
}
|
|
@@ -8673,7 +8689,7 @@ function createFunctionDeclarationFromString(userScript) {
|
|
|
8673
8689
|
}
|
|
8674
8690
|
|
|
8675
8691
|
// src/middlewares.ts
|
|
8676
|
-
var COMMANDS_TO_SKIP = ["getElement", "getElements"];
|
|
8692
|
+
var COMMANDS_TO_SKIP = ["getElement", "getElements", "emit"];
|
|
8677
8693
|
var elementErrorHandler = (fn) => (commandName, commandFn) => {
|
|
8678
8694
|
return function elementErrorHandlerCallback(...args) {
|
|
8679
8695
|
return fn(commandName, async function elementErrorHandlerCallbackFn() {
|
|
@@ -8985,7 +9001,7 @@ var NOOP2 = () => {
|
|
|
8985
9001
|
var ProtocolStub = class {
|
|
8986
9002
|
static async newSession(options) {
|
|
8987
9003
|
const capabilities = emulateSessionCapabilities(options.capabilities);
|
|
8988
|
-
const
|
|
9004
|
+
const browser = {
|
|
8989
9005
|
options,
|
|
8990
9006
|
capabilities,
|
|
8991
9007
|
requestedCapabilities: capabilities,
|
|
@@ -9001,9 +9017,9 @@ var ProtocolStub = class {
|
|
|
9001
9017
|
overwriteCommand: NOOP2,
|
|
9002
9018
|
...capabilitiesEnvironmentDetector(capabilities)
|
|
9003
9019
|
};
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
return
|
|
9020
|
+
browser.addCommand = (...args) => browser.customCommands.push(args);
|
|
9021
|
+
browser.overwriteCommand = (...args) => browser.overwrittenCommands.push(args);
|
|
9022
|
+
return browser;
|
|
9007
9023
|
}
|
|
9008
9024
|
/**
|
|
9009
9025
|
* added just in case user wants to somehow reload webdriver before it was started.
|
|
@@ -9053,7 +9069,7 @@ async function getProtocolDriver(options) {
|
|
|
9053
9069
|
var Key2 = Key;
|
|
9054
9070
|
var SevereServiceError2 = SevereServiceError;
|
|
9055
9071
|
var remote = async function(params, remoteModifier) {
|
|
9056
|
-
const keysToKeep = Object.keys(
|
|
9072
|
+
const keysToKeep = Object.keys(environment.value.variables.WDIO_WORKER_ID ? params : DEFAULTS);
|
|
9057
9073
|
const config = validateConfig(WDIO_DEFAULTS, params, keysToKeep);
|
|
9058
9074
|
await enableFileLogging(config.outputDir);
|
|
9059
9075
|
logger27.setLogLevelsConfig(config.logLevels, config.logLevel);
|