From 853d0dc76fbcf116c127c8fb1209ff879db73443 Mon Sep 17 00:00:00 2001 From: Alex Rudenko Date: Thu, 15 Jun 2023 10:00:14 +0200 Subject: [PATCH] chore: enable coverage over bidi+ (#10387) --- .../src/common/bidi/BrowsingContext.ts | 73 ++++++++++++++----- .../src/common/bidi/Connection.ts | 7 +- .../puppeteer-core/src/common/bidi/Page.ts | 10 ++- test/TestExpectations.json | 48 ++++++++++++ 4 files changed, 118 insertions(+), 20 deletions(-) diff --git a/packages/puppeteer-core/src/common/bidi/BrowsingContext.ts b/packages/puppeteer-core/src/common/bidi/BrowsingContext.ts index 83024c2c923..22126df8764 100644 --- a/packages/puppeteer-core/src/common/bidi/BrowsingContext.ts +++ b/packages/puppeteer-core/src/common/bidi/BrowsingContext.ts @@ -4,7 +4,9 @@ import ProtocolMapping from 'devtools-protocol/types/protocol-mapping.js'; import {WaitForOptions} from '../../api/Page.js'; import PuppeteerUtil from '../../injected/injected.js'; import {assert} from '../../util/assert.js'; +import {Deferred} from '../../util/Deferred.js'; import {stringifyFunction} from '../../util/Function.js'; +import type {CDPSession, Connection as CDPConnection} from '../Connection.js'; import {ProtocolError, TimeoutError} from '../Errors.js'; import {EventEmitter} from '../EventEmitter.js'; import {PuppeteerLifeCycleEvent} from '../LifecycleWatcher.js'; @@ -51,6 +53,54 @@ const lifeCycleToReadinessState = new Map< ['domcontentloaded', 'interactive'], ]); +/** + * @internal + */ +export class CDPSessionWrapper extends EventEmitter implements CDPSession { + #context: BrowsingContext; + #sessionId = Deferred.create(); + + constructor(context: BrowsingContext) { + super(); + this.#context = context; + context.connection + .send('cdp.getSession', { + context: context.id, + }) + .then(session => { + this.#sessionId.resolve(session.result.cdpSession); + }) + .catch(err => { + this.#sessionId.reject(err); + }); + } + + connection(): CDPConnection | undefined { + return undefined; + } + async send( + method: T, + ...paramArgs: ProtocolMapping.Commands[T]['paramsType'] + ): Promise { + const cdpSession = await this.#sessionId.valueOrThrow(); + const result = await this.#context.connection.send('cdp.sendCommand', { + cdpMethod: method, + cdpParams: paramArgs[0] || {}, + cdpSession, + }); + return result.result; + } + + detach(): Promise { + throw new Error('Method not implemented.'); + } + + id(): string { + const val = this.#sessionId.value(); + return val instanceof Error || val === undefined ? '' : val; + } +} + /** * @internal */ @@ -59,7 +109,7 @@ export class BrowsingContext extends EventEmitter { #timeoutSettings: TimeoutSettings; #id: string; #url = 'about:blank'; - #cdpSessionId?: string; + #cdpSession: CDPSession; constructor( connection: Connection, @@ -70,6 +120,7 @@ export class BrowsingContext extends EventEmitter { this.connection = connection; this.#timeoutSettings = timeoutSettings; this.#id = info.context; + this.#cdpSession = new CDPSessionWrapper(this); } #puppeteerUtil?: Promise>; @@ -96,8 +147,8 @@ export class BrowsingContext extends EventEmitter { return this.#id; } - get cdpSessionId(): string | undefined { - return this.#cdpSessionId; + get cdpSession(): CDPSession { + return this.#cdpSession; } async goto( @@ -288,21 +339,9 @@ export class BrowsingContext extends EventEmitter { async sendCDPCommand( method: T, - params: ProtocolMapping.Commands[T]['paramsType'][0] = {} + ...paramArgs: ProtocolMapping.Commands[T]['paramsType'] ): Promise { - if (!this.#cdpSessionId) { - const session = await this.connection.send('cdp.getSession', { - context: this.#id, - }); - const sessionId = session.result.cdpSession; - this.#cdpSessionId = sessionId; - } - const result = await this.connection.send('cdp.sendCommand', { - cdpMethod: method, - cdpParams: params, - cdpSession: this.#cdpSessionId, - }); - return result.result; + return this.#cdpSession.send(method, ...paramArgs); } dispose(): void { diff --git a/packages/puppeteer-core/src/common/bidi/Connection.ts b/packages/puppeteer-core/src/common/bidi/Connection.ts index 6a7b92c1eed..a4341817b47 100644 --- a/packages/puppeteer-core/src/common/bidi/Connection.ts +++ b/packages/puppeteer-core/src/common/bidi/Connection.ts @@ -216,8 +216,11 @@ export class Connection extends EventEmitter { // the CDPSession interface with BiDi?. const cdpSessionId = event.params.cdpSession; for (const context of this.#browsingContexts.values()) { - if (context.cdpSessionId === cdpSessionId) { - context?.emit(event.params.cdpMethod, event.params.cdpParams); + if (context.cdpSession?.id() === cdpSessionId) { + context.cdpSession!.emit( + event.params.cdpMethod, + event.params.cdpParams + ); } } } diff --git a/packages/puppeteer-core/src/common/bidi/Page.ts b/packages/puppeteer-core/src/common/bidi/Page.ts index fb119f7d1d2..a687cf395ca 100644 --- a/packages/puppeteer-core/src/common/bidi/Page.ts +++ b/packages/puppeteer-core/src/common/bidi/Page.ts @@ -29,6 +29,7 @@ import {assert} from '../../util/assert.js'; import {Deferred} from '../../util/Deferred.js'; import {Accessibility} from '../Accessibility.js'; import {ConsoleMessage, ConsoleMessageLocation} from '../ConsoleMessage.js'; +import {Coverage} from '../Coverage.js'; import {TargetCloseError} from '../Errors.js'; import {Handler} from '../EventEmitter.js'; import {FrameManagerEmittedEvents} from '../FrameManager.js'; @@ -120,6 +121,7 @@ export class Page extends PageBase { ], ]); #tracing: Tracing; + #coverage: Coverage; constructor(browserContext: BrowserContext, info: {context: string}) { super(); @@ -169,13 +171,15 @@ export class Page extends PageBase { const deferred = Deferred.create(); this.mainFrame() .context() - .once('Tracing.tracingComplete', event => { + .cdpSession.once('Tracing.tracingComplete', event => { deferred.resolve(event); }); await this.mainFrame().context().sendCDPCommand('Tracing.end'); return deferred.valueOrThrow() as Promise; }, }); + + this.#coverage = new Coverage(this.mainFrame().context().cdpSession); } override get accessibility(): Accessibility { @@ -186,6 +190,10 @@ export class Page extends PageBase { return this.#tracing; } + override get coverage(): Coverage { + return this.#coverage; + } + override browser(): Browser { return this.#browserContext.browser(); } diff --git a/test/TestExpectations.json b/test/TestExpectations.json index 9cc0c6c6d3e..19676bde229 100644 --- a/test/TestExpectations.json +++ b/test/TestExpectations.json @@ -287,6 +287,12 @@ "parameters": ["cdp", "firefox"], "expectations": ["SKIP"] }, + { + "testIdPattern": "[coverage.spec] *", + "platforms": ["darwin", "linux", "win32"], + "parameters": ["chrome", "webDriverBiDi"], + "expectations": ["PASS"] + }, { "testIdPattern": "[Deferred.spec] DeferredPromise should catch errors", "platforms": ["darwin", "linux", "win32"], @@ -1073,6 +1079,48 @@ "parameters": ["cdp", "firefox"], "expectations": ["FAIL"] }, + { + "testIdPattern": "[coverage.spec] Coverage specs CSSCoverage should ignore injected stylesheets", + "platforms": ["darwin", "linux", "win32"], + "parameters": ["chrome", "webDriverBiDi"], + "expectations": ["FAIL"] + }, + { + "testIdPattern": "[coverage.spec] Coverage specs CSSCoverage should work with complicated usecases", + "platforms": ["darwin", "linux", "win32"], + "parameters": ["chrome", "webDriverBiDi"], + "expectations": ["FAIL"] + }, + { + "testIdPattern": "[coverage.spec] Coverage specs CSSCoverage should work with media queries", + "platforms": ["darwin", "linux", "win32"], + "parameters": ["chrome", "webDriverBiDi"], + "expectations": ["FAIL"] + }, + { + "testIdPattern": "[coverage.spec] Coverage specs JSCoverage includeRawScriptCoverage should include rawScriptCoverage field when enabled", + "platforms": ["darwin", "linux", "win32"], + "parameters": ["chrome", "webDriverBiDi"], + "expectations": ["FAIL"] + }, + { + "testIdPattern": "[coverage.spec] Coverage specs JSCoverage includeRawScriptCoverage should not include rawScriptCoverage field when disabled", + "platforms": ["darwin", "linux", "win32"], + "parameters": ["chrome", "webDriverBiDi"], + "expectations": ["FAIL"] + }, + { + "testIdPattern": "[coverage.spec] Coverage specs JSCoverage should ignore pptr internal scripts if reportAnonymousScripts is true", + "platforms": ["darwin", "linux", "win32"], + "parameters": ["chrome", "webDriverBiDi"], + "expectations": ["FAIL"] + }, + { + "testIdPattern": "[coverage.spec] Coverage specs JSCoverage should work", + "platforms": ["darwin", "linux", "win32"], + "parameters": ["chrome", "webDriverBiDi"], + "expectations": ["FAIL"] + }, { "testIdPattern": "[defaultbrowsercontext.spec] DefaultBrowserContext page.deleteCookie() should work", "platforms": ["darwin", "linux", "win32"],