From 63daef17374eee3cade95a76b4cbc25cdc0fb9cb Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 9 Nov 2026 08:21:29 +0100 Subject: [PATCH 1/2] feat!: add Appium 4 support BREAKING CHANGE: requires Appium ^4.0.0-beta.6 and Node ^22.22.2 || ^24.15.0 || >=26.0.0. createSession takes a single w3cCapabilities argument, and the default exports are removed (use the named export). --- README.md | 2 +- docs/getting-started/index.md | 3 ++- lib/commands/find.ts | 6 ++++++ lib/driver.ts | 14 ++++++-------- lib/gecko.ts | 2 -- lib/index.ts | 5 +---- lib/logger.ts | 2 -- package.json | 16 ++++++++-------- scripts/install-geckodriver.mjs | 4 ++-- 9 files changed, 26 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index bdce9dd..336bf92 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ This is an Appium driver for automating Gecko-based browsers (such as Firefox) a different platforms, including Android. > [!IMPORTANT] -> Since major version *2.0.0*, this driver is only compatible with Appium 3. +> Since major version *4.0.0*, this driver is only compatible with Appium 4. ## Documentation diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index 18bf901..6159e8e 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -38,7 +38,8 @@ and prerequisites of Appium itself can be found in [the Appium documentation](ht | Geckodriver version | Supported Appium server version | | --- | --- | -| >= 2.0.0 | Appium 3 | +| >= 4.0.0 | Appium 4 | +| 2.0.0 - 3.0.18 | Appium 3 | | 1.0.0 - 1.4.4 | Appium 2 | ## Installation diff --git a/lib/commands/find.ts b/lib/commands/find.ts index 5a72b78..4df53ad 100644 --- a/lib/commands/find.ts +++ b/lib/commands/find.ts @@ -2,6 +2,12 @@ import {util} from 'appium/support.js'; import type {GeckoDriver} from '../driver.js'; +declare module '../driver.js' { + interface GeckoDriver { + findElOrEls(...args: Parameters): ReturnType; + } +} + /** * Find element(s) by given strategy and selector. If context is provided, search will be performed within the context element. * This is needed to make lookup by image working. diff --git a/lib/driver.ts b/lib/driver.ts index 9f88776..e93212a 100644 --- a/lib/driver.ts +++ b/lib/driver.ts @@ -8,7 +8,7 @@ import type { } from '@appium/types'; import {BaseDriver, errors} from 'appium/driver.js'; -import * as findCommands from './commands/find.js'; +import {findElOrEls} from './commands/find.js'; import {INSECURE_FEAT_CUSTOM_GECKODRIVER_EXECUTABLE} from './constants.js'; import {desiredCapConstraints} from './desired-caps.js'; import {GECKO_SERVER_HOST, GeckoDriverServer} from './gecko.js'; @@ -32,8 +32,6 @@ export class GeckoDriver public proxyReqRes: (...args: any) => any = null as any; - findElOrEls = findCommands.findElOrEls; - private isProxyActive: boolean = false; private _gecko: GeckoDriverServer | null = null; private _bidiProxyUrl: string | null = null; @@ -95,11 +93,9 @@ export class GeckoDriver } override async createSession( - w3cCaps1: W3CDriverCaps, - w3cCaps2?: W3CDriverCaps, - ...args: any[] + w3cCapabilities: W3CDriverCaps, ): Promise> { - const [sessionId, processedCaps] = await super.createSession(w3cCaps1, w3cCaps2, ...args); + const [sessionId, processedCaps] = await super.createSession(w3cCapabilities); this._gecko = new GeckoDriverServer(this.log, processedCaps); let response: StringRecord; try { @@ -150,4 +146,6 @@ export class GeckoDriver } } -export default GeckoDriver; +Object.assign(GeckoDriver.prototype, { + findElOrEls, +}); diff --git a/lib/gecko.ts b/lib/gecko.ts index f17d426..32dd61e 100644 --- a/lib/gecko.ts +++ b/lib/gecko.ts @@ -302,5 +302,3 @@ export class GeckoDriverServer { } } } - -export default GeckoDriverServer; diff --git a/lib/index.ts b/lib/index.ts index 68e462a..3f26146 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,4 +1 @@ -import {GeckoDriver} from './driver.js'; - -export default GeckoDriver; -export {GeckoDriver}; +export {GeckoDriver} from './driver.js'; diff --git a/lib/logger.ts b/lib/logger.ts index 6548081..d010534 100644 --- a/lib/logger.ts +++ b/lib/logger.ts @@ -1,5 +1,3 @@ import {logger} from 'appium/support.js'; export const log = logger.getLogger('GeckoDriver'); - -export default log; diff --git a/package.json b/package.json index b4d3518..478a166 100644 --- a/package.json +++ b/package.json @@ -69,21 +69,21 @@ "teen_process": "^4.0.4" }, "devDependencies": { - "@appium/docutils": "^3.0.0", - "@appium/oxc-config": "^1.1.0", - "@appium/semantic-release-config": "^1.1.0", - "@appium/tsconfig": "^1.2.0", - "@appium/types": "^1.0.0-rc.1", + "@appium/docutils": "^4.0.0-beta.5", + "@appium/oxc-config": "^2.0.0-beta.2", + "@appium/semantic-release-config": "^2.0.0-beta.1", + "@appium/tsconfig": "^2.0.0-beta.1", + "@appium/types": "^2.0.0-beta.5", "@types/node": "^26.0.0", "@types/portscanner": "^2.1.4", "@types/tar-stream": "^3.1.4", - "webdriverio": "^9.0.5" + "webdriverio": "^10.1.0" }, "peerDependencies": { - "appium": "^3.0.0-rc.2" + "appium": "^4.0.0-beta.6" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "node": "^22.22.2 || ^24.15.0 || >=26.0.0", "npm": ">=10" }, "appium": { diff --git a/scripts/install-geckodriver.mjs b/scripts/install-geckodriver.mjs index 067bd2b..be46f7e 100644 --- a/scripts/install-geckodriver.mjs +++ b/scripts/install-geckodriver.mjs @@ -180,7 +180,7 @@ class GeckodriverReleaseCatalog { } throw new Error( `GeckoDriver v${release.version} does not contain any release matching the ` + - `current OS architecture ${process.arch}. Available packages: ${release.assets.map(({name}) => name)}`, + `current OS architecture ${process.arch}. Available packages: ${release.assets.map(({name}) => name).join(', ')}`, ); } @@ -421,7 +421,7 @@ NOTE: await program.parseAsync(process.argv); } -(async () => await main())(); +await main(); /** * @typedef {Object} ReleaseAsset From 155e57405b0a866114f8e3c333cfc24a9f6345e8 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Mon, 9 Nov 2026 08:21:29 +0100 Subject: [PATCH 2/2] test: use $$ for the logo lookup to satisfy WDIO 10 strict selectors --- test/functional/desktop-driver-e2e.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/functional/desktop-driver-e2e.test.ts b/test/functional/desktop-driver-e2e.test.ts index 59a5992..8bfa6dd 100644 --- a/test/functional/desktop-driver-e2e.test.ts +++ b/test/functional/desktop-driver-e2e.test.ts @@ -36,8 +36,9 @@ describe('Desktop Gecko Driver', {timeout: TEST_TIMEOUT}, () => { await waitForCondition( async () => { try { - const element = await driver!.$('img[alt="logo"]'); - return await element.isExisting(); + // The page has more than one logo, which fails WDIO 10's strict `$` + const logos = await driver!.$$('img[alt="logo"]'); + return logos.length > 0; } catch { return false; }