Skip to content

Commit a71240b

Browse files
authored
feat: parse msedge as well as chromedriver (#297)
* feat: parse msedge as well as chromedriver * fix lint * tweak comment * fix load module * fix review * tune * update readme * tweak * use this.driverVersion * update readme * add comment * tweak * add try/catch for safe, tune log * calls stop
1 parent ccae674 commit a71240b

File tree

3 files changed

+224
-139
lines changed

3 files changed

+224
-139
lines changed

README.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,27 @@ appium-chromedriver
33

44
[![Release](https://github.com/appium/appium-chromedriver/actions/workflows/publish.js.yml/badge.svg)](https://github.com/appium/appium-chromedriver/actions/workflows/publish.js.yml)
55

6-
Node.js wrapper around [Chromedriver](https://sites.google.com/a/chromium.org/chromedriver/).
6+
Node.js wrapper around [Chromedriver](https://sites.google.com/chromium.org/driver/)
7+
and [Microsoft Edge WebDriver](https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/).
8+
The Microsoft Edge WebDriver support is since v5.4.0.
79
This wrapper is not used directly in Appium, but rather by various Android drivers to automate
810
Chrome/Chromium-based browsers
911
and web views using Hybrid Mode approach. Check the corresponding driver tutorials to get
1012
more details on it.
1113

1214
> **Note**
1315
>
14-
> The normal use of this package is via an Appium driver such as [UiAutomator2](https://github.com/appium/appium-uiautomator2-driver/) and not directly.
16+
> This package is intended to be used as a helper module for Appium drivers such as
17+
> [UiAutomator2](https://github.com/appium/appium-uiautomator2-driver/) and
18+
> [appium-chromium-driver](https://github.com/appium/appium-chromium-driver).
19+
> It was not created for standalone usage.
1520
> Please ensure you know what you are doing before using this package directly.
1621
22+
> **Note**
23+
>
24+
> This package can work with Microsoft Edge WebDriver as well, but the support is limited.
25+
> For example, automatic downloads do not work for Microsoft Edge WebDriver.
26+
1727
## Skipping binary installation
1828

1929
By default, upon installation the package downloads the most recent known Chromedriver version from

lib/chromedriver.js

+51-14
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const CHROME_BUNDLE_ID = 'com.android.chrome';
2828
const WEBVIEW_SHELL_BUNDLE_ID = 'org.chromium.webview_shell';
2929
const WEBVIEW_BUNDLE_IDS = ['com.google.android.webview', 'com.android.webview'];
3030
const VERSION_PATTERN = /([\d.]+)/;
31+
const WEBDRIVER_VERSION_PATTERN = /Starting (ChromeDriver|Microsoft Edge WebDriver) ([.\d]+)/;
3132

3233
const CD_VERSION_TIMEOUT = 5000;
3334

@@ -84,6 +85,9 @@ class Chromedriver extends events.EventEmitter {
8485
/** @type {any} */
8586
this.capabilities = {};
8687
this.desiredProtocol = PROTOCOLS.MJSONWP;
88+
89+
// Store the running driver version
90+
this.driverVersion = /** @type {string|null} */ null;
8791
}
8892

8993
get log() {
@@ -498,22 +502,29 @@ class Chromedriver extends events.EventEmitter {
498502
}
499503

500504
/**
501-
*
502-
* @param {string} [cdVersion]
505+
* Sync the WebDriver protocol if current on going protocol is W3C or MJSONWP.
506+
* Does nothing if this.driverVersion was null.
503507
*/
504-
syncProtocol(cdVersion) {
505-
const coercedVersion = semver.coerce(cdVersion);
508+
syncProtocol() {
509+
if (this.driverVersion === null) {
510+
// Keep the default protocol if the driverVersion was unsure.
511+
return;
512+
}
513+
514+
const coercedVersion = semver.coerce(this.driverVersion);
506515
if (!coercedVersion || coercedVersion.major < MIN_CD_VERSION_WITH_W3C_SUPPORT) {
507516
this.log.debug(
508-
`Chromedriver v. ${cdVersion} does not fully support ${PROTOCOLS.W3C} protocol. ` +
517+
`The WebDriver v. ${this.driverVersion} does not fully support ${PROTOCOLS.W3C} protocol. ` +
509518
`Defaulting to ${PROTOCOLS.MJSONWP}`
510519
);
511520
return;
512521
}
522+
523+
// Check only chromeOptions for now.
513524
const chromeOptions = getCapValue(this.capabilities, 'chromeOptions', {});
514525
if (chromeOptions.w3c === false) {
515526
this.log.info(
516-
`Chromedriver v. ${cdVersion} supports ${PROTOCOLS.W3C} protocol, ` +
527+
`The WebDriver v. ${this.driverVersion} supports ${PROTOCOLS.W3C} protocol, ` +
517528
`but ${PROTOCOLS.MJSONWP} one has been explicitly requested`
518529
);
519530
return;
@@ -525,6 +536,38 @@ class Chromedriver extends events.EventEmitter {
525536
this.capabilities = toW3cCapNames(this.capabilities);
526537
}
527538

539+
/**
540+
* Sync the protocol by reading the given output
541+
*
542+
* @param {string} out The output of WebDriver process start
543+
*/
544+
detectWebDriverProtocol(out) {
545+
if (this.driverVersion) {
546+
// Nothing is done if the protocol was already detected
547+
return;
548+
}
549+
550+
// also print chromedriver version to logs
551+
// will output something like
552+
// Starting ChromeDriver 2.33.506106 (8a06c39c4582fbfbab6966dbb1c38a9173bfb1a2) on port 9515
553+
// Or MSEdge:
554+
// Starting Microsoft Edge WebDriver 111.0.1661.41 (57be51b50d1be232a9e8186a10017d9e06b1fd16) on port 9515
555+
const match = WEBDRIVER_VERSION_PATTERN.exec(out);
556+
if (match && match.length === 3) {
557+
this.log.debug(`${match[1]} version: '${match[2]}'`);
558+
this.driverVersion = match[2];
559+
try {
560+
this.syncProtocol();
561+
} catch (e) {
562+
this.driverVersion = null;
563+
this.log.error(`Failed to sync the protocol as '${e}'. Stopping the driver process.`);
564+
this.stop();
565+
}
566+
// Does not print else condition log since the log could be
567+
// very noisy when this.verbose option is true.
568+
}
569+
}
570+
528571
/**
529572
*
530573
* @param {object} caps
@@ -589,14 +632,7 @@ class Chromedriver extends events.EventEmitter {
589632
this.log.debug(`Webview version: '${webviewVersion}'`);
590633
}
591634

592-
// also print chromedriver version to logs
593-
// will output something like
594-
// Starting ChromeDriver 2.33.506106 (8a06c39c4582fbfbab6966dbb1c38a9173bfb1a2) on port 9515
595-
match = /Starting ChromeDriver ([.\d]+)/.exec(out);
596-
if (match) {
597-
this.log.debug(`Chromedriver version: '${match[1]}'`);
598-
this.syncProtocol(match[1]);
599-
}
635+
this.detectWebDriverProtocol(out);
600636

601637
// give the output if it is requested
602638
if (this.verbose) {
@@ -613,6 +649,7 @@ class Chromedriver extends events.EventEmitter {
613649

614650
// handle out-of-bound exit by simply emitting a stopped state
615651
this.proc.on('exit', (code, signal) => {
652+
this.driverVersion = null;
616653
processIsAlive = false;
617654
if (
618655
this.state !== Chromedriver.STATE_STOPPED &&

0 commit comments

Comments
 (0)