Skip to content

Commit 934f215

Browse files
chore: add after:browser:launch node event (#28180)
1 parent eab1730 commit 934f215

19 files changed

Lines changed: 326 additions & 71 deletions

cli/types/cypress.d.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6009,7 +6009,11 @@ declare namespace Cypress {
60096009
(fn: (currentSubject: Subject) => void): Chainable<Subject>
60106010
}
60116011

6012-
interface BrowserLaunchOptions {
6012+
interface AfterBrowserLaunchDetails {
6013+
webSocketDebuggerUrl: string
6014+
}
6015+
6016+
interface BeforeBrowserLaunchOptions {
60136017
extensions: string[]
60146018
preferences: { [key: string]: any }
60156019
args: string[]
@@ -6090,12 +6094,13 @@ declare namespace Cypress {
60906094
}
60916095

60926096
interface PluginEvents {
6097+
(action: 'after:browser:launch', fn: (browser: Browser, browserLaunchDetails: AfterBrowserLaunchDetails) => void | Promise<void>): void
60936098
(action: 'after:run', fn: (results: CypressCommandLine.CypressRunResult | CypressCommandLine.CypressFailedRunResult) => void | Promise<void>): void
60946099
(action: 'after:screenshot', fn: (details: ScreenshotDetails) => void | AfterScreenshotReturnObject | Promise<AfterScreenshotReturnObject>): void
60956100
(action: 'after:spec', fn: (spec: Spec, results: CypressCommandLine.RunResult) => void | Promise<void>): void
60966101
(action: 'before:run', fn: (runDetails: BeforeRunDetails) => void | Promise<void>): void
60976102
(action: 'before:spec', fn: (spec: Spec) => void | Promise<void>): void
6098-
(action: 'before:browser:launch', fn: (browser: Browser, browserLaunchOptions: BrowserLaunchOptions) => void | BrowserLaunchOptions | Promise<BrowserLaunchOptions>): void
6103+
(action: 'before:browser:launch', fn: (browser: Browser, afterBrowserLaunchOptions: BeforeBrowserLaunchOptions) => void | Promise<void> | BeforeBrowserLaunchOptions | Promise<BeforeBrowserLaunchOptions>): void
60996104
(action: 'file:preprocessor', fn: (file: FileObject) => string | Promise<string>): void
61006105
(action: 'dev-server:start', fn: (file: DevServerConfig) => Promise<ResolvedDevServerConfig>): void
61016106
(action: 'task', tasks: Tasks): void

packages/server/lib/browsers/browser-cri-client.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,13 @@ export class BrowserCriClient {
574574
this.extraTargetClients.delete(targetId)
575575
}
576576

577+
/**
578+
* @returns the websocket debugger URL for the currently connected browser
579+
*/
580+
getWebSocketDebuggerUrl () {
581+
return this.versionInfo.webSocketDebuggerUrl
582+
}
583+
577584
/**
578585
* Closes the browser client socket as well as the socket for the currently attached page target
579586
*/

packages/server/lib/browsers/chrome.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,10 @@ export = {
645645

646646
await this.attachListeners(url, pageCriClient, automation, options, browser)
647647

648+
await utils.executeAfterBrowserLaunch(browser, {
649+
webSocketDebuggerUrl: browserCriClient.getWebSocketDebuggerUrl(),
650+
})
651+
648652
// return the launched browser process
649653
// with additional method to close the remote connection
650654
return launchedBrowser

packages/server/lib/browsers/cri-client.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -265,15 +265,26 @@ export const create = async ({
265265

266266
maybeDebugCdpMessages(cri)
267267

268-
// Only reconnect when we're not running cypress in cypress. There are a lot of disconnects that happen that we don't want to reconnect on
269-
if (!process.env.CYPRESS_INTERNAL_E2E_TESTING_SELF) {
268+
// Having a host set indicates that this is the child cri target, a.k.a.
269+
// the main Cypress tab (as opposed to the root browser cri target)
270+
const isChildTarget = !!host
271+
272+
// don't reconnect in these circumstances
273+
if (
274+
// is a child target. we only need to reconnect the root browser target
275+
!isChildTarget
276+
// running cypress in cypress - there are a lot of disconnects that happen
277+
// that we don't want to reconnect on
278+
&& !process.env.CYPRESS_INTERNAL_E2E_TESTING_SELF
279+
) {
270280
cri.on('disconnect', retryReconnect)
271281
}
272282

273-
// We only want to try and add child target traffic if we have a host set. This indicates that this is the child cri client.
274-
// Browser cri traffic is handled in browser-cri-client.ts. The basic approach here is we attach to targets and enable network traffic
275-
// We must attach in a paused state so that we can enable network traffic before the target starts running.
276-
if (host) {
283+
// We're only interested in child target traffic. Browser cri traffic is
284+
// handled in browser-cri-client.ts. The basic approach here is we attach
285+
// to targets and enable network traffic. We must attach in a paused state
286+
// so that we can enable network traffic before the target starts running.
287+
if (isChildTarget) {
277288
cri.on('Target.targetCrashed', async (event) => {
278289
if (event.targetId !== target) {
279290
return

packages/server/lib/browsers/electron.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,10 @@ export = {
539539
},
540540
}) as BrowserInstance
541541

542+
await utils.executeAfterBrowserLaunch(browser, {
543+
webSocketDebuggerUrl: browserCriClient!.getWebSocketDebuggerUrl(),
544+
})
545+
542546
return instance
543547
},
544548
}

packages/server/lib/browsers/firefox.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ toolbar {
347347
348348
`
349349

350-
let browserCriClient
350+
let browserCriClient: BrowserCriClient | undefined
351351

352352
export function _createDetachedInstance (browserInstance: BrowserInstance, browserCriClient?: BrowserCriClient): BrowserInstance {
353353
const detachedInstance: BrowserInstance = new EventEmitter() as BrowserInstance
@@ -382,7 +382,7 @@ export function clearInstanceState (options: GracefulShutdownOptions = {}) {
382382
}
383383

384384
export async function connectToNewSpec (browser: Browser, options: BrowserNewTabOpts, automation: Automation) {
385-
await firefoxUtil.connectToNewSpec(options, automation, browserCriClient)
385+
await firefoxUtil.connectToNewSpec(options, automation, browserCriClient!)
386386
}
387387

388388
export function connectToExisting () {
@@ -573,6 +573,10 @@ export async function open (browser: Browser, url: string, options: BrowserLaunc
573573

574574
return originalBrowserKill.apply(browserInstance, args)
575575
}
576+
577+
await utils.executeAfterBrowserLaunch(browser, {
578+
webSocketDebuggerUrl: browserCriClient.getWebSocketDebuggerUrl(),
579+
})
576580
} catch (err) {
577581
errors.throwErr('FIREFOX_COULD_NOT_CONNECT', err)
578582
}

packages/server/lib/browsers/utils.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as plugins from '../plugins'
77
import { getError } from '@packages/errors'
88
import * as launcher from '@packages/launcher'
99
import type { Automation } from '../automation'
10+
import type { Browser } from './types'
1011
import type { CriClient } from './cri-client'
1112

1213
declare global {
@@ -157,6 +158,27 @@ async function executeBeforeBrowserLaunch (browser, launchOptions: typeof defaul
157158
return launchOptions
158159
}
159160

161+
interface AfterBrowserLaunchDetails {
162+
webSocketDebuggerUrl: string | never
163+
}
164+
165+
async function executeAfterBrowserLaunch (browser: Browser, options: AfterBrowserLaunchDetails) {
166+
if (plugins.has('after:browser:launch')) {
167+
const span = telemetry.startSpan({ name: 'lifecycle:after:browser:launch' })
168+
169+
span?.setAttribute({
170+
name: browser.name,
171+
channel: browser.channel,
172+
version: browser.version,
173+
isHeadless: browser.isHeadless,
174+
})
175+
176+
await plugins.execute('after:browser:launch', browser, options)
177+
178+
span?.end()
179+
}
180+
}
181+
160182
function extendLaunchOptionsFromPlugins (launchOptions, pluginConfigResult, options: BrowserLaunchOpts) {
161183
// if we returned an array from the plugin
162184
// then we know the user is using the deprecated
@@ -423,6 +445,8 @@ export = {
423445

424446
extendLaunchOptionsFromPlugins,
425447

448+
executeAfterBrowserLaunch,
449+
426450
executeBeforeBrowserLaunch,
427451

428452
defaultLaunchOptions,

packages/server/lib/browsers/webkit.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ export async function open (browser: Browser, url: string, options: BrowserLaunc
101101

102102
removeBadExitListener()
103103

104-
const pwBrowser = await pw.webkit.connect(pwServer.wsEndpoint())
104+
const websocketUrl = pwServer.wsEndpoint()
105+
const pwBrowser = await pw.webkit.connect(websocketUrl)
105106

106107
wkAutomation = await WebKitAutomation.create({
107108
automation,
@@ -147,5 +148,9 @@ export async function open (browser: Browser, url: string, options: BrowserLaunc
147148
}
148149
}
149150

151+
await utils.executeAfterBrowserLaunch(browser, {
152+
webSocketDebuggerUrl: websocketUrl,
153+
})
154+
150155
return new WkInstance()
151156
}

packages/server/lib/plugins/child/browser_launch.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const util = require('../util')
33
const ARRAY_METHODS = ['concat', 'push', 'unshift', 'slice', 'pop', 'shift', 'slice', 'splice', 'filter', 'map', 'forEach', 'reduce', 'reverse', 'splice', 'includes']
44

55
module.exports = {
6-
wrap (ipc, invoke, ids, args) {
6+
wrapBefore (ipc, invoke, ids, args) {
77
// TODO: remove in next breaking release
88
// This will send a warning message when a deprecated API is used
99
// define array-like functions on this object so we can warn about using deprecated array API

packages/server/lib/plugins/child/run_plugins.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,9 @@ class RunPlugins {
169169
case '_get:task:body':
170170
return this.taskGetBody(ids, args)
171171
case 'before:browser:launch':
172-
return browserLaunch.wrap(this.ipc, this.invoke, ids, args)
172+
return browserLaunch.wrapBefore(this.ipc, this.invoke, ids, args)
173+
case 'after:browser:launch':
174+
return util.wrapChildPromise(this.ipc, this.invoke, ids, args)
173175
default:
174176
debug('unexpected execute message:', event, args)
175177

0 commit comments

Comments
 (0)