From 382e0b525da203b9ade7e985b03a5ee8800e3565 Mon Sep 17 00:00:00 2001 From: Matt Henkes Date: Fri, 21 Oct 2022 15:10:26 -0500 Subject: [PATCH] fix: detect chrome browser process and tab crashes to no longer hang in CI (#24338) * Handle chrome tab and browser crashes. * handle process crashes and add system tests * handle crashing on windows * updating comment * update unit tests * Update packages/server/lib/browsers/index.ts Co-authored-by: Emily Rohrbough * Apply suggestions from code review Co-authored-by: Ryan Manuel * fix flaky system test probably Co-authored-by: Emily Rohrbough Co-authored-by: Ryan Manuel --- .../__snapshot-html__/BROWSER_CRASHED.html | 48 +++ .../__snapshot-html__/RENDERER_CRASHED.html | 3 +- packages/errors/src/errors.ts | 15 +- .../test/unit/visualSnapshotErrors_spec.ts | 5 + packages/server/lib/browsers/chrome.ts | 30 +- packages/server/lib/browsers/electron.ts | 12 +- packages/server/lib/browsers/firefox.ts | 18 +- packages/server/lib/browsers/index.ts | 26 +- packages/server/lib/browsers/types.ts | 4 + packages/server/lib/browsers/webkit.ts | 9 +- packages/server/lib/open_project.ts | 2 + packages/server/lib/project-base.ts | 4 +- packages/types/src/server.ts | 1 + .../browser_crash_handling_spec.js | 331 ++++++++++++++++++ .../cypress/e2e/chrome_process_crash.cy.js | 4 + .../e2e/cypress/e2e/chrome_tab_crash.cy.js | 4 + .../e2e/cypress/e2e/web_security.cy.js | 2 +- .../test/browser_crash_handling_spec.js | 49 +++ 18 files changed, 546 insertions(+), 21 deletions(-) create mode 100644 packages/errors/__snapshot-html__/BROWSER_CRASHED.html create mode 100644 system-tests/__snapshots__/browser_crash_handling_spec.js create mode 100644 system-tests/projects/e2e/cypress/e2e/chrome_process_crash.cy.js create mode 100644 system-tests/projects/e2e/cypress/e2e/chrome_tab_crash.cy.js create mode 100644 system-tests/test/browser_crash_handling_spec.js diff --git a/packages/errors/__snapshot-html__/BROWSER_CRASHED.html b/packages/errors/__snapshot-html__/BROWSER_CRASHED.html new file mode 100644 index 000000000000..da8c4e4d4ebe --- /dev/null +++ b/packages/errors/__snapshot-html__/BROWSER_CRASHED.html @@ -0,0 +1,48 @@ + + + + + + + + + + + +
We detected that the Chrome process just crashed with code 'code' and signal 'signal'.
+
+We have failed the current test and have relaunched Chrome.
+
+This can happen for many different reasons:
+
+- You wrote an endless loop and you must fix your own code
+- You are running lots of tests on a memory intense application
+- You are running in a memory starved VM environment
+- There are problems with your GPU / GPU drivers
+- There are browser bugs
+
\ No newline at end of file diff --git a/packages/errors/__snapshot-html__/RENDERER_CRASHED.html b/packages/errors/__snapshot-html__/RENDERER_CRASHED.html index e3912fc901d3..1a587a4d9a9f 100644 --- a/packages/errors/__snapshot-html__/RENDERER_CRASHED.html +++ b/packages/errors/__snapshot-html__/RENDERER_CRASHED.html @@ -41,7 +41,6 @@ This can happen for a number of different reasons: - You wrote an endless loop and you must fix your own code -- There is a memory leak in Cypress (unlikely but possible) - You are running Docker (there is an easy fix for this: see link below) - You are running lots of tests on a memory intense application - You are running in a memory starved VM environment @@ -50,5 +49,5 @@ You can learn more including how to fix Docker here: -https://on.cypress.io/renderer-process-crashed +https://on.cypress.io/renderer-process-crashed \ No newline at end of file diff --git a/packages/errors/src/errors.ts b/packages/errors/src/errors.ts index 096043e12a2a..173099df05c9 100644 --- a/packages/errors/src/errors.ts +++ b/packages/errors/src/errors.ts @@ -570,7 +570,6 @@ export const AllCypressErrors = { This can happen for a number of different reasons: - You wrote an endless loop and you must fix your own code - - There is a memory leak in Cypress (unlikely but possible) - You are running Docker (there is an easy fix for this: see link below) - You are running lots of tests on a memory intense application - You are running in a memory starved VM environment @@ -581,6 +580,20 @@ export const AllCypressErrors = { https://on.cypress.io/renderer-process-crashed` }, + BROWSER_CRASHED: (browser: string, code: string | number, signal: string) => { + return errTemplate`\ + We detected that the ${fmt.highlight(browser)} process just crashed with code '${fmt.highlight(code)}' and signal '${fmt.highlight(signal)}'. + + We have failed the current test and have relaunched ${fmt.highlight(browser)}. + + This can happen for many different reasons: + + - You wrote an endless loop and you must fix your own code + - You are running lots of tests on a memory intense application + - You are running in a memory starved VM environment + - There are problems with your GPU / GPU drivers + - There are browser bugs` + }, AUTOMATION_SERVER_DISCONNECTED: () => { return errTemplate`The automation client disconnected. Cannot continue running tests.` }, diff --git a/packages/errors/test/unit/visualSnapshotErrors_spec.ts b/packages/errors/test/unit/visualSnapshotErrors_spec.ts index bf5e141f06e1..42bb52ddd61f 100644 --- a/packages/errors/test/unit/visualSnapshotErrors_spec.ts +++ b/packages/errors/test/unit/visualSnapshotErrors_spec.ts @@ -646,6 +646,11 @@ describe('visual error templates', () => { default: [], } }, + BROWSER_CRASHED: () => { + return { + default: ['Chrome', 'code', 'signal'], + } + }, AUTOMATION_SERVER_DISCONNECTED: () => { return { default: [], diff --git a/packages/server/lib/browsers/chrome.ts b/packages/server/lib/browsers/chrome.ts index e3308b88aa0e..b8c5cf2a04cd 100644 --- a/packages/server/lib/browsers/chrome.ts +++ b/packages/server/lib/browsers/chrome.ts @@ -15,6 +15,7 @@ import { fs } from '../util/fs' import { CdpAutomation, screencastOpts } from './cdp_automation' import * as protocol from './protocol' import utils from './utils' +import * as errors from '../errors' import type { Browser, BrowserInstance } from './types' import { BrowserCriClient } from './browser-cri-client' import type { CriClient } from './cri-client' @@ -561,6 +562,17 @@ export = { return args }, + /** + * Clear instance state for the chrome instance, this is normally called in on kill or on exit. + */ + clearInstanceState () { + debug('closing remote interface client') + + // Do nothing on failure here since we're shutting down anyway + browserCriClient?.close().catch() + browserCriClient = undefined + }, + async connectToNewSpec (browser: Browser, options: BrowserNewTabOpts, automation: Automation) { debug('connecting to new chrome tab in existing instance with url and debugging port', { url: options.url }) @@ -595,6 +607,18 @@ export = { async attachListeners (url: string, pageCriClient: CriClient, automation: Automation, options: BrowserLaunchOpts | BrowserNewTabOpts) { const browserCriClient = this._getBrowserCriClient() + // Handle chrome tab crashes. + pageCriClient.on('Inspector.targetCrashed', () => { + const err = errors.get('RENDERER_CRASHED') + + if (!options.onError) { + errors.log(err) + throw new Error('Missing onError in attachListeners') + } + + options.onError(err) + }) + if (!browserCriClient) throw new Error('Missing browserCriClient in attachListeners') debug('attaching listeners to chrome %o', { url, options }) @@ -700,11 +724,7 @@ export = { launchedBrowser.browserCriClient = browserCriClient launchedBrowser.kill = (...args) => { - debug('closing remote interface client') - - // Do nothing on failure here since we're shutting down anyway - browserCriClient?.close().catch() - browserCriClient = undefined + this.clearInstanceState() debug('closing chrome') diff --git a/packages/server/lib/browsers/electron.ts b/packages/server/lib/browsers/electron.ts index 9d420d92c5da..73fd63dce9b5 100644 --- a/packages/server/lib/browsers/electron.ts +++ b/packages/server/lib/browsers/electron.ts @@ -146,9 +146,10 @@ export = { onCrashed () { const err = errors.get('RENDERER_CRASHED') - errors.log(err) - - if (!options.onError) throw new Error('Missing onError in onCrashed') + if (!options.onError) { + errors.log(err) + throw new Error('Missing onError in onCrashed') + } options.onError(err) }, @@ -471,6 +472,11 @@ export = { }) }, + /** + * Clear instance state for the electron instance, this is normally called in on kill or on exit for electron there isn't state to clear. + */ + clearInstanceState () {}, + async connectToNewSpec (browser: Browser, options: ElectronOpts, automation: Automation) { if (!options.url) throw new Error('Missing url in connectToNewSpec') diff --git a/packages/server/lib/browsers/firefox.ts b/packages/server/lib/browsers/firefox.ts index 6bbc42ef4088..0c844fcc1cd5 100644 --- a/packages/server/lib/browsers/firefox.ts +++ b/packages/server/lib/browsers/firefox.ts @@ -371,6 +371,17 @@ export function _createDetachedInstance (browserInstance: BrowserInstance, brows return detachedInstance } +/** +* Clear instance state for the chrome instance, this is normally called in on kill or on exit. +*/ +export function clearInstanceState () { + debug('closing remote interface client') + if (browserCriClient) { + browserCriClient.close().catch() + browserCriClient = undefined + } +} + export async function connectToNewSpec (browser: Browser, options: BrowserNewTabOpts, automation: Automation) { await firefoxUtil.connectToNewSpec(options, automation, browserCriClient) } @@ -552,13 +563,8 @@ export async function open (browser: Browser, url: string, options: BrowserLaunc const originalBrowserKill = browserInstance.kill browserInstance.kill = (...args) => { - debug('closing remote interface client') - // Do nothing on failure here since we're shutting down anyway - if (browserCriClient) { - browserCriClient.close().catch() - browserCriClient = undefined - } + clearInstanceState() debug('closing firefox') diff --git a/packages/server/lib/browsers/index.ts b/packages/server/lib/browsers/index.ts index 441dde6a8814..427a187a9c3a 100644 --- a/packages/server/lib/browsers/index.ts +++ b/packages/server/lib/browsers/index.ts @@ -2,6 +2,7 @@ import _ from 'lodash' import Bluebird from 'bluebird' import Debug from 'debug' import utils from './utils' +import * as errors from '../errors' import check from 'check-more-types' import { exec } from 'child_process' import util from 'util' @@ -155,13 +156,36 @@ export = { // TODO: normalizing opening and closing / exiting // so that there is a default for each browser but // enable the browser to configure the interface - instance.once('exit', () => { + instance.once('exit', async (code, signal) => { ctx.browser.setBrowserStatus('closed') // TODO: make this a required property if (!options.onBrowserClose) throw new Error('onBrowserClose did not exist in interactive mode') + const browserDisplayName = instance?.browser?.displayName || 'unknown' + options.onBrowserClose() + browserLauncher.clearInstanceState() instance = null + + // We are being very narrow on when to restart the browser here. The only case we can reliably test the 'SIGTRAP' signal. + // We want to avoid adding signals in here that may intentionally be caused by a user. + // For example exiting firefox through either force quitting or quitting via cypress will fire a 'SIGTERM' event which + // would result in constantly relaunching the browser when the user actively wants to quit. + // On windows the crash produces 2147483651 as an exit code. We should add to the list of crashes we handle as we see them. + // In the future we may consider delegating to the browsers to determine if an exit is a crash since it might be different + // depending on what browser has crashed. + if (code === null && ['SIGTRAP', 'SIGABRT'].includes(signal) || code === 2147483651 && signal === null) { + const err = errors.get('BROWSER_CRASHED', browserDisplayName, code, signal) + + if (!options.onError) { + errors.log(err) + throw new Error('Missing onError in attachListeners') + } + + await options.onError(err) + + await options.relaunchBrowser!() + } }) // TODO: instead of waiting an arbitrary diff --git a/packages/server/lib/browsers/types.ts b/packages/server/lib/browsers/types.ts index 08dafccf42a3..f8e2b99e2a03 100644 --- a/packages/server/lib/browsers/types.ts +++ b/packages/server/lib/browsers/types.ts @@ -35,4 +35,8 @@ export type BrowserLauncher = { * Used in Cypress-in-Cypress tests to connect to the existing browser instance. */ connectToExisting: (browser: Browser, options: BrowserLaunchOpts, automation: Automation) => void | Promise + /** + * Used to clear instance state after the browser has been exited. + */ + clearInstanceState: () => void } diff --git a/packages/server/lib/browsers/webkit.ts b/packages/server/lib/browsers/webkit.ts index a7b1a80da3a5..493cd6dc9b1d 100644 --- a/packages/server/lib/browsers/webkit.ts +++ b/packages/server/lib/browsers/webkit.ts @@ -25,6 +25,13 @@ export async function connectToNewSpec (browser: Browser, options: BrowserNewTab }) } +/** + * Clear instance state for the webkit instance, this is normally called in on kill or on exit. + */ +export function clearInstanceState () { + wkAutomation = undefined +} + export function connectToExisting () { throw new Error('Cypress-in-Cypress is not supported for WebKit.') } @@ -120,7 +127,7 @@ export async function open (browser: Browser, url: string, options: BrowserLaunc async kill () { debug('closing pwBrowser') await pwBrowser.close() - wkAutomation = undefined + clearInstanceState() } /** diff --git a/packages/server/lib/open_project.ts b/packages/server/lib/open_project.ts index b440a03a031f..f90790cb3093 100644 --- a/packages/server/lib/open_project.ts +++ b/packages/server/lib/open_project.ts @@ -186,6 +186,8 @@ export class OpenProject { return await browsers.connectToNewSpec(browser, { onInitializeNewBrowserTab, ...options }, automation) } + options.relaunchBrowser = this.relaunchBrowser + return await browsers.open(browser, options, automation, this._ctx) } diff --git a/packages/server/lib/project-base.ts b/packages/server/lib/project-base.ts index 3b41ed790b16..291b0d775a82 100644 --- a/packages/server/lib/project-base.ts +++ b/packages/server/lib/project-base.ts @@ -103,7 +103,9 @@ export class ProjectBase extends EE { this.options = { report: false, onFocusTests () {}, - onError () {}, + onError (error) { + errors.log(error) + }, onWarning: this.ctx.onWarning, ...options, } diff --git a/packages/types/src/server.ts b/packages/types/src/server.ts index 2fa7228e9892..dd381edb9a4d 100644 --- a/packages/types/src/server.ts +++ b/packages/types/src/server.ts @@ -20,6 +20,7 @@ export type BrowserLaunchOpts = { isTextTerminal: boolean onBrowserClose?: (...args: unknown[]) => void onBrowserOpen?: (...args: unknown[]) => void + relaunchBrowser?: () => Promise } & Partial // TODO: remove the `Partial` here by making it impossible for openProject.launch to be called w/o OpenProjectLaunchOpts & Pick diff --git a/system-tests/__snapshots__/browser_crash_handling_spec.js b/system-tests/__snapshots__/browser_crash_handling_spec.js new file mode 100644 index 000000000000..606e1ee0d4f5 --- /dev/null +++ b/system-tests/__snapshots__/browser_crash_handling_spec.js @@ -0,0 +1,331 @@ +exports['Browser Crash Handling / when the tab crashes in chrome / fails'] = ` + +==================================================================================================== + + (Run Starting) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Cypress: 1.2.3 │ + │ Browser: FooBrowser 88 │ + │ Specs: 2 found (chrome_tab_crash.cy.js, simple.cy.js) │ + │ Searched: cypress/e2e/chrome_tab_crash.cy.js, cypress/e2e/simple.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +──────────────────────────────────────────────────────────────────────────────────────────────────── + + Running: chrome_tab_crash.cy.js (1 of 2) + + + +We detected that the Chromium Renderer process just crashed. + +This is the equivalent to seeing the 'sad face' when Chrome dies. + +This can happen for a number of different reasons: + +- You wrote an endless loop and you must fix your own code +- You are running Docker (there is an easy fix for this: see link below) +- You are running lots of tests on a memory intense application +- You are running in a memory starved VM environment +- There are problems with your GPU / GPU drivers +- There are browser bugs in Chromium + +You can learn more including how to fix Docker here: + +https://on.cypress.io/renderer-process-crashed + + (Results) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Tests: 0 │ + │ Passing: 0 │ + │ Failing: 1 │ + │ Pending: 0 │ + │ Skipped: 0 │ + │ Screenshots: 0 │ + │ Video: true │ + │ Duration: X seconds │ + │ Spec Ran: chrome_tab_crash.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + + (Video) + + - Started processing: Compressing to 32 CRF + - Finished processing: /XXX/XXX/XXX/cypress/videos/chrome_tab_crash.cy.js.mp4 (X second) + + +──────────────────────────────────────────────────────────────────────────────────────────────────── + + Running: simple.cy.js (2 of 2) + + + ✓ is true + + 1 passing + + + (Results) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Tests: 1 │ + │ Passing: 1 │ + │ Failing: 0 │ + │ Pending: 0 │ + │ Skipped: 0 │ + │ Screenshots: 0 │ + │ Video: true │ + │ Duration: X seconds │ + │ Spec Ran: simple.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + + (Video) + + - Started processing: Compressing to 32 CRF + - Finished processing: /XXX/XXX/XXX/cypress/videos/simple.cy.js.mp4 (X second) + + +==================================================================================================== + + (Run Finished) + + + Spec Tests Passing Failing Pending Skipped + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ ✖ chrome_tab_crash.cy.js XX:XX - - 1 - - │ + ├────────────────────────────────────────────────────────────────────────────────────────────────┤ + │ ✔ simple.cy.js XX:XX 1 1 - - - │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + ✖ 1 of 2 failed (50%) XX:XX 1 1 1 - - + + +` + +exports['Browser Crash Handling / when the tab crashes in electron / fails'] = ` + +==================================================================================================== + + (Run Starting) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Cypress: 1.2.3 │ + │ Browser: FooBrowser 88 │ + │ Specs: 2 found (chrome_tab_crash.cy.js, simple.cy.js) │ + │ Searched: cypress/e2e/chrome_tab_crash.cy.js, cypress/e2e/simple.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +──────────────────────────────────────────────────────────────────────────────────────────────────── + + Running: chrome_tab_crash.cy.js (1 of 2) + + + +We detected that the Chromium Renderer process just crashed. + +This is the equivalent to seeing the 'sad face' when Chrome dies. + +This can happen for a number of different reasons: + +- You wrote an endless loop and you must fix your own code +- You are running Docker (there is an easy fix for this: see link below) +- You are running lots of tests on a memory intense application +- You are running in a memory starved VM environment +- There are problems with your GPU / GPU drivers +- There are browser bugs in Chromium + +You can learn more including how to fix Docker here: + +https://on.cypress.io/renderer-process-crashed + + (Results) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Tests: 0 │ + │ Passing: 0 │ + │ Failing: 1 │ + │ Pending: 0 │ + │ Skipped: 0 │ + │ Screenshots: 0 │ + │ Video: true │ + │ Duration: X seconds │ + │ Spec Ran: chrome_tab_crash.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + + (Video) + + - Started processing: Compressing to 32 CRF + - Finished processing: /XXX/XXX/XXX/cypress/videos/chrome_tab_crash.cy.js.mp4 (X second) + + +──────────────────────────────────────────────────────────────────────────────────────────────────── + + Running: simple.cy.js (2 of 2) + + + ✓ is true + + 1 passing + + + (Results) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Tests: 1 │ + │ Passing: 1 │ + │ Failing: 0 │ + │ Pending: 0 │ + │ Skipped: 0 │ + │ Screenshots: 0 │ + │ Video: true │ + │ Duration: X seconds │ + │ Spec Ran: simple.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + + (Video) + + - Started processing: Compressing to 32 CRF + - Finished processing: /XXX/XXX/XXX/cypress/videos/simple.cy.js.mp4 (X second) + + +==================================================================================================== + + (Run Finished) + + + Spec Tests Passing Failing Pending Skipped + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ ✖ chrome_tab_crash.cy.js XX:XX - - 1 - - │ + ├────────────────────────────────────────────────────────────────────────────────────────────────┤ + │ ✔ simple.cy.js XX:XX 1 1 - - - │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + ✖ 1 of 2 failed (50%) XX:XX 1 1 1 - - + + +` + +exports['Browser Crash Handling / when the browser process crashes in chrome / fails'] = ` + +==================================================================================================== + + (Run Starting) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Cypress: 1.2.3 │ + │ Browser: FooBrowser 88 │ + │ Specs: 2 found (chrome_process_crash.cy.js, simple.cy.js) │ + │ Searched: cypress/e2e/chrome_process_crash.cy.js, cypress/e2e/simple.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +──────────────────────────────────────────────────────────────────────────────────────────────────── + + Running: chrome_process_crash.cy.js (1 of 2) + + + +We detected that the Chrome process just crashed with code 'null' and signal 'SIGTRAP'. + +We have failed the current test and have relaunched Chrome. + +This can happen for many different reasons: + +- You wrote an endless loop and you must fix your own code +- You are running lots of tests on a memory intense application +- You are running in a memory starved VM environment +- There are problems with your GPU / GPU drivers +- There are browser bugs + + (Results) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Tests: 0 │ + │ Passing: 0 │ + │ Failing: 1 │ + │ Pending: 0 │ + │ Skipped: 0 │ + │ Screenshots: 0 │ + │ Video: true │ + │ Duration: X seconds │ + │ Spec Ran: chrome_process_crash.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + + (Video) + + - Started processing: Compressing to 32 CRF + - Finished processing: /XXX/XXX/XXX/cypress/videos/chrome_process_crash.cy.js.mp4 (X second) + + +──────────────────────────────────────────────────────────────────────────────────────────────────── + + Running: simple.cy.js (2 of 2) + + + ✓ is true + + 1 passing + + + (Results) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Tests: 1 │ + │ Passing: 1 │ + │ Failing: 0 │ + │ Pending: 0 │ + │ Skipped: 0 │ + │ Screenshots: 0 │ + │ Video: true │ + │ Duration: X seconds │ + │ Spec Ran: simple.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + + (Video) + + - Started processing: Compressing to 32 CRF + - Finished processing: /XXX/XXX/XXX/cypress/videos/simple.cy.js.mp4 (X second) + + +==================================================================================================== + + (Run Finished) + + + Spec Tests Passing Failing Pending Skipped + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ ✖ chrome_process_crash.cy.js XX:XX - - 1 - - │ + ├────────────────────────────────────────────────────────────────────────────────────────────────┤ + │ ✔ simple.cy.js XX:XX 1 1 - - - │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + ✖ 1 of 2 failed (50%) XX:XX 1 1 1 - - + + +` + +exports['Browser Crash Handling / when the browser process crashes in electron / fails'] = ` + +==================================================================================================== + + (Run Starting) + + ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ Cypress: 1.2.3 │ + │ Browser: FooBrowser 88 │ + │ Specs: 2 found (chrome_process_crash.cy.js, simple.cy.js) │ + │ Searched: cypress/e2e/chrome_process_crash.cy.js, cypress/e2e/simple.cy.js │ + └────────────────────────────────────────────────────────────────────────────────────────────────┘ + + +──────────────────────────────────────────────────────────────────────────────────────────────────── + + Running: chrome_process_crash.cy.js (1 of 2) + + + +` diff --git a/system-tests/projects/e2e/cypress/e2e/chrome_process_crash.cy.js b/system-tests/projects/e2e/cypress/e2e/chrome_process_crash.cy.js new file mode 100644 index 000000000000..7c70a2e0a6c3 --- /dev/null +++ b/system-tests/projects/e2e/cypress/e2e/chrome_process_crash.cy.js @@ -0,0 +1,4 @@ +it('crashes the chrome process', () => { + Cypress.automation('remote:debugger:protocol', { command: 'Browser.crash', params: {} }) + cy.visit('localhost') +}) diff --git a/system-tests/projects/e2e/cypress/e2e/chrome_tab_crash.cy.js b/system-tests/projects/e2e/cypress/e2e/chrome_tab_crash.cy.js new file mode 100644 index 000000000000..77fc85a8a850 --- /dev/null +++ b/system-tests/projects/e2e/cypress/e2e/chrome_tab_crash.cy.js @@ -0,0 +1,4 @@ +it('crashes the chrome tab', () => { + Cypress.automation('remote:debugger:protocol', { command: 'Page.navigate', params: { url: 'chrome://crash', transitionType: 'typed' } }) + cy.visit('localhost') +}) diff --git a/system-tests/projects/e2e/cypress/e2e/web_security.cy.js b/system-tests/projects/e2e/cypress/e2e/web_security.cy.js index 8963bb0a7a86..06b8bf57c650 100644 --- a/system-tests/projects/e2e/cypress/e2e/web_security.cy.js +++ b/system-tests/projects/e2e/cypress/e2e/web_security.cy.js @@ -25,7 +25,7 @@ describe('web security', function () { .contains('success!', { timeout: 500 }) }) - it('finds the correct spec bridge even if a previous spec bridge host is a subset of the current host', () => { + it('finds the correct spec bridge even if a previous spec bridge host is a subset of the current host', { defaultCommandTimeout: 4000 }, () => { // Establish a spec bridge with a 'bar.com' host prior to loading 'foobar.com' if (Cypress.config('experimentalSessionAndOrigin')) { cy.origin('http://www.bar.com:4466', () => undefined) diff --git a/system-tests/test/browser_crash_handling_spec.js b/system-tests/test/browser_crash_handling_spec.js new file mode 100644 index 000000000000..5852c5fc4b14 --- /dev/null +++ b/system-tests/test/browser_crash_handling_spec.js @@ -0,0 +1,49 @@ +const systemTests = require('../lib/system-tests').default + +describe('Browser Crash Handling', () => { + systemTests.setup({ + settings: { + e2e: {}, + }, + }) + + // It should fail the chrome_tab_crash spec, but the simple spec should run and succeed + context('when the tab crashes in chrome', () => { + systemTests.it('fails', { + browser: 'chrome', + spec: 'chrome_tab_crash.cy.js,simple.cy.js', + snapshot: true, + expectedExitCode: 1, + }) + }) + + // It should fail the chrome_tab_crash spec, but the simple spec should run and succeed + context('when the tab crashes in electron', () => { + systemTests.it('fails', { + browser: 'electron', + spec: 'chrome_tab_crash.cy.js,simple.cy.js', + snapshot: true, + expectedExitCode: 1, + }) + }) + + // It should fail the chrome_tab_crash spec, but the simple spec should run and succeed + context('when the browser process crashes in chrome', () => { + systemTests.it('fails', { + browser: 'chrome', + spec: 'chrome_process_crash.cy.js,simple.cy.js', + snapshot: true, + expectedExitCode: 1, + }) + }) + + // If chrome crashes, all of cypress crashes when in electron + context('when the browser process crashes in electron', () => { + systemTests.it('fails', { + browser: 'electron', + spec: 'chrome_process_crash.cy.js,simple.cy.js', + snapshot: true, + expectedExitCode: 1, + }) + }) +})