From 2d7c003adaf2690606cf084fc158626c2ebcf3a4 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Mon, 8 Aug 2022 10:39:54 -0700 Subject: [PATCH] chore: minor inspect tweaks (#16334) --- packages/playwright-core/src/cli/driver.ts | 31 +++++++++++++++++-- .../src/remote/playwrightConnection.ts | 27 +++++++++++++--- .../src/server/injected/recorder.ts | 2 +- .../playwright-core/src/server/recorder.ts | 6 ++-- 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/packages/playwright-core/src/cli/driver.ts b/packages/playwright-core/src/cli/driver.ts index dd3d828e58..4c7573ec83 100644 --- a/packages/playwright-core/src/cli/driver.ts +++ b/packages/playwright-core/src/cli/driver.ts @@ -28,6 +28,7 @@ import { gracefullyCloseAll } from '../utils/processLauncher'; import { Recorder } from '../server/recorder'; import { EmptyRecorderApp } from '../server/recorder/recorderApp'; import type { BrowserContext } from '../server/browserContext'; +import { serverSideCallMetadata } from '../server/instrumentation'; export function printApiJson() { // Note: this file is generated by build-playwright-driver.sh @@ -80,6 +81,8 @@ function selfDestruct() { }); } +const internalMetadata = serverSideCallMetadata(); + function wireController(playwright: Playwright, wsEndpoint: string) { process.send!({ method: 'ready', params: { wsEndpoint } }); process.on('message', async message => { @@ -90,13 +93,37 @@ function wireController(playwright: Playwright, wsEndpoint: string) { } if (message.method === 'inspect') { - for (const recorder of await allRecorders(playwright)) - recorder.setMode(message.params.enabled ? 'inspecting' : 'none'); + if (!message.params.enabled) { + for (const recorder of await allRecorders(playwright)) { + recorder.setHighlightedSelector(''); + recorder.setMode('none'); + } + return; + } + + // Create browser if none. + const browsers = playwright.allBrowsers(); + if (!browsers.length) + await playwright.chromium.launch(internalMetadata, { headless: false }); + // Create page if none. + const pages = playwright.allPages(); + if (!pages.length) { + const [browser] = playwright.allBrowsers(); + const { context } = await browser.newContextForReuse({}, internalMetadata); + await context.newPage(internalMetadata); + } + // Toggle inspect mode. + for (const recorder of await allRecorders(playwright)) { + recorder.setHighlightedSelector(''); + recorder.setMode('inspecting'); + } + return; } if (message.method === 'highlight') { for (const recorder of await allRecorders(playwright)) recorder.setHighlightedSelector(message.params.selector); + return; } } catch (e) { diff --git a/packages/playwright-core/src/remote/playwrightConnection.ts b/packages/playwright-core/src/remote/playwrightConnection.ts index afa84413e4..c8900352ba 100644 --- a/packages/playwright-core/src/remote/playwrightConnection.ts +++ b/packages/playwright-core/src/remote/playwrightConnection.ts @@ -100,9 +100,10 @@ export class PlaywrightConnection { const socksProxy = this._options.enableSocksProxy ? await this._enableSocksProxy(playwright) : undefined; const browser = await playwright[this._options.browserName as 'chromium'].launch(serverSideCallMetadata(), this._options.launchOptions); - // Close the browser on disconnect. - // TODO: it is technically possible to launch more browsers over protocol. - this._cleanups.push(() => browser.close()); + this._cleanups.push(async () => { + for (const browser of playwright.allBrowsers()) + await browser.close(); + }); browser.on(Browser.Events.Disconnected, () => { // Underlying browser did close for some reason - force disconnect the client. this.close({ code: 1001, reason: 'Browser closed' }); @@ -120,8 +121,11 @@ export class PlaywrightConnection { this.close({ code: 1001, reason: 'Browser closed' }); }); const playwrightDispatcher = new PlaywrightDispatcher(scope, playwright, undefined, browser); - // In pre-launched mode, keep the browser and just cleanup new contexts. - // TODO: it is technically possible to launch more browsers over protocol. + // In pre-launched mode, keep only the pre-launched browser. + for (const b of playwright.allBrowsers()) { + if (b !== browser) + await b.close(); + } this._cleanups.push(() => playwrightDispatcher.cleanup()); return playwrightDispatcher; } @@ -156,6 +160,19 @@ export class PlaywrightConnection { }); } + this._cleanups.push(async () => { + // Don't close the pages so that user could debug them, + // but close all the empty browsers and contexts to clean up. + for (const browser of playwright.allBrowsers()) { + for (const context of browser.contexts()) { + if (!context.pages().length) + await context.close(serverSideCallMetadata()); + } + if (!browser.contexts()) + await browser.close(); + } + }); + const playwrightDispatcher = new PlaywrightDispatcher(scope, playwright, undefined, browser); return playwrightDispatcher; } diff --git a/packages/playwright-core/src/server/injected/recorder.ts b/packages/playwright-core/src/server/injected/recorder.ts index 523a6ed608..095f8d9b8d 100644 --- a/packages/playwright-core/src/server/injected/recorder.ts +++ b/packages/playwright-core/src/server/injected/recorder.ts @@ -85,7 +85,7 @@ class Recorder { } private async _pollRecorderMode() { - const pollPeriod = 500; + const pollPeriod = 1000; if (this._pollRecorderModeTimer) clearTimeout(this._pollRecorderModeTimer); const state = await globalThis.__pw_recorderState().catch(e => null); diff --git a/packages/playwright-core/src/server/recorder.ts b/packages/playwright-core/src/server/recorder.ts index 551c787d26..5b9308fd00 100644 --- a/packages/playwright-core/src/server/recorder.ts +++ b/packages/playwright-core/src/server/recorder.ts @@ -97,12 +97,10 @@ export class Recorder implements InstrumentationListener { recorderApp.on('event', (data: EventData) => { if (data.event === 'setMode') { this.setMode(data.params.mode); - this._refreshOverlay(); return; } if (data.event === 'selectorUpdated') { - this._highlightedSelector = data.params.selector; - this._refreshOverlay(); + this.setHighlightedSelector(data.params.selector); return; } if (data.event === 'step') { @@ -189,12 +187,14 @@ export class Recorder implements InstrumentationListener { setMode(mode: Mode) { if (this._mode === mode) return; + this._highlightedSelector = ''; this._mode = mode; this._recorderApp?.setMode(this._mode); this._contextRecorder.setEnabled(this._mode === 'recording'); this._debugger.setMuted(this._mode === 'recording'); if (this._mode !== 'none' && this._context.pages().length === 1) this._context.pages()[0].bringToFront().catch(() => {}); + this._refreshOverlay(); } setHighlightedSelector(selector: string) {