@eyeo/get-browser-binary 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitlab-ci.yml +4 -6
- package/RELEASE_NOTES.md +10 -0
- package/package.json +9 -9
- package/src/browsers.js +74 -56
- package/src/utils.js +7 -7
- package/test/browsers.js +4 -2
- package/test/utils.js +1 -1
package/.gitlab-ci.yml
CHANGED
|
@@ -51,15 +51,13 @@ test:browsers:windows:
|
|
|
51
51
|
- choco upgrade -y nodejs --version 16.10.0
|
|
52
52
|
- npm install
|
|
53
53
|
script:
|
|
54
|
+
# Running Edge tests only on the preinstalled version
|
|
55
|
+
# https://gitlab.com/eyeo/developer-experience/get-browser-binary/-/issues/29
|
|
56
|
+
- npm test -- --grep "edge.*latest"
|
|
57
|
+
- npm test -- --grep "chromium"
|
|
54
58
|
# Running only a subset of Firefox tests to avoid low OS resources error
|
|
55
59
|
# https://gitlab.com/eyeo/developer-experience/get-browser-binary/-/issues/2
|
|
56
60
|
- npm test -- --grep "firefox.*installs"
|
|
57
|
-
# Running npm v8 on powershell has issues when the grep value contains the
|
|
58
|
-
# pipe (|) literal. Storing that string as a verbatim string (single quotes)
|
|
59
|
-
# and then sorrounding it with four double quotes does the trick.
|
|
60
|
-
# https://gitlab.com/eyeo/developer-experience/get-browser-binary/-/issues/29
|
|
61
|
-
- $full_tests = '(chromium|edge.*latest)'
|
|
62
|
-
- npm test -- --grep """"$full_tests""""
|
|
63
61
|
tags:
|
|
64
62
|
- shared-windows
|
|
65
63
|
- windows
|
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
# 0.10.0
|
|
2
|
+
|
|
3
|
+
- Added handling of the new headless mode in Chromium (#45)
|
|
4
|
+
- Fixed an issue that prevented Chromium to be installed on macOS ARM processors
|
|
5
|
+
(!59)
|
|
6
|
+
- Changed documentation nullable parameters to optional parameters (#41)
|
|
7
|
+
- Increased the npm geckodriver version to 3.1.0 (!57)
|
|
8
|
+
- Fixed an issue with Windows Edge and msedgedriver, which occasionally failed
|
|
9
|
+
when building the driver (!56)
|
|
10
|
+
|
|
1
11
|
# 0.9.0
|
|
2
12
|
|
|
3
13
|
- Fixed a Chromium install issue by increasing the value of
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eyeo/get-browser-binary",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Install browser binaries and matching webdrivers",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -30,17 +30,17 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"dmg": "^0.1.0",
|
|
32
32
|
"extract-zip": "^2.0.1",
|
|
33
|
-
"geckodriver": "
|
|
34
|
-
"got": "^
|
|
35
|
-
"jimp": "^0.
|
|
36
|
-
"selenium-webdriver": "^4.
|
|
33
|
+
"geckodriver": "3.1.0",
|
|
34
|
+
"got": "^12.5.3",
|
|
35
|
+
"jimp": "^0.22.4",
|
|
36
|
+
"selenium-webdriver": "^4.8.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"eslint": "^8.
|
|
39
|
+
"eslint": "^8.33.0",
|
|
40
40
|
"eslint-config-eyeo": "^3.2.0",
|
|
41
|
-
"expect": "^
|
|
42
|
-
"jsdoc": "^
|
|
43
|
-
"mocha": "^10.
|
|
41
|
+
"expect": "^29.4.2",
|
|
42
|
+
"jsdoc": "^4.0.0",
|
|
43
|
+
"mocha": "^10.2.0"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"docs": "jsdoc --readme README.md --destination docs src/*.js",
|
package/src/browsers.js
CHANGED
|
@@ -25,7 +25,6 @@ import webdriver from "selenium-webdriver";
|
|
|
25
25
|
import chrome from "selenium-webdriver/chrome.js";
|
|
26
26
|
import firefox from "selenium-webdriver/firefox.js";
|
|
27
27
|
import edge from "selenium-webdriver/edge.js";
|
|
28
|
-
import command from "selenium-webdriver/lib/command.js";
|
|
29
28
|
import extractZip from "extract-zip";
|
|
30
29
|
|
|
31
30
|
import {download, extractTar, extractDmg, killDriverProcess, wait}
|
|
@@ -50,12 +49,19 @@ const BROWSER_DOWNLOAD_ERROR = "Browser download failed";
|
|
|
50
49
|
const BROWSER_NOT_INSTALLED_ERROR = "Browser is not installed";
|
|
51
50
|
const ELEMENT_NOT_FOUND_ERROR = "HTML element not found";
|
|
52
51
|
|
|
52
|
+
function getMajorVersion(versionNumber) {
|
|
53
|
+
let majorVersion = parseInt(versionNumber && versionNumber.split(".")[0], 10);
|
|
54
|
+
if (isNaN(majorVersion))
|
|
55
|
+
throw new Error(`${UNSUPPORTED_VERSION_ERROR}: ${versionNumber}`);
|
|
56
|
+
|
|
57
|
+
return majorVersion;
|
|
58
|
+
}
|
|
59
|
+
|
|
53
60
|
function checkVersion(version, minVersion, channels = []) {
|
|
54
61
|
if (channels.includes(version))
|
|
55
62
|
return;
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
if (isNaN(mainVersion) || mainVersion < minVersion)
|
|
64
|
+
if (getMajorVersion(version) < minVersion)
|
|
59
65
|
throw new Error(`${UNSUPPORTED_VERSION_ERROR}: ${version}`);
|
|
60
66
|
}
|
|
61
67
|
|
|
@@ -72,19 +78,17 @@ function checkPlatform() {
|
|
|
72
78
|
class Browser {
|
|
73
79
|
/**
|
|
74
80
|
* @typedef {Object} BrowserBinary
|
|
75
|
-
* @property {string} binary
|
|
76
|
-
* @property {string} versionNumber
|
|
77
|
-
* binary.
|
|
81
|
+
* @property {string} binary The path to the browser binary.
|
|
82
|
+
* @property {string} versionNumber The version number of the browser binary.
|
|
78
83
|
*/
|
|
79
84
|
|
|
80
85
|
/**
|
|
81
86
|
* Installs the browser. The installation process is detailed on the
|
|
82
87
|
* subclasses.
|
|
83
|
-
* @param {string} version
|
|
84
|
-
* Please find examples on the subclasses.
|
|
85
|
-
* @param {number
|
|
86
|
-
* install files to complete. When set to 0 there is no time limit.
|
|
87
|
-
* to 0.
|
|
88
|
+
* @param {string} [version=latest] Either full version number or
|
|
89
|
+
* channel/release. Please find examples on the subclasses.
|
|
90
|
+
* @param {number} [downloadTimeout=0] Allowed time in ms for the download of
|
|
91
|
+
* install files to complete. When set to 0 there is no time limit.
|
|
88
92
|
* @return {BrowserBinary}
|
|
89
93
|
* @throws {Error} Unsupported browser version, Unsupported platform, Browser
|
|
90
94
|
* download failed.
|
|
@@ -95,7 +99,7 @@ class Browser {
|
|
|
95
99
|
|
|
96
100
|
/**
|
|
97
101
|
* Gets the installed version returned by the browser binary.
|
|
98
|
-
* @param {string} binary
|
|
102
|
+
* @param {string} binary The path to the browser binary.
|
|
99
103
|
* @return {string} Installed browser version.
|
|
100
104
|
*/
|
|
101
105
|
static async getInstalledVersion(binary) {
|
|
@@ -119,27 +123,28 @@ class Browser {
|
|
|
119
123
|
|
|
120
124
|
/**
|
|
121
125
|
* @typedef {Object} driverOptions
|
|
122
|
-
* @property {boolean} headless=true
|
|
123
|
-
* or not.
|
|
124
|
-
*
|
|
126
|
+
* @property {boolean} [headless=true] Run the browser in headless mode,
|
|
127
|
+
* or not. In Chromium >= 111, the
|
|
128
|
+
* {@link https://developer.chrome.com/articles/new-headless/ new headless mode}
|
|
129
|
+
* is used.
|
|
130
|
+
* @property {Array.<string>} [extensionPaths=[]] Loads extensions to the
|
|
125
131
|
* browser.
|
|
126
|
-
* @property {boolean} incognito=false
|
|
132
|
+
* @property {boolean} [incognito=false] Runs the browser in incognito mode,
|
|
127
133
|
* or not.
|
|
128
|
-
* @property {boolean} insecure=false
|
|
134
|
+
* @property {boolean} [insecure=false] Forces the browser to accept insecure
|
|
129
135
|
* certificates, or not.
|
|
130
|
-
* @property {Array.<string>} [extraArgs=[]]
|
|
136
|
+
* @property {Array.<string>} [extraArgs=[]] Additional arguments to start
|
|
131
137
|
* the browser with.
|
|
132
138
|
*/
|
|
133
139
|
|
|
134
140
|
/**
|
|
135
141
|
* Installs the webdriver matching the browser version and runs the
|
|
136
142
|
* browser. If needed, the browser binary is also installed.
|
|
137
|
-
* @param {string} version
|
|
138
|
-
* Please find examples on the subclasses.
|
|
139
|
-
* @param {driverOptions
|
|
140
|
-
* @param {number
|
|
143
|
+
* @param {string} [version=latest] Either full version number or
|
|
144
|
+
* channel/release. Please find examples on the subclasses.
|
|
145
|
+
* @param {driverOptions} [options={}] Options to start the browser with.
|
|
146
|
+
* @param {number} [downloadTimeout=0] Allowed time in ms for the download of
|
|
141
147
|
* browser install files to complete. When set to 0 there is no time limit.
|
|
142
|
-
* Defaults to 0.
|
|
143
148
|
* @return {webdriver}
|
|
144
149
|
* @throws {Error} Unsupported browser version, Unsupported platform, Browser
|
|
145
150
|
* download failed, Driver download failed, Unable to start driver.
|
|
@@ -151,8 +156,8 @@ class Browser {
|
|
|
151
156
|
/**
|
|
152
157
|
* By default, extensions are disabled in incognito mode. This function
|
|
153
158
|
* enables the extension when loaded in incognito.
|
|
154
|
-
* @param {webdriver} driver
|
|
155
|
-
* @param {string} extensionTitle
|
|
159
|
+
* @param {webdriver} driver The driver controlling the browser.
|
|
160
|
+
* @param {string} extensionTitle Title of the extension to be enabled.
|
|
156
161
|
* @return {webdriver}
|
|
157
162
|
* @throws {Error} Unsupported browser version, Extension not found, HTML
|
|
158
163
|
* element not found.
|
|
@@ -185,7 +190,7 @@ class Chromium extends Browser {
|
|
|
185
190
|
"win32-x64": "win64",
|
|
186
191
|
"linux-x64": "linux",
|
|
187
192
|
"darwin-x64": "mac",
|
|
188
|
-
"
|
|
193
|
+
"darwin-arm64": "mac_arm64"
|
|
189
194
|
}[platformArch];
|
|
190
195
|
let data = await got(`https://omahaproxy.appspot.com/all.json?os=${os}`).json();
|
|
191
196
|
let release = data[0].versions.find(ver => ver.channel == channel);
|
|
@@ -212,11 +217,10 @@ class Chromium extends Browser {
|
|
|
212
217
|
/**
|
|
213
218
|
* Installs the browser. The Chromium executable gets extracted in the
|
|
214
219
|
* {@link snapshotsBaseDir} folder, ready to go.
|
|
215
|
-
* @param {string} version
|
|
216
|
-
* number (i.e. "77.0.3865.0").
|
|
217
|
-
* @param {number
|
|
218
|
-
* install files to complete. When set to 0 there is no time limit.
|
|
219
|
-
* to 0.
|
|
220
|
+
* @param {string} [version=latest] Either "latest", "beta", "dev" or a full
|
|
221
|
+
* version number (i.e. "77.0.3865.0").
|
|
222
|
+
* @param {number} [downloadTimeout=0] Allowed time in ms for the download of
|
|
223
|
+
* install files to complete. When set to 0 there is no time limit.
|
|
220
224
|
* @return {BrowserBinary}
|
|
221
225
|
* @throws {Error} Unsupported browser version, Unsupported platform, Browser
|
|
222
226
|
* download failed.
|
|
@@ -237,7 +241,7 @@ class Chromium extends Browser {
|
|
|
237
241
|
"win32-x64": ["Win_x64", "chrome-win.zip"],
|
|
238
242
|
"linux-x64": ["Linux_x64", "chrome-linux.zip"],
|
|
239
243
|
"darwin-x64": ["Mac", "chrome-mac.zip"],
|
|
240
|
-
"
|
|
244
|
+
"darwin-arm64": ["Mac_Arm", "chrome-mac.zip"]
|
|
241
245
|
}[platformArch];
|
|
242
246
|
let archive;
|
|
243
247
|
let browserDir;
|
|
@@ -333,8 +337,14 @@ class Chromium extends Browser {
|
|
|
333
337
|
let options = new chrome.Options().addArguments("no-sandbox", ...extraArgs);
|
|
334
338
|
if (extensionPaths.length > 0)
|
|
335
339
|
options.addArguments(`load-extension=${extensionPaths.join(",")}`);
|
|
336
|
-
if (headless)
|
|
337
|
-
|
|
340
|
+
if (headless) {
|
|
341
|
+
// New headless mode introduced in Chrome 111
|
|
342
|
+
// https://developer.chrome.com/articles/new-headless/
|
|
343
|
+
if (getMajorVersion(versionNumber) >= 111)
|
|
344
|
+
options.addArguments("headless=new");
|
|
345
|
+
else
|
|
346
|
+
options.headless();
|
|
347
|
+
}
|
|
338
348
|
if (insecure)
|
|
339
349
|
options.addArguments("ignore-certificate-errors");
|
|
340
350
|
if (incognito)
|
|
@@ -423,11 +433,10 @@ class Firefox extends Browser {
|
|
|
423
433
|
/**
|
|
424
434
|
* Installs the browser. The Firefox executable gets extracted in the
|
|
425
435
|
* {@link snapshotsBaseDir} folder, ready to go.
|
|
426
|
-
* @param {string} version
|
|
427
|
-
* number (i.e. "68.0").
|
|
428
|
-
* @param {number
|
|
429
|
-
* install files to complete. When set to 0 there is no time limit.
|
|
430
|
-
* to 0.
|
|
436
|
+
* @param {string} [version=latest] Either "latest", "beta" or a full version
|
|
437
|
+
* number (i.e. "68.0").
|
|
438
|
+
* @param {number} [downloadTimeout=0] Allowed time in ms for the download of
|
|
439
|
+
* install files to complete. When set to 0 there is no time limit.
|
|
431
440
|
* @return {BrowserBinary}
|
|
432
441
|
* @throws {Error} Unsupported browser version, Unsupported platform, Browser
|
|
433
442
|
* download failed.
|
|
@@ -512,11 +521,8 @@ class Firefox extends Browser {
|
|
|
512
521
|
}, 30000, `${DRIVER_START_ERROR}: geckodriver`, 1000);
|
|
513
522
|
|
|
514
523
|
for (let extensionPath of extensionPaths) {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
.setParameter("path", extensionPath)
|
|
518
|
-
.setParameter("temporary", true)
|
|
519
|
-
);
|
|
524
|
+
let temporary = true; // Parameter not documented on the webdriver docs
|
|
525
|
+
await driver.installAddon(extensionPath, temporary);
|
|
520
526
|
}
|
|
521
527
|
return driver;
|
|
522
528
|
}
|
|
@@ -565,8 +571,7 @@ class Edge extends Browser {
|
|
|
565
571
|
versionNumbers.push(matches[2]);
|
|
566
572
|
|
|
567
573
|
let compareVersions = (v1, v2) =>
|
|
568
|
-
|
|
569
|
-
1 : -1;
|
|
574
|
+
getMajorVersion(v1) < getMajorVersion(v2) ? 1 : -1;
|
|
570
575
|
versionNumber = versionNumbers.sort(compareVersions)[0];
|
|
571
576
|
}
|
|
572
577
|
else {
|
|
@@ -613,11 +618,10 @@ class Edge extends Browser {
|
|
|
613
618
|
* Installs the browser. On Linux, Edge is installed as a system package,
|
|
614
619
|
* which requires root permissions. On MacOS, Edge is installed as a user
|
|
615
620
|
* app (not as a system app). Installing Edge on Windows is not supported.
|
|
616
|
-
* @param {string} version
|
|
617
|
-
* number (i.e. "95.0.1020.40").
|
|
618
|
-
* @param {number
|
|
619
|
-
* install files to complete. When set to 0 there is no time limit.
|
|
620
|
-
* to 0.
|
|
621
|
+
* @param {string} [version=latest] Either "latest", "beta", "dev" or a full
|
|
622
|
+
* version number (i.e. "95.0.1020.40").
|
|
623
|
+
* @param {number} [downloadTimeout=0] Allowed time in ms for the download of
|
|
624
|
+
* install files to complete. When set to 0 there is no time limit.
|
|
621
625
|
* @return {BrowserBinary}
|
|
622
626
|
* @throws {Error} Unsupported browser version, Unsupported platform, Browser
|
|
623
627
|
* download failed.
|
|
@@ -760,7 +764,22 @@ class Edge extends Browser {
|
|
|
760
764
|
builder.setEdgeOptions(options);
|
|
761
765
|
builder.setEdgeService(serviceBuilder);
|
|
762
766
|
|
|
763
|
-
|
|
767
|
+
let driver;
|
|
768
|
+
// On Windows CI, occasionally a SessionNotCreatedError is thrown, likely
|
|
769
|
+
// due to low OS resources, that's why building the driver is retried
|
|
770
|
+
await wait(async() => {
|
|
771
|
+
try {
|
|
772
|
+
driver = await builder.build();
|
|
773
|
+
return true;
|
|
774
|
+
}
|
|
775
|
+
catch (err) {
|
|
776
|
+
if (err.name != "SessionNotCreatedError")
|
|
777
|
+
throw err;
|
|
778
|
+
await killDriverProcess("msedgedriver");
|
|
779
|
+
}
|
|
780
|
+
}, 30000, `${DRIVER_START_ERROR}: msedgedriver`, 1000);
|
|
781
|
+
|
|
782
|
+
return driver;
|
|
764
783
|
}
|
|
765
784
|
|
|
766
785
|
/** @see Browser.enableExtensionInIncognito */
|
|
@@ -787,11 +806,10 @@ class Edge extends Browser {
|
|
|
787
806
|
|
|
788
807
|
/**
|
|
789
808
|
* @type {Object}
|
|
790
|
-
* @property {Chromium} chromium
|
|
809
|
+
* @property {Chromium} chromium Browser and webdriver functionality for
|
|
791
810
|
* Chromium.
|
|
792
|
-
* @property {Firefox} firefox
|
|
793
|
-
*
|
|
794
|
-
* @property {Edge} edge - Browser and webdriver functionality for Edge.
|
|
811
|
+
* @property {Firefox} firefox Browser and webdriver functionality for Firefox.
|
|
812
|
+
* @property {Edge} edge Browser and webdriver functionality for Edge.
|
|
795
813
|
*/
|
|
796
814
|
export const BROWSERS = {
|
|
797
815
|
chromium: Chromium,
|
package/src/utils.js
CHANGED
|
@@ -28,10 +28,10 @@ import Jimp from "jimp";
|
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* Downloads url resources.
|
|
31
|
-
* @param {string} url
|
|
32
|
-
* @param {string} destFile
|
|
33
|
-
* @param {number
|
|
34
|
-
* When set to 0 there is no time limit.
|
|
31
|
+
* @param {string} url The url of the resource to be downloaded.
|
|
32
|
+
* @param {string} destFile The destination file path.
|
|
33
|
+
* @param {number} [timeout=0] Allowed time in ms for the download to complete.
|
|
34
|
+
* When set to 0 there is no time limit.
|
|
35
35
|
* @throws {TypeError} Invalid URL, Download timeout.
|
|
36
36
|
*/
|
|
37
37
|
export async function download(url, destFile, timeout = 0) {
|
|
@@ -164,9 +164,9 @@ export function wait(condition, timeout = 0, message, pollTimeout = 100) {
|
|
|
164
164
|
|
|
165
165
|
/**
|
|
166
166
|
* Takes a screenshot of the full page by scrolling from top to bottom.
|
|
167
|
-
* @param {webdriver} driver
|
|
168
|
-
* @
|
|
169
|
-
*
|
|
167
|
+
* @param {webdriver} driver The driver controlling the browser.
|
|
168
|
+
* @param {boolean} [hideScrollbars=true] Hides any scrollbars before taking
|
|
169
|
+
* the screenshot, or not.
|
|
170
170
|
* @return {Jimp} A Jimp image object containing the screenshot.
|
|
171
171
|
* @example
|
|
172
172
|
* // Getting a base-64 encoded PNG from the returned Jimp image
|
package/test/browsers.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import fs from "fs";
|
|
19
|
-
import expect from "expect";
|
|
19
|
+
import {expect} from "expect";
|
|
20
20
|
import path from "path";
|
|
21
21
|
|
|
22
22
|
import {BROWSERS, snapshotsBaseDir, takeFullPageScreenshot} from "../index.js";
|
|
@@ -242,7 +242,9 @@ for (let browser of Object.keys(BROWSERS)) {
|
|
|
242
242
|
});
|
|
243
243
|
|
|
244
244
|
it("loads an extension", async() => {
|
|
245
|
-
|
|
245
|
+
// Chromium's old headless mode doesn't support loading extensions
|
|
246
|
+
let headless = browser == "firefox" || (browser == "chromium" &&
|
|
247
|
+
["latest", "beta", "dev"].includes(version));
|
|
246
248
|
let {extensionPaths} = getExtension(browser, version);
|
|
247
249
|
|
|
248
250
|
driver = await BROWSERS[browser].getDriver(
|