From 3b5a865e8cc93b662705d05b908d28bc370088e6 Mon Sep 17 00:00:00 2001 From: Sriharsha Date: Fri, 28 Oct 2022 18:17:41 +0530 Subject: [PATCH 1/5] [JS] add support for selenium manager --- .../node/selenium-webdriver/BUILD.bazel | 23 +++++ javascript/node/selenium-webdriver/chrome.js | 17 ++-- .../common/seleniumManager.js | 87 +++++++++++++++++++ javascript/node/selenium-webdriver/firefox.js | 16 ++-- .../test/lib/webdriver_test.js | 2 +- 5 files changed, 131 insertions(+), 14 deletions(-) create mode 100644 javascript/node/selenium-webdriver/common/seleniumManager.js diff --git a/javascript/node/selenium-webdriver/BUILD.bazel b/javascript/node/selenium-webdriver/BUILD.bazel index 3a92bb12a5608..60c83fe52d508 100644 --- a/javascript/node/selenium-webdriver/BUILD.bazel +++ b/javascript/node/selenium-webdriver/BUILD.bazel @@ -23,6 +23,7 @@ SRC_FILES = [ "remote/*.js", "testing/*.js", "devtools/*.js", + "common/*.js" ]) pkg_npm( @@ -31,6 +32,9 @@ pkg_npm( srcs = SRC_FILES, deps = [ ":license", + ":manager-linux", + ":manager-macos", + ":manager-windows", "//javascript/node/selenium-webdriver/lib/atoms:find-elements", "//javascript/node/selenium-webdriver/lib/atoms:get_attribute", "//javascript/node/selenium-webdriver/lib/atoms:is_displayed", @@ -141,3 +145,22 @@ genrule( ":cdp-srcs-generator-" + n, ], ) for n in BROWSER_VERSIONS] + + +copy_file( + name = "manager-linux", + src = "//common/manager:linux/selenium-manager", + out = "bin/linux/selenium-manager", +) + +copy_file( + name = "manager-windows", + src = "//common/manager:windows/selenium-manager.exe", + out = "bin/windows/selenium-manager.exe", +) + +copy_file( + name = "manager-macos", + src = "//common/manager:macos/selenium-manager", + out = "bin/macos/selenium-manager", +) diff --git a/javascript/node/selenium-webdriver/chrome.js b/javascript/node/selenium-webdriver/chrome.js index f0ab9c14bb5b6..cee89bd1d0204 100644 --- a/javascript/node/selenium-webdriver/chrome.js +++ b/javascript/node/selenium-webdriver/chrome.js @@ -130,6 +130,7 @@ const io = require('./io') const { Browser } = require('./lib/capabilities') const chromium = require('./chromium') +const { driverLocation } = require('./common/seleniumManager') /** * Name of the ChromeDriver executable. @@ -150,19 +151,23 @@ class ServiceBuilder extends chromium.ServiceBuilder { /** * @param {string=} opt_exe Path to the server executable to use. If omitted, * the builder will attempt to locate the chromedriver on the current - * PATH. + * PATH. If the chromedriver is not available in path, selenium-manager will + * download the chromedriver * @throws {Error} If provided executable does not exist, or the chromedriver * cannot be found on the PATH. */ constructor(opt_exe) { let exe = opt_exe || locateSynchronously() + if (!exe) { - throw Error( - `The ChromeDriver could not be found on the current PATH. Please ` + - `download the latest version of the ChromeDriver from ` + - `http://chromedriver.storage.googleapis.com/index.html and ensure ` + - `it can be found on your PATH.` + console.log( + ` The ChromeDriver could not be found on the current PATH, trying Selenium Manager` ) + exe = driverLocation(Browser.CHROME) + } + + if (!exe) { + throw Error(`Unable to obtain driver using Selenium Manager`) } super(exe) } diff --git a/javascript/node/selenium-webdriver/common/seleniumManager.js b/javascript/node/selenium-webdriver/common/seleniumManager.js new file mode 100644 index 0000000000000..a5f9f1ef450fc --- /dev/null +++ b/javascript/node/selenium-webdriver/common/seleniumManager.js @@ -0,0 +1,87 @@ +/* + * Licensed to the Software Freedom Conservancy (SFC) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The SFC licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Wrapper for getting information from the Selenium Manager binaries + */ + +const { platform } = require('process') +const path = require('path') +const fs = require('fs') +const execSync = require('child_process').execSync + +/** + * currently supported browsers for selenium-manager + * @type {string[]} + */ +const Browser = ['chrome', 'firefox'] + +/** + * Determines the path of the correct Selenium Manager binary + * @returns {string} + */ +function getBinary() { + const directory = { + darwin: 'macos', + win32: 'windows', + cygwin: 'windows', + linux: 'linux', + }[platform] + + const file = + directory === 'windows' ? 'selenium-manager.exe' : 'selenium-manager' + + const filePath = path.join(__dirname, '..', '/bin', directory, file) + + if (!fs.existsSync(filePath)) { + throw new Error(`Unable to obtain Selenium Manager`) + } + + return filePath +} + +/** + * Determines the path of the correct driver + * @param {Browser|string} browser name to fetch the driver + * @returns {string} path of the driver location + */ + +function driverLocation(browser) { + if (!Browser.includes(browser.toLocaleString())) { + throw new Error( + `Unable to locate driver associated with browser name: ${browser}` + ) + } + + let args = [getBinary(), '--browser', browser] + let result + + try { + result = execSync(args.join(' ')).toString() + } catch (e) { + throw new Error( + `Error executing command with ${args} : Error ${e.stderr.toString()}` + ) + } + + return result.replace('INFO\t', '').trim() +} + +// PUBLIC API +module.exports = { driverLocation } diff --git a/javascript/node/selenium-webdriver/firefox.js b/javascript/node/selenium-webdriver/firefox.js index cf5885afb3eb1..99f4f06306011 100644 --- a/javascript/node/selenium-webdriver/firefox.js +++ b/javascript/node/selenium-webdriver/firefox.js @@ -127,6 +127,7 @@ const webdriver = require('./lib/webdriver') const zip = require('./io/zip') const { Browser, Capabilities } = require('./lib/capabilities') const { Zip } = require('./io/zip') +const { driverLocation } = require('./common/seleniumManager') /** * Thrown when there an add-on is malformed. @@ -459,15 +460,16 @@ function locateSynchronously() { */ function findGeckoDriver() { let exe = locateSynchronously() + if (!exe) { - throw Error( - 'The ' + - GECKO_DRIVER_EXE + - ' executable could not be found on the current ' + - 'PATH. Please download the latest version from ' + - 'https://github.com/mozilla/geckodriver/releases/ ' + - 'and ensure it can be found on your PATH.' + console.log( + `The ${GECKO_DRIVER_EXE} executable could not be found on the current PATH, trying Selenium Manager` ) + exe = driverLocation(Browser.FIREFOX) + } + + if (!exe) { + throw Error(`Unable to obtain driver using Selenium Manager`) } return exe } diff --git a/javascript/node/selenium-webdriver/test/lib/webdriver_test.js b/javascript/node/selenium-webdriver/test/lib/webdriver_test.js index 60261eac93c3a..a983d3bbe31dd 100644 --- a/javascript/node/selenium-webdriver/test/lib/webdriver_test.js +++ b/javascript/node/selenium-webdriver/test/lib/webdriver_test.js @@ -228,7 +228,7 @@ describe('WebDriver', function () { .expect(CName.NEW_SESSION) .withParameters({ capabilities: { - alwaysMatch: { browserName: 'firefox'}, + alwaysMatch: { browserName: 'firefox' }, firstMatch: [{}], }, }) From 950b78972f9865c9f611cd3f0c649dfea9cafc07 Mon Sep 17 00:00:00 2001 From: Sriharsha Date: Fri, 28 Oct 2022 19:13:33 +0530 Subject: [PATCH 2/5] [JS] set visibility to js bindings --- common/manager/BUILD.bazel | 1 + 1 file changed, 1 insertion(+) diff --git a/common/manager/BUILD.bazel b/common/manager/BUILD.bazel index 6f794fc6ca061..9d95d82ce2a7a 100644 --- a/common/manager/BUILD.bazel +++ b/common/manager/BUILD.bazel @@ -26,5 +26,6 @@ exports_files( "//java/test/org/openqa/selenium/firefox:__pkg__", "//py:__pkg__", "//rb:__pkg__", + "//javascript/node/selenium-webdriver:__pkg__", ], ) From 61a1a015f033b0657790f423d56da1930ab5297c Mon Sep 17 00:00:00 2001 From: titusfortner Date: Fri, 28 Oct 2022 09:08:52 -0500 Subject: [PATCH 3/5] [js] run CI with drivers from Selenium Manager --- .github/workflows/ci-javascript.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci-javascript.yml b/.github/workflows/ci-javascript.yml index 4b3a9c30ec721..b6ed591228d3b 100644 --- a/.github/workflows/ci-javascript.yml +++ b/.github/workflows/ci-javascript.yml @@ -53,16 +53,17 @@ jobs: java-version: 11 - name: Setup Fluxbox run: sudo apt-get -y install fluxbox - - name: Setup Firefox and GeckoDriver - uses: ./.github/actions/setup-firefox + - name: Setup Firefox + uses: abhi1693/setup-browser@v0.3.4 with: + browser: firefox version: ${{ matrix.version }} if: | matrix.browser == 'firefox' - - name: Setup Chrome and ChromeDriver - uses: ./.github/actions/setup-chrome + - name: Setup Chrome + uses: browser-actions/setup-chrome@latest with: - version: ${{ matrix.version }} + chrome-version: ${{ matrix.version }} if: | matrix.browser == 'chrome' - name: Start XVFB @@ -98,9 +99,10 @@ jobs: java-version: 11 - name: Setup Fluxbox run: sudo apt-get -y install fluxbox - - name: Setup Firefox and GeckoDriver - uses: ./.github/actions/setup-firefox + - name: Setup Firefox + uses: abhi1693/setup-browser@v0.3.4 with: + browser: firefox version: ${{ matrix.version }} - name: Start XVFB run: Xvfb :99 & From 7f72a9748dfc1811f43a90751bc0e9b696e7016c Mon Sep 17 00:00:00 2001 From: Sriharsha Date: Mon, 31 Oct 2022 16:59:36 +0530 Subject: [PATCH 4/5] [JS] throw legacy error msg if driver not found in both ways, and wrap code in try/catch --- javascript/node/selenium-webdriver/chrome.js | 15 +++++++++++---- .../selenium-webdriver/common/seleniumManager.js | 4 ++++ javascript/node/selenium-webdriver/firefox.js | 14 ++++++++++---- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/javascript/node/selenium-webdriver/chrome.js b/javascript/node/selenium-webdriver/chrome.js index cee89bd1d0204..2c765f07622b1 100644 --- a/javascript/node/selenium-webdriver/chrome.js +++ b/javascript/node/selenium-webdriver/chrome.js @@ -163,12 +163,19 @@ class ServiceBuilder extends chromium.ServiceBuilder { console.log( ` The ChromeDriver could not be found on the current PATH, trying Selenium Manager` ) - exe = driverLocation(Browser.CHROME) - } - if (!exe) { - throw Error(`Unable to obtain driver using Selenium Manager`) + try { + exe = driverLocation(Browser.CHROME) + } catch (e) { + throw Error( + `The ChromeDriver could not be found on the current PATH. + Please download the latest version of the ChromeDriver + from http://chromedriver.storage.googleapis.com/index.html + and ensure it can be found on your PATH.` + ) + } } + super(exe) } } diff --git a/javascript/node/selenium-webdriver/common/seleniumManager.js b/javascript/node/selenium-webdriver/common/seleniumManager.js index a5f9f1ef450fc..d9e88f7c39fdd 100644 --- a/javascript/node/selenium-webdriver/common/seleniumManager.js +++ b/javascript/node/selenium-webdriver/common/seleniumManager.js @@ -80,6 +80,10 @@ function driverLocation(browser) { ) } + if (!result.startsWith('INFO\t')) { + throw new Error(`Unsuccessful command executed ${args}}`) + } + return result.replace('INFO\t', '').trim() } diff --git a/javascript/node/selenium-webdriver/firefox.js b/javascript/node/selenium-webdriver/firefox.js index 99f4f06306011..15e299fbed2dc 100644 --- a/javascript/node/selenium-webdriver/firefox.js +++ b/javascript/node/selenium-webdriver/firefox.js @@ -465,12 +465,18 @@ function findGeckoDriver() { console.log( `The ${GECKO_DRIVER_EXE} executable could not be found on the current PATH, trying Selenium Manager` ) - exe = driverLocation(Browser.FIREFOX) - } - if (!exe) { - throw Error(`Unable to obtain driver using Selenium Manager`) + try { + exe = driverLocation(Browser.FIREFOX) + } catch (e) { + throw Error( + `The ${GECKO_DRIVER_EXE} executable could not be found on the current PATH. + Please download the latest version from https://github.com/mozilla/geckodriver/releases/ + and ensure it can be found on your PATH.` + ) + } } + return exe } From aa2e42d84f5002086914dfae91fa9f454aa7929f Mon Sep 17 00:00:00 2001 From: Sriharsha Date: Tue, 1 Nov 2022 13:09:11 +0530 Subject: [PATCH 5/5] [JS] add selenium-manager edge support --- javascript/node/selenium-webdriver/chrome.js | 18 +++++++++++------- .../common/seleniumManager.js | 2 +- javascript/node/selenium-webdriver/edge.js | 15 +++++++++++++++ javascript/node/selenium-webdriver/firefox.js | 14 +++++++++----- 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/javascript/node/selenium-webdriver/chrome.js b/javascript/node/selenium-webdriver/chrome.js index 2c765f07622b1..68e4e6a892705 100644 --- a/javascript/node/selenium-webdriver/chrome.js +++ b/javascript/node/selenium-webdriver/chrome.js @@ -166,16 +166,20 @@ class ServiceBuilder extends chromium.ServiceBuilder { try { exe = driverLocation(Browser.CHROME) - } catch (e) { - throw Error( - `The ChromeDriver could not be found on the current PATH. - Please download the latest version of the ChromeDriver - from http://chromedriver.storage.googleapis.com/index.html - and ensure it can be found on your PATH.` - ) + } catch (err) { + console.log(`Unable to obtain driver using Selenium Manager: ${err}`) } } + if (!exe) { + throw Error( + `The ChromeDriver could not be found on the current PATH. + Please download the latest version of the ChromeDriver + from http://chromedriver.storage.googleapis.com/index.html + and ensure it can be found on your PATH.` + ) + } + super(exe) } } diff --git a/javascript/node/selenium-webdriver/common/seleniumManager.js b/javascript/node/selenium-webdriver/common/seleniumManager.js index d9e88f7c39fdd..26206fb6525d2 100644 --- a/javascript/node/selenium-webdriver/common/seleniumManager.js +++ b/javascript/node/selenium-webdriver/common/seleniumManager.js @@ -30,7 +30,7 @@ const execSync = require('child_process').execSync * currently supported browsers for selenium-manager * @type {string[]} */ -const Browser = ['chrome', 'firefox'] +const Browser = ['chrome', 'firefox', 'edge'] /** * Determines the path of the correct Selenium Manager binary diff --git a/javascript/node/selenium-webdriver/edge.js b/javascript/node/selenium-webdriver/edge.js index 9dd54d5a516d1..2247a2b790434 100644 --- a/javascript/node/selenium-webdriver/edge.js +++ b/javascript/node/selenium-webdriver/edge.js @@ -80,6 +80,7 @@ const { Browser } = require('./lib/capabilities') const io = require('./io') const chromium = require('./chromium') +const { driverLocation } = require('./common/seleniumManager') /** * Name of the EdgeDriver executable. @@ -106,6 +107,19 @@ class ServiceBuilder extends chromium.ServiceBuilder { */ constructor(opt_exe) { let exe = opt_exe || locateSynchronously() + + if (!exe) { + console.log( + `The WebDriver for Edge could not be found on the current PATH, trying Selenium Manager` + ) + + try { + exe = driverLocation('edge') + } catch (err) { + console.log(`Unable to obtain driver using Selenium Manager: ${err}`) + } + } + if (!exe) { throw Error( `The WebDriver for Edge could not be found on the current PATH. Please download the ` + @@ -114,6 +128,7 @@ class ServiceBuilder extends chromium.ServiceBuilder { `and ensure it can be found on your PATH.` ) } + super(exe) this.setLoopback(true) } diff --git a/javascript/node/selenium-webdriver/firefox.js b/javascript/node/selenium-webdriver/firefox.js index 15e299fbed2dc..c796740f71412 100644 --- a/javascript/node/selenium-webdriver/firefox.js +++ b/javascript/node/selenium-webdriver/firefox.js @@ -468,13 +468,17 @@ function findGeckoDriver() { try { exe = driverLocation(Browser.FIREFOX) - } catch (e) { - throw Error( - `The ${GECKO_DRIVER_EXE} executable could not be found on the current PATH. + } catch (err) { + console.log(`Unable to obtain driver using Selenium Manager: ${err}`) + } + } + + if (!exe) { + throw Error( + `The ${GECKO_DRIVER_EXE} executable could not be found on the current PATH. Please download the latest version from https://github.com/mozilla/geckodriver/releases/ and ensure it can be found on your PATH.` - ) - } + ) } return exe