Skip to content
This repository was archived by the owner on Sep 1, 2024. It is now read-only.

Commit 56acafc

Browse files
committed
[cypress] Work around SIGSEGV in Chrome 117 w/ headless mode
The latest Chrome 117 release (now rolled out to GitHub Actions runners) broke interoperability with Cypress <= 12.14 in headless mode. See cypress-io/cypress#27804. This change implements the workaround in cypress-io/cypress#27804 (comment), which replaces `--headless` with `--headless=new`. See also the underlying Chrome bug here: https://bugs.chromium.org/p/chromium/issues/detail?id=1483163
1 parent ced36a8 commit 56acafc

File tree

14 files changed

+183
-1
lines changed

14 files changed

+183
-1
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (c) 2023 Developer Innovations, LLC
2+
3+
/**
4+
* Workaround for https://github.com/cypress-io/cypress/issues/27804.
5+
*
6+
* @param {Cypress.PluginEvents} on
7+
* @returns void
8+
*/
9+
export const fixHeadlessChrome = (on) => {
10+
on(
11+
"before:browser:launch",
12+
/**
13+
* @param {Cypress.Browser} browser,
14+
* @param {Cypress.BrowserLaunchOptions} launchOptions
15+
* @returns {void | Cypress.BrowserLaunchOptions}
16+
*/
17+
(browser, launchOptions) => {
18+
if (
19+
browser.family === "chromium" &&
20+
browser.name !== "electron" &&
21+
browser.isHeadless
22+
) {
23+
launchOptions.args = launchOptions.args.map((arg) =>
24+
arg === "--headless" ? "--headless=new" : arg
25+
);
26+
}
27+
28+
return launchOptions;
29+
}
30+
);
31+
};
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) 2023 Developer Innovations, LLC
2+
3+
// Workaround for https://github.com/cypress-io/cypress/issues/27804.
4+
export const fixHeadlessChrome = (on: Cypress.PluginEvents): void => {
5+
on(
6+
"before:browser:launch",
7+
(
8+
browser: Cypress.Browser,
9+
launchOptions: Cypress.BrowserLaunchOptions
10+
): void | Cypress.BrowserLaunchOptions => {
11+
if (
12+
browser.family === "chromium" &&
13+
browser.name !== "electron" &&
14+
browser.isHeadless
15+
) {
16+
launchOptions.args = launchOptions.args.map((arg) =>
17+
arg === "--headless" ? "--headless=new" : arg
18+
);
19+
}
20+
21+
return launchOptions;
22+
}
23+
);
24+
};

packages/cypress-plugin/test/integration-input-esm/cypress-config.cjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ module.exports = {
1717
* @returns {Promise<Cypress.PluginConfigOptions | void> | Cypress.PluginConfigOptions | void}
1818
*/
1919
async setupNodeEvents(on, _config) {
20+
const { fixHeadlessChrome } = await import("./config-js/headless.js");
21+
22+
fixHeadlessChrome(on);
2023
registerCosmiconfigMock();
2124
registerSimpleGitMock();
2225

@@ -38,6 +41,9 @@ module.exports = {
3841
* @returns {Promise<Cypress.PluginConfigOptions | void> | Cypress.PluginConfigOptions | void}
3942
*/
4043
async setupNodeEvents(on, _config) {
44+
const { fixHeadlessChrome } = await import("./config-js/headless.js");
45+
46+
fixHeadlessChrome(on);
4147
registerCosmiconfigMock();
4248
registerSimpleGitMock();
4349

packages/cypress-plugin/test/integration-input-esm/cypress-config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { registerTasks } from "./config-js/tasks.js";
55
import webpackConfig from "./config-js/webpack.js";
66
import { registerSimpleGitMock } from "unflakable-test-common/dist/git.js";
77
import { registerCosmiconfigMock } from "unflakable-test-common/dist/config.js";
8+
import { fixHeadlessChrome } from "./config-js/headless.js";
89

910
/**
1011
* @type {Cypress.ConfigOptions}
@@ -17,6 +18,7 @@ export default {
1718
* @returns {Promise<Cypress.PluginConfigOptions | void> | Cypress.PluginConfigOptions | void}
1819
*/
1920
setupNodeEvents(on, _config) {
21+
fixHeadlessChrome(on);
2022
registerCosmiconfigMock();
2123
registerSimpleGitMock();
2224
registerTasks(on);
@@ -35,6 +37,7 @@ export default {
3537
* @returns {Promise<Cypress.PluginConfigOptions | void> | Cypress.PluginConfigOptions | void}
3638
*/
3739
setupNodeEvents(on, _config) {
40+
fixHeadlessChrome(on);
3841
registerCosmiconfigMock();
3942
registerSimpleGitMock();
4043
registerTasks(on);

packages/cypress-plugin/test/integration-input-esm/cypress.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import { registerTasks } from "./config/tasks.js";
88
import webpackConfig from "./config/webpack.js";
99
import { registerSimpleGitMock } from "unflakable-test-common/dist/git.js";
1010
import { registerCosmiconfigMock } from "unflakable-test-common/dist/config.js";
11+
import { fixHeadlessChrome } from "./config/headless.js";
1112

1213
export default defineConfig({
1314
component: {
1415
setupNodeEvents(on: Cypress.PluginEvents, _config) {
16+
fixHeadlessChrome(on);
1517
registerCosmiconfigMock();
1618
registerSimpleGitMock();
1719
registerTasks(on);
@@ -31,6 +33,7 @@ export default defineConfig({
3133
| Promise<Cypress.PluginConfigOptions | void>
3234
| Cypress.PluginConfigOptions
3335
| void {
36+
fixHeadlessChrome(on);
3437
registerCosmiconfigMock();
3538
registerSimpleGitMock();
3639
registerTasks(on);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright (c) 2023 Developer Innovations, LLC
2+
3+
module.exports = {
4+
/**
5+
* Workaround for https://github.com/cypress-io/cypress/issues/27804.
6+
*
7+
* @param {Cypress.PluginEvents} on
8+
* @returns void
9+
*/
10+
fixHeadlessChrome: (on) => {
11+
on(
12+
"before:browser:launch",
13+
/**
14+
* @param {Cypress.Browser} browser,
15+
* @param {Cypress.BrowserLaunchOptions} launchOptions
16+
* @returns {void | Cypress.BrowserLaunchOptions}
17+
*/
18+
(browser, launchOptions) => {
19+
if (
20+
browser.family === "chromium" &&
21+
browser.name !== "electron" &&
22+
browser.isHeadless
23+
) {
24+
launchOptions.args = launchOptions.args.map((arg) =>
25+
arg === "--headless" ? "--headless=new" : arg
26+
);
27+
}
28+
29+
return launchOptions;
30+
}
31+
);
32+
},
33+
};

packages/cypress-plugin/test/integration-input-manual/cypress-config.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { registerCosmiconfigMock } from "unflakable-test-common/dist/config.js";
88
import { registerUnflakable } from "@unflakable/cypress-plugin";
99
import semverGte from "semver/functions/gte.js";
1010
import path from "path";
11+
import headless from "./config/headless.js";
1112
import cypressOnFix from "cypress-on-fix";
1213

1314
/**
@@ -22,6 +23,7 @@ export default {
2223
*/
2324
setupNodeEvents(baseOn, config) {
2425
const on = cypressOnFix(baseOn);
26+
headless.fixHeadlessChrome(on);
2527
registerCosmiconfigMock();
2628
registerSimpleGitMock();
2729
tasks.registerTasks(on);
@@ -43,6 +45,7 @@ export default {
4345
*/
4446
setupNodeEvents(baseOn, config) {
4547
const on = cypressOnFix(baseOn);
48+
headless.fixHeadlessChrome(on);
4649
registerCosmiconfigMock();
4750
registerSimpleGitMock();
4851
tasks.registerTasks(on);

packages/cypress-plugin/test/integration-input-manual/cypress.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const semverGte = require("semver/functions/gte");
1111

1212
const { registerUnflakable } = require("@unflakable/cypress-plugin");
1313
const path = require("path");
14+
const { fixHeadlessChrome } = require("./config/headless");
1415
const cypressOnFix = require("cypress-on-fix");
1516

1617
module.exports = {
@@ -25,6 +26,7 @@ module.exports = {
2526
*/
2627
setupNodeEvents(baseOn, config) {
2728
const on = cypressOnFix(baseOn);
29+
fixHeadlessChrome(on);
2830
registerCosmiconfigMock();
2931
registerSimpleGitMock();
3032
registerTasks(on);
@@ -46,6 +48,7 @@ module.exports = {
4648
*/
4749
setupNodeEvents(baseOn, config) {
4850
const on = cypressOnFix(baseOn);
51+
fixHeadlessChrome(on);
4952
registerCosmiconfigMock();
5053
registerSimpleGitMock();
5154
registerTasks(on);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright (c) 2023 Developer Innovations, LLC
2+
3+
module.exports = {
4+
/**
5+
* Workaround for https://github.com/cypress-io/cypress/issues/27804.
6+
*
7+
* @param {Cypress.PluginEvents} on
8+
* @returns void
9+
*/
10+
fixHeadlessChrome: (on) => {
11+
on(
12+
"before:browser:launch",
13+
/**
14+
* @param {Cypress.Browser} browser,
15+
* @param {Cypress.BrowserLaunchOptions} launchOptions
16+
* @returns {void | Cypress.BrowserLaunchOptions}
17+
*/
18+
(browser, launchOptions) => {
19+
if (
20+
browser.family === "chromium" &&
21+
browser.name !== "electron" &&
22+
browser.isHeadless
23+
) {
24+
launchOptions.args = launchOptions.args.map((arg) =>
25+
arg === "--headless" ? "--headless=new" : arg
26+
);
27+
}
28+
29+
return launchOptions;
30+
}
31+
);
32+
},
33+
};
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) 2023 Developer Innovations, LLC
2+
3+
// Workaround for https://github.com/cypress-io/cypress/issues/27804.
4+
export const fixHeadlessChrome = (on: Cypress.PluginEvents): void => {
5+
on(
6+
"before:browser:launch",
7+
(
8+
browser: Cypress.Browser,
9+
launchOptions: Cypress.BrowserLaunchOptions
10+
): void | Cypress.BrowserLaunchOptions => {
11+
if (
12+
browser.family === "chromium" &&
13+
browser.name !== "electron" &&
14+
browser.isHeadless
15+
) {
16+
launchOptions.args = launchOptions.args.map((arg) =>
17+
arg === "--headless" ? "--headless=new" : arg
18+
);
19+
}
20+
21+
return launchOptions;
22+
}
23+
);
24+
};

0 commit comments

Comments
 (0)