@eyeo/get-browser-binary 0.19.0 → 0.20.1

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/.mocharc.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "timeout": 80000
2
+ "timeout": 90000
3
3
  }
package/RELEASE_NOTES.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Unreleased
2
2
 
3
+ # 0.20.1
4
+
5
+ - test: Fixes enabling developer mode (!131)
6
+
7
+ # 0.20.0
8
+
9
+ - Enable developer mode for incognito tests (!126)
10
+ - Adds support to beta and dev channels for Edge in macOS (!127)
11
+ - Enable developer mode for latest versions of chromium browsers (!128)
12
+
3
13
  # 0.19.0
4
14
 
5
15
  - Fixes an issue starting with Firefox version 135 which prevented the binary to be downloaded (#82)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eyeo/get-browser-binary",
3
- "version": "0.19.0",
3
+ "version": "0.20.1",
4
4
  "description": "Install browser binaries and matching webdrivers",
5
5
  "repository": {
6
6
  "type": "git",
package/src/browser.js CHANGED
@@ -125,7 +125,6 @@ export class Browser {
125
125
  * enables the extension when loaded in incognito.
126
126
  * @param {webdriver} driver The driver controlling the browser.
127
127
  * @param {string} extensionTitle Title of the extension to be enabled.
128
- * @return {webdriver}
129
128
  * @throws {Error} Unsupported browser version, Extension not found, HTML
130
129
  * element not found.
131
130
  */
package/src/chromium.js CHANGED
@@ -19,7 +19,7 @@ import path from "path";
19
19
  import fs from "fs";
20
20
 
21
21
  import got from "got";
22
- import webdriver from "selenium-webdriver";
22
+ import {Builder} from "selenium-webdriver";
23
23
  import chrome from "selenium-webdriver/chrome.js";
24
24
  import extractZip from "extract-zip";
25
25
 
@@ -27,6 +27,25 @@ import {Browser} from "./browser.js";
27
27
  import {download, getMajorVersion, checkVersion, checkPlatform, errMsg,
28
28
  snapshotsBaseDir, platformArch, checkExtensionPaths} from "./utils.js";
29
29
 
30
+ async function enableDeveloperMode(driver) {
31
+ const currentHandle = await driver.getWindowHandle();
32
+
33
+ await driver.switchTo().newWindow("window");
34
+ await driver.navigate().to("chrome://extensions");
35
+ await driver.executeScript(() => {
36
+ const devModeToggle = document
37
+ .querySelector("extensions-manager").shadowRoot
38
+ .getElementById("toolbar").shadowRoot
39
+ .querySelector("#toolbar #devMode");
40
+
41
+ if (!devModeToggle.checked)
42
+ devModeToggle.click();
43
+ });
44
+
45
+ await driver.close();
46
+ await driver.switchTo().window(currentHandle);
47
+ }
48
+
30
49
  /**
31
50
  * Browser and webdriver functionality for Chromium.
32
51
  * @hideconstructor
@@ -211,8 +230,8 @@ export class Chromium extends Browser {
211
230
  await checkExtensionPaths(extensionPaths);
212
231
  options.addArguments(`load-extension=${extensionPaths.join(",")}`);
213
232
  }
233
+ let majorVersion = getMajorVersion(versionNumber);
214
234
  if (headless) {
215
- let majorVersion = getMajorVersion(versionNumber);
216
235
  // https://www.selenium.dev/blog/2023/headless-is-going-away/
217
236
  if (majorVersion >= 109)
218
237
  options.addArguments("headless=new");
@@ -227,11 +246,18 @@ export class Chromium extends Browser {
227
246
  options.addArguments("incognito");
228
247
  options.setChromeBinaryPath(binary);
229
248
 
230
- let builder = new webdriver.Builder();
249
+ let builder = new Builder();
231
250
  builder.forBrowser("chrome");
232
251
  builder.setChromeOptions(options);
233
252
 
234
- return builder.build();
253
+ const driver = builder.build();
254
+
255
+ // From Chromium 134 on, developer mode needs to be enabled
256
+ // for custom extensions to work properly
257
+ if (majorVersion >= 134)
258
+ await enableDeveloperMode(driver);
259
+
260
+ return driver;
235
261
  }
236
262
 
237
263
  /** @see Browser.enableExtensionInIncognito */
package/src/edge.js CHANGED
@@ -21,7 +21,7 @@ import {promisify} from "util";
21
21
  import fs from "fs";
22
22
 
23
23
  import got from "got";
24
- import webdriver from "selenium-webdriver";
24
+ import {until, By, Builder} from "selenium-webdriver";
25
25
  import edge from "selenium-webdriver/edge.js";
26
26
 
27
27
  import {Browser} from "./browser.js";
@@ -29,9 +29,23 @@ import {download, killDriverProcess, wait, getMajorVersion, checkVersion,
29
29
  checkPlatform, errMsg, snapshotsBaseDir, checkExtensionPaths}
30
30
  from "./utils.js";
31
31
 
32
- let {By} = webdriver;
33
32
  let {platform} = process;
34
33
 
34
+ async function enableDeveloperMode(driver) {
35
+ const currentHandle = await driver.getWindowHandle();
36
+ await driver.switchTo().newWindow("window");
37
+ await driver.navigate().to("edge://extensions/");
38
+
39
+ await driver.executeScript(() => {
40
+ const devModeToggle = document.getElementById("developer-mode");
41
+ if (!devModeToggle.checked)
42
+ devModeToggle.click();
43
+ });
44
+
45
+ await driver.close();
46
+ await driver.switchTo().window(currentHandle);
47
+ }
48
+
35
49
  /**
36
50
  * Browser and webdriver functionality for Edge.
37
51
  * @hideconstructor
@@ -83,19 +97,24 @@ export class Edge extends Browser {
83
97
  return {versionNumber, channel};
84
98
  }
85
99
 
86
- static #darwinApp = "Microsoft Edge";
100
+ static #getDarwinApp(channel = "stable") {
101
+ const firstUppercase =
102
+ String(channel).charAt(0).toUpperCase() + String(channel).slice(1);
103
+ return channel === "stable" ? "Microsoft Edge" : `Microsoft Edge ${firstUppercase}`;
104
+ }
87
105
 
88
106
  static #getBinaryPath(channel = "stable") {
89
107
  switch (platform) {
90
108
  case "win32":
91
- let programFiles = process.env["ProgramFiles(x86)"] ?
109
+ const programFiles = process.env["ProgramFiles(x86)"] ?
92
110
  "${Env:ProgramFiles(x86)}" : "${Env:ProgramFiles}";
93
111
  return `${programFiles}\\Microsoft\\Edge\\Application\\msedge.exe`;
94
112
  case "linux":
95
113
  return channel == "stable" ?
96
114
  "/usr/bin/microsoft-edge" : `/usr/bin/microsoft-edge-${channel}`;
97
115
  case "darwin":
98
- return `${process.env.HOME}/Applications/${Edge.#darwinApp}.app/Contents/MacOS/${Edge.#darwinApp}`;
116
+ const darwinApp = Edge.#getDarwinApp(channel);
117
+ return `${process.env.HOME}/Applications/${darwinApp}.app/Contents/MacOS/${darwinApp}`;
99
118
  default:
100
119
  checkPlatform();
101
120
  }
@@ -119,9 +138,8 @@ export class Edge extends Browser {
119
138
  // https://support.microsoft.com/en-us/microsoft-edge/why-can-t-i-uninstall-microsoft-edge-ee150b3b-7d7a-9984-6d83-eb36683d526d
120
139
  throw new Error(`${errMsg.unsupportedPlatform}: ${platform}`);
121
140
 
122
- if (platform == "darwin" && version != "latest")
123
- // Only latest Edge is supported on macOS
124
- throw new Error(`${errMsg.unsupportedVersion}: ${version}. Only "latest" is supported`);
141
+ if (platform == "darwin" && !/latest|beta|dev/.test(version))
142
+ throw new Error(`${errMsg.unsupportedVersion}: ${version}. Only "latest", "beta" or "dev" are supported`);
125
143
 
126
144
  checkVersion(version, Edge.#MIN_VERSION, Edge.#CHANNELS);
127
145
  let {versionNumber, channel} = await Edge.#getVersionForChannel(version);
@@ -143,16 +161,14 @@ export class Edge extends Browser {
143
161
  let url = `https://packages.microsoft.com/repos/edge/pool/main/m/microsoft-edge-${channel}/${filename}`;
144
162
  try {
145
163
  if (platform == "darwin") {
146
- let caskUrl = "https://formulae.brew.sh/api/cask/microsoft-edge.json";
147
- let caskJson;
164
+ const caskFile = channel === "stable" ? "microsoft-edge.json" : `microsoft-edge@${channel}.json`;
165
+ const caskUrl = `https://formulae.brew.sh/api/cask/${caskFile}`;
148
166
  try {
149
- caskJson = await got(caskUrl).json();
167
+ ({url} = await got(caskUrl).json());
150
168
  }
151
169
  catch (err) {
152
170
  throw new Error(`${errMsg.browserVersionCheck}: ${caskUrl}\n${err}`);
153
171
  }
154
- ({url} = process.arch == "arm64" ?
155
- caskJson.variations.arm64_ventura : caskJson);
156
172
  }
157
173
  await download(url, archive, downloadTimeout);
158
174
  }
@@ -164,7 +180,7 @@ export class Edge extends Browser {
164
180
  await promisify(exec)(`dpkg -i ${archive}`);
165
181
  }
166
182
  else if (platform == "darwin") {
167
- await fs.promises.rm(`${process.env.HOME}/Applications/${Edge.#darwinApp}.app`, {force: true, recursive: true});
183
+ await fs.promises.rm(`${process.env.HOME}/Applications/${Edge.#getDarwinApp(channel)}.app`, {force: true, recursive: true});
168
184
  await promisify(exec)(`installer -pkg ${archive} -target CurrentUserHomeDirectory`);
169
185
  }
170
186
 
@@ -213,10 +229,10 @@ export class Edge extends Browser {
213
229
  options.addArguments("inprivate");
214
230
  if (insecure)
215
231
  options.addArguments("ignore-certificate-errors");
216
- if (platform == "linux")
232
+ if (platform === "linux" || platform === "darwin")
217
233
  options.setEdgeChromiumBinaryPath(binary);
218
234
 
219
- let builder = new webdriver.Builder();
235
+ let builder = new Builder();
220
236
  builder.forBrowser("MicrosoftEdge");
221
237
  builder.setEdgeOptions(options);
222
238
 
@@ -235,25 +251,46 @@ export class Edge extends Browser {
235
251
  }
236
252
  }, 30000, `${errMsg.driverStart}: msedgedriver`, 1000);
237
253
 
254
+ // From Edge 134 on, developer mode needs to be enabled
255
+ // for custom extensions to work properly
256
+ if (versionNumber >= 134)
257
+ await enableDeveloperMode(driver);
258
+
238
259
  return driver;
239
260
  }
240
261
 
241
262
  /** @see Browser.enableExtensionInIncognito */
242
263
  static async enableExtensionInIncognito(driver, extensionTitle) {
243
264
  await driver.navigate().to("edge://extensions/");
265
+
244
266
  for (let elem of await driver.findElements(By.css("[role=listitem]"))) {
245
267
  let text = await elem.getAttribute("innerHTML");
246
268
  if (!text.includes(extensionTitle))
247
269
  continue;
248
270
 
249
271
  for (let button of await elem.findElements(By.css("button"))) {
250
- text = await elem.getAttribute("innerHTML");
272
+ text = await button.getAttribute("outerHTML");
251
273
  if (!text.includes("Details"))
252
274
  continue;
253
275
 
254
276
  await button.click();
255
- return await driver.findElement(By.id("itemAllowIncognito")).click();
277
+ await driver.findElement(By.id("itemAllowIncognito")).click();
278
+
279
+ // On Edge 134, extension gets turned off when incognito mode is enabled
280
+ // We need to turn it back on by clicking the toggle
281
+ try {
282
+ await driver.wait(until.elementLocated(
283
+ By.css('[aria-label="Extension on"]:not(:checked)')), 3000).click();
284
+ }
285
+ catch (err) {
286
+ // ignoring timeout errors, as the element is not expected
287
+ // to be present for all Edge versions
288
+ if (err.name !== "TimeoutError")
289
+ throw err;
290
+ }
291
+ return;
256
292
  }
293
+
257
294
  throw new Error(`${errMsg.elemNotFound}: Details button`);
258
295
  }
259
296
  throw new Error(`${errMsg.extensionNotFound}: ${extensionTitle}`);
package/src/firefox.js CHANGED
@@ -21,7 +21,7 @@ import {promisify} from "util";
21
21
  import fs from "fs";
22
22
 
23
23
  import got from "got";
24
- import webdriver from "selenium-webdriver";
24
+ import {until, By, Builder} from "selenium-webdriver";
25
25
  import firefox from "selenium-webdriver/firefox.js";
26
26
  import {Command} from "selenium-webdriver/lib/command.js";
27
27
 
@@ -30,8 +30,6 @@ import {download, extractTar, extractDmg, killDriverProcess, wait,
30
30
  getMajorVersion, checkVersion, checkPlatform, errMsg, snapshotsBaseDir,
31
31
  platformArch, checkExtensionPaths} from "./utils.js";
32
32
 
33
- let {until, By} = webdriver;
34
-
35
33
  /**
36
34
  * Browser and webdriver functionality for Firefox.
37
35
  * @hideconstructor
@@ -221,7 +219,7 @@ export class Firefox extends Browser {
221
219
  // https://github.com/mozilla/geckodriver/issues/1560
222
220
  await wait(async() => {
223
221
  try {
224
- driver = await new webdriver.Builder()
222
+ driver = await new Builder()
225
223
  .forBrowser("firefox")
226
224
  .setFirefoxOptions(options)
227
225
  .build();
package/test/browsers.js CHANGED
@@ -224,6 +224,11 @@ for (let browser of Object.keys(BROWSERS)) {
224
224
 
225
225
  it("runs", async function() {
226
226
  driver = await BROWSERS[browser].getDriver(version);
227
+ const url = await driver.getCurrentUrl();
228
+ // check that default automation tab is in focus:
229
+ // data;, (chromium) and about:blank (firefox)
230
+ expect(url).toEqual(expect.stringMatching(/^(data:,|about:blank)$/));
231
+
227
232
  await basicUrlTest(driver, browser);
228
233
 
229
234
  let browserVersion =