@eyeo/get-browser-binary
Version:
Install browser binaries and matching webdrivers
138 lines (127 loc) • 5.46 kB
JavaScript
/*
* Copyright (c) 2006-present eyeo GmbH
*
* This module is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {exec, execFile} from "child_process";
import {promisify} from "util";
import {errMsg} from "./utils.js";
/**
* Base class for browser and webdriver functionality. Please see subclasses for
* browser specific details. All classes can be used statically.
* @hideconstructor
*/
export class Browser {
/**
* @typedef {Object} BrowserBinary
* @property {string} binary The path to the browser binary.
* @property {string} versionNumber The version number of the browser binary.
*/
/**
* Installs the browser. The installation process is detailed on the
* subclasses.
* @param {string} [version=latest] Either full version number or
* channel/release. Please find examples on the subclasses.
* @param {number} [downloadTimeout=0] Allowed time in ms for the download of
* install files to complete. When set to 0 there is no time limit.
* @return {BrowserBinary}
* @throws {Error} Unsupported browser version, Unsupported platform, Browser
* download failed.
*/
static async installBrowser(version, downloadTimeout = 0) {
// to be implemented by the subclass
}
/**
* Gets the installed version returned by the browser binary. Subclasses add
* specific parsing to this function.
* @param {string} binary The path to the browser binary.
* @return {string} Installed browser version.
* @throws {Error} Browser is not installed.
*/
static async getInstalledVersion(binary) {
try {
let stdout;
let stderr;
if (process.platform == "win32") {
({stdout, stderr} = await promisify(exec)(
`(Get-ItemProperty ${binary}).VersionInfo.ProductVersion`,
{shell: "powershell.exe"})
);
}
else {
({stdout, stderr} = await promisify(execFile)(binary, ["--version"]));
}
if (stderr)
throw new Error(stderr);
return stdout.trim();
}
catch (err) {
throw new Error(`${errMsg.browserNotInstalled}.\nBinary path: ${binary}\n${err}`);
}
}
/**
* @typedef {Object} webdriver
* @see https://www.selenium.dev/selenium/docs/api/javascript/index.html
*/
/**
* @typedef {Object} driverOptions
* @property {boolean} [headless=true] Run the browser in headless mode,
* or not. In Chromium >= 111 and Edge >= 114 the
* {@link https://developer.chrome.com/articles/new-headless/ new headless mode}
* is used.
* @property {Array.<string>} [extensionPaths=[]] Paths to folders containing
* unpacked extensions which will be loaded to the browser.
* @property {boolean} [incognito=false] Runs the browser in incognito mode,
* or not.
* @property {boolean} [insecure=false] Forces the browser to accept insecure
* certificates, or not.
* @property {Array.<string>} [extraArgs=[]] Additional arguments to start
* the browser with.
* @property {string} [proxy] Only for Firefox, path to network
* proxy autoconfig url (PAC file).
* @property {string} [customBrowserBinary] Path to the browser binary to be
* used, instead of the browser installed by installBrowser(). This option
* overrides the version parameter in getDriver().
*/
/**
* Installs the webdriver matching the browser version and runs the
* browser. If needed, the browser binary is also installed.
* @param {string} [version=latest] Either full version number or
* channel/release. Please find examples on the subclasses.
* @param {driverOptions} [options={}] Options to start the browser with.
* @param {number} [downloadTimeout=0] Allowed time in ms for the download of
* browser install files to complete. When set to 0 there is no time limit.
* @return {webdriver}
* @throws {Error} Unsupported browser version, Unsupported platform, Browser
* download failed, Driver download failed, Unable to start driver, Manifest
* file not found.
*/
static async getDriver(version, options = {}, downloadTimeout = 0) {
// to be implemented by the subclass
}
/**
* By default, extensions are disabled in incognito mode. This function
* enables the extension when loaded in incognito.
* @param {webdriver} driver The driver controlling the browser.
* @param {string} extensionTitle Title of the extension to be enabled.
* @throws {Error} Unsupported browser version, Extension not found, HTML
* element not found.
*/
static async enableExtensionInIncognito(driver, extensionTitle) {
// Allowing the extension in incognito mode can't happen programmatically:
// https://stackoverflow.com/questions/57419654
// https://bugzilla.mozilla.org/show_bug.cgi?id=1729315
// That is done through the UI, to be implemented by the subclass
}
}