@eyeo/get-browser-binary 0.3.0 → 0.5.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/.dockerignore +3 -0
- package/.eslintrc.json +2 -1
- package/.gitlab-ci.yml +18 -13
- package/CODE_OF_CONDUCT.md +132 -0
- package/README.md +40 -11
- package/RELEASE_NOTES.md +14 -0
- package/package.json +1 -2
- package/src/browsers.js +499 -116
- package/src/utils.js +51 -8
- package/test/.eslintrc.json +2 -1
- package/test/browsers.js +136 -75
- package/test/docker/Dockerfile +9 -0
- package/test/docker/entrypoint.sh +4 -0
package/src/utils.js
CHANGED
|
@@ -56,7 +56,7 @@ export async function download(url, destFile) {
|
|
|
56
56
|
|
|
57
57
|
export async function extractTar(archive, dir) {
|
|
58
58
|
await fs.promises.mkdir(dir);
|
|
59
|
-
await promisify(exec)(
|
|
59
|
+
await promisify(exec)(`tar -jxf ${archive} -C ${dir}`);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
export async function extractDmg(archive, dir) {
|
|
@@ -78,17 +78,12 @@ export async function extractDmg(archive, dir) {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
export async function runWinInstaller(archive, dir) {
|
|
82
|
-
// Procedure inspired from mozinstall. Uninstaller will also need to be run.
|
|
83
|
-
// https://hg.mozilla.org/mozilla-central/file/tip/testing/mozbase/mozinstall/mozinstall/mozinstall.py
|
|
84
|
-
await promisify(exec)(`"${archive}" /extractdir=${dir}`);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
81
|
export async function getBrowserVersion(driver) {
|
|
88
82
|
let version = (await driver.getCapabilities()).getBrowserVersion();
|
|
89
|
-
return parseInt(version.split(".")[0], 10);
|
|
83
|
+
return version ? parseInt(version.split(".")[0], 10) : null;
|
|
90
84
|
}
|
|
91
85
|
|
|
86
|
+
// Useful to unlock the driver file before replacing it or executing it
|
|
92
87
|
export async function killDriverProcess(driverName) {
|
|
93
88
|
let cmd = `kill $(pgrep ${driverName})`;
|
|
94
89
|
let shell;
|
|
@@ -106,3 +101,51 @@ export async function killDriverProcess(driverName) {
|
|
|
106
101
|
throw err;
|
|
107
102
|
}
|
|
108
103
|
}
|
|
104
|
+
|
|
105
|
+
export function wait(condition, timeout = 0, message, pollTimeout = 100) {
|
|
106
|
+
if (typeof condition !== "function")
|
|
107
|
+
throw TypeError("Wait condition must be a function");
|
|
108
|
+
|
|
109
|
+
function evaluateCondition() {
|
|
110
|
+
return new Promise((resolve, reject) => {
|
|
111
|
+
try {
|
|
112
|
+
resolve(condition(this));
|
|
113
|
+
}
|
|
114
|
+
catch (ex) {
|
|
115
|
+
reject(ex);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
let result = new Promise((resolve, reject) => {
|
|
121
|
+
let startTime = Date.now();
|
|
122
|
+
let pollCondition = async() => {
|
|
123
|
+
evaluateCondition().then(value => {
|
|
124
|
+
let elapsed = Date.now() - startTime;
|
|
125
|
+
if (value) {
|
|
126
|
+
resolve(value);
|
|
127
|
+
}
|
|
128
|
+
else if (timeout && elapsed >= timeout) {
|
|
129
|
+
try {
|
|
130
|
+
let timeoutMessage = message ?
|
|
131
|
+
`${typeof message === "function" ? message() : message}\n` : "";
|
|
132
|
+
reject(
|
|
133
|
+
new Error(`${timeoutMessage}Wait timed out after ${elapsed}ms`)
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
catch (ex) {
|
|
137
|
+
reject(
|
|
138
|
+
new Error(`${ex.message}\nWait timed out after ${elapsed}ms`)
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
setTimeout(pollCondition, pollTimeout);
|
|
144
|
+
}
|
|
145
|
+
}, reject);
|
|
146
|
+
};
|
|
147
|
+
pollCondition();
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
return result;
|
|
151
|
+
}
|
package/test/.eslintrc.json
CHANGED
package/test/browsers.js
CHANGED
|
@@ -24,13 +24,15 @@ import {killDriverProcess} from "../src/utils.js";
|
|
|
24
24
|
|
|
25
25
|
// Required to set the driver path on Windows
|
|
26
26
|
import "chromedriver";
|
|
27
|
-
import "
|
|
27
|
+
import "geckodriver";
|
|
28
28
|
|
|
29
29
|
const VERSIONS = {
|
|
30
|
-
chromium: [
|
|
31
|
-
firefox: [
|
|
32
|
-
edge: [
|
|
30
|
+
chromium: ["latest", "75.0.3770.0", "beta", "dev"],
|
|
31
|
+
firefox: ["latest", "60.0", "beta"],
|
|
32
|
+
edge: ["latest", "95.0.1020.53", "beta", "dev"],
|
|
33
|
+
opera: ["latest", "62.0.3331.66"]
|
|
33
34
|
};
|
|
35
|
+
const TEST_URL = "https://gitlab.com/eyeo/developer-experience/get-browser-binary";
|
|
34
36
|
let extensionPaths = [path.resolve(process.cwd(), "test", "extension")];
|
|
35
37
|
|
|
36
38
|
async function switchToHandle(driver, testFn) {
|
|
@@ -62,85 +64,144 @@ async function getHandle(driver, page) {
|
|
|
62
64
|
return handle;
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
catch (e) {}
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
let driver = null;
|
|
78
|
-
afterEach(async() => {
|
|
79
|
-
if (!driver)
|
|
80
|
-
return;
|
|
81
|
-
|
|
82
|
-
await driver.quit();
|
|
83
|
-
driver = null;
|
|
84
|
-
// Some platforms don't immediately kill the chromedriver process
|
|
85
|
-
if (browser == "chromium")
|
|
86
|
-
await killDriverProcess("chromedriver");
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("downloads", async function() {
|
|
90
|
-
if (browser == "edge")
|
|
91
|
-
// Edge download is not implemented. It is assumed to be installed.
|
|
92
|
-
this.skip();
|
|
93
|
-
|
|
94
|
-
this.timeout(40000);
|
|
95
|
-
let {binary} = await BROWSERS[browser].downloadBinary(version);
|
|
96
|
-
|
|
97
|
-
await fs.promises.access(binary);
|
|
98
|
-
expect(binary).toEqual(
|
|
99
|
-
expect.stringContaining(path.join(snapshotsBaseDir, browser)));
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it("runs", async() => {
|
|
103
|
-
let names = {
|
|
104
|
-
chromium: "chrome",
|
|
105
|
-
firefox: "firefox",
|
|
106
|
-
edge: /(MicrosoftEdge|msedge)/
|
|
107
|
-
};
|
|
67
|
+
function normalize(version) {
|
|
68
|
+
// Discards any numbers after the third dot. For example, "103.0.5060.134"
|
|
69
|
+
// will return "103.0.5060", and "68.0" will return "68.0"
|
|
70
|
+
let normalized = version.split(".").slice(0, 3).join(".");
|
|
71
|
+
// On Windows, Firefox beta versions look like "103.0b9", but the installed
|
|
72
|
+
// version returned by the browser is actually "103.0"
|
|
73
|
+
return normalized.split("b")[0];
|
|
74
|
+
}
|
|
108
75
|
|
|
109
|
-
|
|
110
|
-
|
|
76
|
+
function getWindowSize(driver) {
|
|
77
|
+
return driver.executeScript(() => {
|
|
78
|
+
return {height: window.innerHeight, width: window.innerWidth};
|
|
79
|
+
});
|
|
80
|
+
}
|
|
111
81
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
82
|
+
expect.extend({
|
|
83
|
+
toMeasureLessThan(small, big) {
|
|
84
|
+
let pass = small.width < big.width || small.height < big.height;
|
|
85
|
+
let message = () =>
|
|
86
|
+
`expected small sizes (w: ${small.width}, h: ${small.height}) ` +
|
|
87
|
+
`to be smaller than big sizes (w: ${big.width}, h: ${big.height})`;
|
|
88
|
+
if (pass)
|
|
89
|
+
return {message, pass: true};
|
|
90
|
+
return {message, pass: false};
|
|
91
|
+
}
|
|
92
|
+
});
|
|
115
93
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
94
|
+
for (let browser of Object.keys(BROWSERS)) {
|
|
95
|
+
describe(`Browser: ${browser}`, function() {
|
|
96
|
+
this.timeout(150000);
|
|
97
|
+
|
|
98
|
+
before(async() => {
|
|
99
|
+
try {
|
|
100
|
+
await fs.promises.rm(snapshotsBaseDir, {recursive: true});
|
|
101
|
+
}
|
|
102
|
+
catch (e) {}
|
|
103
|
+
});
|
|
121
104
|
|
|
122
|
-
|
|
123
|
-
|
|
105
|
+
for (let version of VERSIONS[browser]) {
|
|
106
|
+
describe(`Version: ${version}`, () => {
|
|
107
|
+
let driver = null;
|
|
108
|
+
|
|
109
|
+
async function quitDriver() {
|
|
110
|
+
if (!driver)
|
|
111
|
+
return;
|
|
112
|
+
|
|
113
|
+
await driver.quit();
|
|
114
|
+
driver = null;
|
|
115
|
+
// Some platforms don't immediately kill the driver process
|
|
116
|
+
if (browser == "chromium")
|
|
117
|
+
await killDriverProcess("chromedriver");
|
|
118
|
+
else if (browser == "firefox")
|
|
119
|
+
await killDriverProcess("geckodriver");
|
|
120
|
+
}
|
|
124
121
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
122
|
+
afterEach(quitDriver);
|
|
123
|
+
|
|
124
|
+
it("downloads", async function() {
|
|
125
|
+
if (browser == "edge" && process.platform == "win32")
|
|
126
|
+
this.skip();
|
|
127
|
+
|
|
128
|
+
let {binary, versionNumber} =
|
|
129
|
+
await BROWSERS[browser].downloadBinary(version);
|
|
130
|
+
let browserName =
|
|
131
|
+
browser == "opera" ? /(opera|Opera)/ :
|
|
132
|
+
browser == "edge" ? /(edge|Edge)/ :
|
|
133
|
+
browser;
|
|
134
|
+
expect(binary).toEqual(expect.stringMatching(browserName));
|
|
135
|
+
|
|
136
|
+
let installedVersion =
|
|
137
|
+
await BROWSERS[browser].getInstalledVersion(binary);
|
|
138
|
+
expect(installedVersion).toEqual(
|
|
139
|
+
expect.stringContaining(normalize(versionNumber)));
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("runs", async() => {
|
|
143
|
+
let names = {
|
|
144
|
+
chromium: "chrome",
|
|
145
|
+
firefox: "firefox",
|
|
146
|
+
edge: /(MicrosoftEdge|msedge)/,
|
|
147
|
+
opera: /(opera|chrome)/
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
driver = await BROWSERS[browser].getDriver(version);
|
|
151
|
+
await driver.navigate().to(TEST_URL);
|
|
152
|
+
|
|
153
|
+
expect((await driver.getCapabilities()).getBrowserName())
|
|
154
|
+
.toEqual(expect.stringMatching(names[browser]));
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("supports extra args", async() => {
|
|
158
|
+
let headless = false;
|
|
159
|
+
let extraArgs = browser == "firefox" ?
|
|
160
|
+
["--devtools"] : ["auto-open-devtools-for-tabs"];
|
|
161
|
+
|
|
162
|
+
driver = await BROWSERS[browser].getDriver(
|
|
163
|
+
version, {headless, extraArgs});
|
|
164
|
+
await driver.navigate().to(TEST_URL);
|
|
165
|
+
let sizeDevToolsOpen = await getWindowSize(driver);
|
|
166
|
+
await quitDriver();
|
|
167
|
+
|
|
168
|
+
driver = await BROWSERS[browser].getDriver(version, {headless});
|
|
169
|
+
await driver.navigate().to(TEST_URL);
|
|
170
|
+
let sizeDevToolsClosed = await getWindowSize(driver);
|
|
171
|
+
|
|
172
|
+
expect(sizeDevToolsOpen).toMeasureLessThan(sizeDevToolsClosed);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it("loads an extension", async() => {
|
|
176
|
+
let headless = browser == "firefox";
|
|
177
|
+
|
|
178
|
+
driver = await BROWSERS[browser].getDriver(
|
|
179
|
+
version, {headless, extensionPaths});
|
|
180
|
+
await getHandle(driver, "/index.html");
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("loads an extension in incognito mode", async function() {
|
|
184
|
+
if (browser == "firefox" && version == "60.0")
|
|
185
|
+
this.skip();
|
|
186
|
+
|
|
187
|
+
driver = await BROWSERS[browser].getDriver(
|
|
188
|
+
version, {headless: false, extensionPaths, incognito: true});
|
|
189
|
+
await BROWSERS[browser].enableExtensionInIncognito(
|
|
190
|
+
driver, "Browser download test extension"
|
|
191
|
+
);
|
|
192
|
+
await getHandle(driver, "/index.html");
|
|
193
|
+
});
|
|
128
194
|
});
|
|
195
|
+
}
|
|
129
196
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
197
|
+
it("does not download unsupported versions", async function() {
|
|
198
|
+
if (browser == "edge" && process.platform == "win32")
|
|
199
|
+
this.skip();
|
|
133
200
|
|
|
134
|
-
|
|
135
|
-
this.timeout(30000);
|
|
201
|
+
const UNSUPPORTED = "0.0";
|
|
136
202
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
await BROWSERS[browser].enableExtensionInIncognito(
|
|
140
|
-
driver, "Browser download test extension"
|
|
141
|
-
);
|
|
142
|
-
await getHandle(driver, "/index.html");
|
|
143
|
-
});
|
|
203
|
+
await expect(BROWSERS[browser].downloadBinary(UNSUPPORTED))
|
|
204
|
+
.rejects.toThrow(`Unsupported browser version: ${UNSUPPORTED}`);
|
|
144
205
|
});
|
|
145
|
-
}
|
|
206
|
+
});
|
|
146
207
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
FROM registry.gitlab.com/eyeo/docker/get-browser-binary:node16
|
|
2
|
+
|
|
3
|
+
COPY package*.json get-browser-binary/
|
|
4
|
+
RUN cd get-browser-binary && npm install
|
|
5
|
+
|
|
6
|
+
COPY . get-browser-binary/
|
|
7
|
+
|
|
8
|
+
ENV TEST_ARGS="--grep Browser"
|
|
9
|
+
ENTRYPOINT get-browser-binary/test/docker/entrypoint.sh
|