diff --git a/src/browser/browser.js b/src/browser/browser.js index f278e60d1..71d9be7fd 100644 --- a/src/browser/browser.js +++ b/src/browser/browser.js @@ -5,7 +5,7 @@ const _ = require("lodash"); const { SAVE_HISTORY_MODE } = require("../constants/config"); const { X_REQUEST_ID_DELIMITER } = require("../constants/browser"); const history = require("./history"); -const addRunStepCommand = require("./commands/runStep"); +const addRunStepCommand = require("./commands/runStep").default; const CUSTOM_SESSION_OPTS = [ "outputDir", diff --git a/src/browser/commands/assert-view/index.js b/src/browser/commands/assert-view/index.js index 4171192c1..65a4a99b5 100644 --- a/src/browser/commands/assert-view/index.js +++ b/src/browser/commands/assert-view/index.js @@ -28,7 +28,7 @@ const getIgnoreDiffPixelCountRatio = value => { return percent / 100; }; -module.exports = browser => { +module.exports.default = browser => { const screenShooter = ScreenShooter.create(browser); const { publicAPI: session, config } = browser; const { diff --git a/src/browser/commands/clearSession.ts b/src/browser/commands/clearSession.ts index a122f8a09..5ef85c48a 100644 --- a/src/browser/commands/clearSession.ts +++ b/src/browser/commands/clearSession.ts @@ -1,7 +1,7 @@ import type { Browser } from "../types"; import logger from "../../utils/logger"; -export = async (browser: Browser): Promise => { +export default async (browser: Browser): Promise => { const { publicAPI: session } = browser; const clearStorage = async (storageName: "localStorage" | "sessionStorage"): Promise => { diff --git a/src/browser/commands/getConfig.js b/src/browser/commands/getConfig.js index 02b8d6085..28df756d2 100644 --- a/src/browser/commands/getConfig.js +++ b/src/browser/commands/getConfig.js @@ -1,6 +1,6 @@ "use strict"; -module.exports = browser => { +module.exports.default = browser => { const { publicAPI: session, config } = browser; session.addCommand("getConfig", () => config); }; diff --git a/src/browser/commands/getPuppeteer.js b/src/browser/commands/getPuppeteer.js index 7e177b77e..65c40c3c4 100644 --- a/src/browser/commands/getPuppeteer.js +++ b/src/browser/commands/getPuppeteer.js @@ -2,7 +2,7 @@ const urljoin = require("url-join"); -module.exports = browser => { +module.exports.default = browser => { const { publicAPI: session, config } = browser; if (!config.browserWSEndpoint || !session.getPuppeteer) { diff --git a/src/browser/commands/moveCursorTo.ts b/src/browser/commands/moveCursorTo.ts index 8476f2330..c2b1ed146 100644 --- a/src/browser/commands/moveCursorTo.ts +++ b/src/browser/commands/moveCursorTo.ts @@ -5,30 +5,33 @@ type MoveToOptions = { yOffset?: number; }; +// As of now, we can't export type of the command function directly. See: https://github.com/webdriverio/webdriverio/issues/12527 +export type MoveCursorToCommand = (options: MoveToOptions) => Promise; + +const makeMoveCursorToCommand = (session: WebdriverIO.Browser) => + async function (this: WebdriverIO.Element, { xOffset = 0, yOffset = 0 }: MoveToOptions = {}): Promise { + + if (!this.isW3C) { + return this.moveToElement(this.elementId, xOffset, yOffset); + } + + const { x, y, width, height } = await this.getElementRect(this.elementId); + const { scrollX, scrollY } = await session.execute(function (this: Window) { + return { scrollX: this.scrollX, scrollY: this.scrollY }; + }); + + const newXOffset = Math.floor(x - scrollX + (typeof xOffset === "number" ? xOffset : width / 2)); + const newYOffset = Math.floor(y - scrollY + (typeof yOffset === "number" ? yOffset : height / 2)); + + return session + .action("pointer", { parameters: { pointerType: "mouse" } }) + .move({ x: newXOffset, y: newYOffset }) + .perform(); + }; + // TODO: remove after next major version -export = async (browser: Browser): Promise => { +export default async (browser: Browser): Promise => { const { publicAPI: session } = browser; - session.addCommand( - "moveCursorTo", - async function (this: WebdriverIO.Element, { xOffset = 0, yOffset = 0 }: MoveToOptions = {}): Promise { - if (!this.isW3C) { - return this.moveToElement(this.elementId, xOffset, yOffset); - } - - const { x, y, width, height } = await this.getElementRect(this.elementId); - const { scrollX, scrollY } = await session.execute(function (this: Window) { - return { scrollX: this.scrollX, scrollY: this.scrollY }; - }); - - const newXOffset = Math.floor(x - scrollX + (typeof xOffset === "number" ? xOffset : width / 2)); - const newYOffset = Math.floor(y - scrollY + (typeof yOffset === "number" ? yOffset : height / 2)); - - return session - .action("pointer", { parameters: { pointerType: "mouse" } }) - .move({ x: newXOffset, y: newYOffset }) - .perform(); - }, - true, - ); + session.addCommand("moveCursorTo", makeMoveCursorToCommand(session), true); }; diff --git a/src/browser/commands/openAndWait.ts b/src/browser/commands/openAndWait.ts index 9a37e6cfe..6083b0cdd 100644 --- a/src/browser/commands/openAndWait.ts +++ b/src/browser/commands/openAndWait.ts @@ -2,6 +2,7 @@ import _ from "lodash"; import { Matches } from "webdriverio"; import PageLoader from "../../utils/page-loader"; import type { Browser } from "../types"; +import { BrowserConfig } from "../../config/browser-config"; interface WaitOpts { selector?: string | string[]; @@ -23,25 +24,23 @@ const is: Record boolean> = { favicon: match => _.isString(match.url) && match.url.endsWith("/favicon.ico"), }; -export = (browser: Browser): void => { - const { publicAPI: session, config } = browser; - const { openAndWaitOpts } = config; - const isChrome = config.desiredCapabilities?.browserName === "chrome"; - const isCDP = config.automationProtocol === "devtools"; - +const makeOpenAndWaitCommand = (config: BrowserConfig, session: WebdriverIO.Browser) => function openAndWait( uri: string, { selector = [], predicate, - waitNetworkIdle = openAndWaitOpts?.waitNetworkIdle, - waitNetworkIdleTimeout = openAndWaitOpts?.waitNetworkIdleTimeout, - failOnNetworkError = openAndWaitOpts?.failOnNetworkError, + waitNetworkIdle = config.openAndWaitOpts?.waitNetworkIdle, + waitNetworkIdleTimeout = config.openAndWaitOpts?.waitNetworkIdleTimeout, + failOnNetworkError = config.openAndWaitOpts?.failOnNetworkError, shouldThrowError = shouldThrowErrorDefault, - ignoreNetworkErrorsPatterns = openAndWaitOpts?.ignoreNetworkErrorsPatterns, - timeout = openAndWaitOpts?.timeout || config?.pageLoadTimeout || 0, + ignoreNetworkErrorsPatterns = config.openAndWaitOpts?.ignoreNetworkErrorsPatterns, + timeout = config.openAndWaitOpts?.timeout || config?.pageLoadTimeout || 0, }: WaitOpts = {}, ): Promise { + const isChrome = config.desiredCapabilities?.browserName === "chrome"; + const isCDP = config.automationProtocol === "devtools"; + waitNetworkIdle &&= isChrome || isCDP; if (!uri || uri === emptyPageUrl) { @@ -110,9 +109,14 @@ export = (browser: Browser): void => { pageLoader.load(goToPage).then(checkLoaded); }).finally(() => pageLoader.unsubscribe()); - } + }; + +export type OpenAndWaitCommand = ReturnType; + +export default (browser: Browser): void => { + const { publicAPI: session, config } = browser; - session.addCommand("openAndWait", openAndWait); + session.addCommand("openAndWait", makeOpenAndWaitCommand(config, session)); }; function isMatchPatterns(patterns: Array = [], str: string): boolean { diff --git a/src/browser/commands/runStep.js b/src/browser/commands/runStep.js index 671ed7b69..fcb69cd67 100644 --- a/src/browser/commands/runStep.js +++ b/src/browser/commands/runStep.js @@ -2,7 +2,7 @@ const _ = require("lodash"); -module.exports = browser => { +module.exports.default = browser => { const { publicAPI: session } = browser; session.addCommand("runStep", (stepName, stepCb) => { if (!_.isString(stepName)) { diff --git a/src/browser/commands/scrollIntoView.ts b/src/browser/commands/scrollIntoView.ts index 7146de881..3562b4e20 100644 --- a/src/browser/commands/scrollIntoView.ts +++ b/src/browser/commands/scrollIntoView.ts @@ -1,7 +1,7 @@ import type { Browser } from "../types"; // TODO: remove after fix https://github.com/webdriverio/webdriverio/issues/9620 -export = async (browser: Browser): Promise => { +export default async (browser: Browser): Promise => { const { publicAPI: session } = browser; session.overwriteCommand( diff --git a/src/browser/commands/setOrientation.js b/src/browser/commands/setOrientation.js index 9152ca359..54ea7a1ce 100644 --- a/src/browser/commands/setOrientation.js +++ b/src/browser/commands/setOrientation.js @@ -1,7 +1,7 @@ /* global document */ "use strict"; -module.exports = browser => { +module.exports.default = browser => { const { publicAPI: session, config } = browser; if (!session.setOrientation) { diff --git a/src/browser/commands/switchToRepl.ts b/src/browser/commands/switchToRepl.ts index f4f119940..cdc54d54c 100644 --- a/src/browser/commands/switchToRepl.ts +++ b/src/browser/commands/switchToRepl.ts @@ -8,7 +8,7 @@ import type { Browser } from "../types"; const REPL_LINE_EVENT = "line"; -export = async (browser: Browser): Promise => { +export default async (browser: Browser): Promise => { const { publicAPI: session } = browser; const applyContext = (replServer: repl.REPLServer, ctx: Record = {}): void => { diff --git a/src/browser/existing-browser.js b/src/browser/existing-browser.js index 0a389c29c..48c643d34 100644 --- a/src/browser/existing-browser.js +++ b/src/browser/existing-browser.js @@ -181,7 +181,7 @@ module.exports = class ExistingBrowser extends Browser { this._addMetaAccessCommands(this._session); this._decorateUrlMethod(this._session); - commandsList.forEach(command => require(`./commands/${command}`)(this)); + commandsList.forEach(command => require(`./commands/${command}`).default(this)); super._addCommands(); } diff --git a/src/browser/types.ts b/src/browser/types.ts index ae572288e..f4b9b98c2 100644 --- a/src/browser/types.ts +++ b/src/browser/types.ts @@ -1,6 +1,8 @@ import type { AssertViewCommand, AssertViewElementCommand } from "./commands/types"; import type { BrowserConfig } from "./../config/browser-config"; import type { AssertViewResult, RunnerTest, RunnerHook } from "../types"; +import { MoveCursorToCommand } from "./commands/moveCursorTo"; +import { OpenAndWaitCommand } from "./commands/openAndWait"; export interface BrowserMeta { pid: number; @@ -107,6 +109,8 @@ declare global { }; }; + openAndWait: OpenAndWaitCommand; + switchToRepl: (ctx?: Record) => Promise; clearSession: () => Promise; @@ -144,6 +148,8 @@ declare global { * "compositeImage", "screenshotDelay", "selectorToScroll" */ assertView: AssertViewElementCommand; + + moveCursorTo: MoveCursorToCommand; } } }