@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/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)(["tar", "-jxf", archive, "-C", dir].join(" "));
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
+ }
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "env": {
3
- "mocha": true
3
+ "mocha": true,
4
+ "browser": true
4
5
  }
5
6
  }
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 "msedgedriver";
27
+ import "geckodriver";
28
28
 
29
29
  const VERSIONS = {
30
- chromium: [void 0, "beta", "dev", "77.0.3865.0"],
31
- firefox: [void 0, "beta", "68.0"],
32
- edge: [void 0]
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
- for (let browser of Object.keys(BROWSERS)) {
66
- for (let version of VERSIONS[browser]) {
67
- describe(`Browser: ${browser} ${version || "latest"}`, function() {
68
- this.timeout(20000);
69
-
70
- before(async() => {
71
- try {
72
- await fs.promises.rm(snapshotsBaseDir, {recursive: true});
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
- driver = await BROWSERS[browser].getDriver(version);
110
- await driver.navigate().to("about:blank");
76
+ function getWindowSize(driver) {
77
+ return driver.executeScript(() => {
78
+ return {height: window.innerHeight, width: window.innerWidth};
79
+ });
80
+ }
111
81
 
112
- expect((await driver.getCapabilities()).getBrowserName())
113
- .toEqual(expect.stringMatching(names[browser]));
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
- it("supports extra args", async() => {
117
- driver = await BROWSERS[browser].getDriver(
118
- version, {extraArgs: ["auto-open-devtools-for-tabs"]});
119
- await driver.navigate().to("about:blank");
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
- it("loads an extension", async() => {
123
- let headless = browser == "firefox";
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
- driver = await BROWSERS[browser].getDriver(
126
- version, {headless, extensionPaths});
127
- await getHandle(driver, "/index.html");
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
- it("loads an extension in incognito mode", async function() {
131
- if (browser == "firefox" && version == "68.0")
132
- this.skip();
197
+ it("does not download unsupported versions", async function() {
198
+ if (browser == "edge" && process.platform == "win32")
199
+ this.skip();
133
200
 
134
- if (process.platform == "win32")
135
- this.timeout(30000);
201
+ const UNSUPPORTED = "0.0";
136
202
 
137
- driver = await BROWSERS[browser].getDriver(
138
- version, {headless: false, extensionPaths, incognito: true});
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
@@ -0,0 +1,4 @@
1
+ #! /bin/bash
2
+
3
+ cd get-browser-binary
4
+ xvfb-run -a npm test -- $TEST_ARGS