chore: update chromium-bidi (#10620)

This commit is contained in:
Nikolay Vitkov 2023-07-28 11:11:14 +02:00 committed by GitHub
parent fdada74ba7
commit 0757d04358
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 397 additions and 285 deletions

36
package-lock.json generated
View File

@ -3411,16 +3411,21 @@
}
},
"node_modules/chromium-bidi": {
"version": "0.4.16",
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.16.tgz",
"integrity": "sha512-7ZbXdWERxRxSwo3txsBjjmc/NLxqb1Bk30mRb0BMS4YIaiV6zvKZqL/UAH+DdqcDYayDWk2n/y8klkBDODrPvA==",
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.19.tgz",
"integrity": "sha512-8pzgvc/f4OpQMNRqgwqJKLd1cJFzKgh/foXbUgSD+lCyB+SSHUgo6FYaOHoMfHv10+0kP3/WYxKVGV1MH8QjtQ==",
"dependencies": {
"mitt": "3.0.0"
"mitt": "3.0.1"
},
"peerDependencies": {
"devtools-protocol": "*"
}
},
"node_modules/chromium-bidi/node_modules/mitt": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
},
"node_modules/ci-info": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz",
@ -7222,6 +7227,7 @@
},
"node_modules/mitt": {
"version": "3.0.0",
"dev": true,
"license": "MIT"
},
"node_modules/mkdirp": {
@ -10563,7 +10569,7 @@
"license": "Apache-2.0",
"dependencies": {
"@puppeteer/browsers": "1.4.6",
"chromium-bidi": "0.4.16",
"chromium-bidi": "0.4.19",
"cross-fetch": "4.0.0",
"debug": "4.3.4",
"devtools-protocol": "0.0.1147663",
@ -12894,11 +12900,18 @@
"dev": true
},
"chromium-bidi": {
"version": "0.4.16",
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.16.tgz",
"integrity": "sha512-7ZbXdWERxRxSwo3txsBjjmc/NLxqb1Bk30mRb0BMS4YIaiV6zvKZqL/UAH+DdqcDYayDWk2n/y8klkBDODrPvA==",
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.19.tgz",
"integrity": "sha512-8pzgvc/f4OpQMNRqgwqJKLd1cJFzKgh/foXbUgSD+lCyB+SSHUgo6FYaOHoMfHv10+0kP3/WYxKVGV1MH8QjtQ==",
"requires": {
"mitt": "3.0.0"
"mitt": "3.0.1"
},
"dependencies": {
"mitt": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
}
}
},
"ci-info": {
@ -15419,7 +15432,8 @@
}
},
"mitt": {
"version": "3.0.0"
"version": "3.0.0",
"dev": true
},
"mkdirp": {
"version": "1.0.4",
@ -16338,7 +16352,7 @@
"version": "file:packages/puppeteer-core",
"requires": {
"@puppeteer/browsers": "1.4.6",
"chromium-bidi": "0.4.16",
"chromium-bidi": "0.4.19",
"cross-fetch": "4.0.0",
"debug": "4.3.4",
"devtools-protocol": "0.0.1147663",

View File

@ -144,7 +144,7 @@
"author": "The Chromium Authors",
"license": "Apache-2.0",
"dependencies": {
"chromium-bidi": "0.4.16",
"chromium-bidi": "0.4.19",
"cross-fetch": "4.0.0",
"debug": "4.3.4",
"devtools-protocol": "0.0.1147663",

View File

@ -1074,6 +1074,9 @@ export class ElementHandle<
}
}
/**
* @public
*/
export interface AutofillData {
creditCard: {
// See https://chromedevtools.github.io/devtools-protocol/tot/Autofill/#type-CreditCard.

View File

@ -86,7 +86,7 @@ class CDPConnectionAdapter {
throw new Error('Unknown CDP session with id' + id);
}
if (!this.#adapters.has(session)) {
const adapter = new CDPClientAdapter(session);
const adapter = new CDPClientAdapter(session, id, this.#browser);
this.#adapters.set(session, adapter);
return adapter;
}
@ -113,13 +113,25 @@ class CDPClientAdapter<T extends EventEmitter & Pick<CDPPPtrConnection, 'send'>>
{
#closed = false;
#client: T;
sessionId: string | undefined = undefined;
#browserClient?: BidiMapper.CdpClient;
constructor(client: T) {
constructor(
client: T,
sessionId?: string,
browserClient?: BidiMapper.CdpClient
) {
super();
this.#client = client;
this.sessionId = sessionId;
this.#browserClient = browserClient;
this.#client.on('*', this.#forwardMessage as Handler<any>);
}
browserClient(): BidiMapper.CdpClient {
return this.#browserClient!;
}
#forwardMessage = <T extends keyof CdpEvents>(
method: T,
event: CdpEvents[T]
@ -163,32 +175,27 @@ class NoOpTransport
extends BidiMapper.EventEmitter<any>
implements BidiMapper.BidiTransport
{
#onMessage: (
message: Bidi.Message.RawCommandRequest
) => Promise<void> | void = async (
_m: Bidi.Message.RawCommandRequest
): Promise<void> => {
return;
};
#onMessage: (message: Bidi.ChromiumBidi.Command) => Promise<void> | void =
async (_m: Bidi.ChromiumBidi.Command): Promise<void> => {
return;
};
emitMessage(message: Bidi.Message.RawCommandRequest) {
emitMessage(message: Bidi.ChromiumBidi.Command) {
void this.#onMessage(message);
}
setOnMessage(
onMessage: (message: Bidi.Message.RawCommandRequest) => Promise<void> | void
onMessage: (message: Bidi.ChromiumBidi.Command) => Promise<void> | void
): void {
this.#onMessage = onMessage;
}
async sendMessage(message: Bidi.Message.OutgoingMessage): Promise<void> {
async sendMessage(message: Bidi.ChromiumBidi.Message): Promise<void> {
this.emit('bidiResponse', message);
}
close() {
this.#onMessage = async (
_m: Bidi.Message.RawCommandRequest
): Promise<void> => {
this.#onMessage = async (_m: Bidi.ChromiumBidi.Command): Promise<void> => {
return;
};
}

View File

@ -49,7 +49,8 @@ import {debugError} from './utils.js';
* @internal
*/
export class Browser extends BrowserBase {
static readonly subscribeModules: Bidi.Session.SubscriptionRequestEvent[] = [
// TODO: Update generator to include fully module
static readonly subscribeModules: string[] = [
'browsingContext',
'network',
'log',
@ -114,12 +115,16 @@ export class Browser extends BrowserBase {
#contexts: BrowserContext[] = [];
#browserTarget: BiDiBrowserTarget;
#connectionEventHandlers = new Map<string, Handler<any>>([
#connectionEventHandlers = new Map<
Bidi.BrowsingContextEvent['method'],
Handler<any>
>([
['browsingContext.contextCreated', this.#onContextCreated.bind(this)],
['browsingContext.contextDestroyed', this.#onContextDestroyed.bind(this)],
['browsingContext.domContentLoaded', this.#onContextDomLoaded.bind(this)],
['browsingContext.fragmentNavigated', this.#onContextNavigation.bind(this)],
['browsingContext.navigationStarted', this.#onContextNavigation.bind(this)],
]) as Map<Bidi.BrowsingContext.EventNames, Handler>;
]);
constructor(
opts: Options & {
@ -151,6 +156,15 @@ export class Browser extends BrowserBase {
}
}
#onContextDomLoaded(event: Bidi.BrowsingContext.Info) {
const context = this.#connection.getBrowsingContext(event.context);
context.url = event.url;
const target = this.#targets.get(event.context);
if (target) {
this.emit(BrowserEmittedEvents.TargetChanged, target);
}
}
#onContextNavigation(event: Bidi.BrowsingContext.NavigationInfo) {
const context = this.#connection.getBrowsingContext(event.context);
context.url = event.url;
@ -163,7 +177,7 @@ export class Browser extends BrowserBase {
}
}
#onContextCreated(event: Bidi.BrowsingContext.ContextCreatedEvent['params']) {
#onContextCreated(event: Bidi.BrowsingContext.ContextCreated['params']) {
const context = new BrowsingContext(this.#connection, event);
this.#connection.registerBrowsingContexts(context);
// TODO: once more browsing context types are supported, this should be
@ -197,7 +211,7 @@ export class Browser extends BrowserBase {
}
async #onContextDestroyed(
event: Bidi.BrowsingContext.ContextDestroyedEvent['params']
event: Bidi.BrowsingContext.ContextDestroyed['params']
) {
const context = this.#connection.getBrowsingContext(event.context);
const topLevelContext = this.#connection.getTopLevelContext(event.context);

View File

@ -14,6 +14,8 @@
* limitations under the License.
*/
import * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
import {BrowserContext as BrowserContextBase} from '../../api/BrowserContext.js';
import {Page as PageBase} from '../../api/Page.js';
import {Target} from '../../api/Target.js';
@ -66,7 +68,7 @@ export class BrowserContext extends BrowserContextBase {
override async newPage(): Promise<PageBase> {
const {result} = await this.#connection.send('browsingContext.create', {
type: 'tab',
type: Bidi.BrowsingContext.CreateType.Tab,
});
const target = this.#browser._getTargetById(result.context);

View File

@ -32,8 +32,8 @@ const lifeCycleToReadinessState = new Map<
PuppeteerLifeCycleEvent,
Bidi.BrowsingContext.ReadinessState
>([
['load', 'complete'],
['domcontentloaded', 'interactive'],
['load', Bidi.BrowsingContext.ReadinessState.Complete],
['domcontentloaded', Bidi.BrowsingContext.ReadinessState.Interactive],
]);
/**
@ -84,7 +84,7 @@ export class CDPSessionWrapper extends EventEmitter implements CDPSession {
);
}
const session = await this.#sessionId.valueOrThrow();
const result = await this.#context.connection.send('cdp.sendCommand', {
const {result} = await this.#context.connection.send('cdp.sendCommand', {
method: method,
params: paramArgs[0],
session,
@ -140,12 +140,12 @@ export class BrowsingContext extends Realm {
this.#parent = info.parent;
this.#cdpSession = new CDPSessionWrapper(this);
this.on(
'browsingContext.fragmentNavigated',
(info: Bidi.BrowsingContext.NavigationInfo) => {
this.#url = info.url;
}
);
this.on('browsingContext.domContentLoaded', this.#updateUrl.bind(this));
this.on('browsingContext.load', this.#updateUrl.bind(this));
}
#updateUrl(info: Bidi.BrowsingContext.NavigationInfo) {
this.url = info.url;
}
createSandboxRealm(sandbox: string): Realm {

View File

@ -22,33 +22,11 @@ import {debug} from '../Debug.js';
import {EventEmitter} from '../EventEmitter.js';
import {BrowsingContext, cdpSessions} from './BrowsingContext.js';
import {debugError} from './utils.js';
const debugProtocolSend = debug('puppeteer:webDriverBiDi:SEND ►');
const debugProtocolReceive = debug('puppeteer:webDriverBiDi:RECV ◀');
interface Capability {
// session.CapabilityRequest = {
// ? acceptInsecureCerts: bool,
// ? browserName: text,
// ? browserVersion: text,
// ? platformName: text,
// ? proxy: {
// ? proxyType: "pac" / "direct" / "autodetect" / "system" / "manual",
// ? proxyAutoconfigUrl: text,
// ? ftpProxy: text,
// ? httpProxy: text,
// ? noProxy: [*text],
// ? sslProxy: text,
// ? socksProxy: text,
// ? socksVersion: 0..255,
// },
// Extensible
// };
acceptInsecureCerts?: boolean;
browserName?: string;
browserVersion?: string;
}
/**
* @internal
*/
@ -59,11 +37,11 @@ interface Commands {
};
'script.callFunction': {
params: Bidi.Script.CallFunctionParameters;
returnType: Bidi.Script.CallFunctionResult;
returnType: Bidi.Script.EvaluateResult;
};
'script.disown': {
params: Bidi.Script.DisownParameters;
returnType: Bidi.Script.DisownResult;
returnType: Bidi.EmptyResult;
};
'script.addPreloadScript': {
params: Bidi.Script.AddPreloadScriptParameters;
@ -76,7 +54,7 @@ interface Commands {
};
'browsingContext.close': {
params: Bidi.BrowsingContext.CloseParameters;
returnType: Bidi.Message.EmptyResult;
returnType: Bidi.EmptyResult;
};
'browsingContext.getTree': {
params: Bidi.BrowsingContext.GetTreeParameters;
@ -88,7 +66,7 @@ interface Commands {
};
'browsingContext.reload': {
params: Bidi.BrowsingContext.ReloadParameters;
returnType: Bidi.Message.EmptyResult;
returnType: Bidi.EmptyResult;
};
'browsingContext.print': {
params: Bidi.BrowsingContext.PrintParameters;
@ -101,27 +79,16 @@ interface Commands {
'input.performActions': {
params: Bidi.Input.PerformActionsParameters;
returnType: Bidi.Message.EmptyResult;
returnType: Bidi.EmptyResult;
};
'input.releaseActions': {
params: Bidi.Input.ReleaseActionsParameters;
returnType: Bidi.Message.EmptyResult;
returnType: Bidi.EmptyResult;
};
'session.new': {
params: {
// capabilities: session.CapabilitiesRequest
capabilities?: {
// session.CapabilitiesRequest = {
// ? alwaysMatch: session.CapabilityRequest,
// ? firstMatch: [*session.CapabilityRequest]
// }
alwaysMatch?: Capability;
};
}; // TODO: Update Types in chromium bidi
returnType: {
result: {sessionId: string; capabilities: Capability};
};
params: Bidi.Session.NewParameters;
returnType: Bidi.Session.NewResult;
};
'session.status': {
params: object;
@ -129,18 +96,18 @@ interface Commands {
};
'session.subscribe': {
params: Bidi.Session.SubscriptionRequest;
returnType: Bidi.Message.EmptyResult;
returnType: Bidi.EmptyResult;
};
'session.unsubscribe': {
params: Bidi.Session.SubscriptionRequest;
returnType: Bidi.Message.EmptyResult;
returnType: Bidi.EmptyResult;
};
'cdp.sendCommand': {
params: Bidi.Cdp.SendCommandParams;
params: Bidi.Cdp.SendCommandParameters;
returnType: Bidi.Cdp.SendCommandResult;
};
'cdp.getSession': {
params: Bidi.Cdp.GetSessionParams;
params: Bidi.Cdp.GetSessionParameters;
returnType: Bidi.Cdp.GetSessionResult;
};
}
@ -184,16 +151,16 @@ export class Connection extends EventEmitter {
send<T extends keyof Commands>(
method: T,
params: Commands[T]['params']
): Promise<Commands[T]['returnType']> {
): Promise<{result: Commands[T]['returnType']}> {
return this.#callbacks.create(method, this.#timeout, id => {
const stringifiedMessage = JSON.stringify({
id,
method,
params,
} as Bidi.Message.CommandRequest);
} as Bidi.Command);
debugProtocolSend(stringifiedMessage);
this.#transport.send(stringifiedMessage);
}) as Promise<Commands[T]['returnType']>;
}) as Promise<{result: Commands[T]['returnType']}>;
}
/**
@ -206,27 +173,29 @@ export class Connection extends EventEmitter {
});
}
debugProtocolReceive(message);
const object = JSON.parse(message) as
| Bidi.Message.CommandResponse
| Bidi.Message.EventMessage;
const object = JSON.parse(message) as Bidi.ChromiumBidi.Message;
if ('id' in object) {
if ('id' in object && object.id) {
if ('error' in object) {
this.#callbacks.reject(
object.id,
createProtocolError(object),
createProtocolError(object as Bidi.ErrorResponse),
object.message
);
} else {
this.#callbacks.resolve(object.id, object);
}
} else {
this.#maybeEmitOnContext(object);
this.emit(object.method, object.params);
if ('error' in object || 'id' in object || 'launched' in object) {
debugError(object);
} else {
this.#maybeEmitOnContext(object);
this.emit(object.method, object.params);
}
}
}
#maybeEmitOnContext(event: Bidi.Message.EventMessage) {
#maybeEmitOnContext(event: Bidi.ChromiumBidi.Event) {
let context: BrowsingContext | undefined;
// Context specific events
if ('context' in event.params && event.params.context) {
@ -292,7 +261,7 @@ export class Connection extends EventEmitter {
/**
* @internal
*/
function createProtocolError(object: Bidi.Message.ErrorResult): string {
function createProtocolError(object: Bidi.ErrorResponse): string {
let message = `${object.error} ${object.message}`;
if (object.stacktrace) {
message += ` ${object.stacktrace}`;
@ -300,8 +269,6 @@ function createProtocolError(object: Bidi.Message.ErrorResult): string {
return message;
}
function isCDPEvent(
event: Bidi.Message.EventMessage
): event is Bidi.Cdp.EventReceivedEvent {
function isCDPEvent(event: Bidi.ChromiumBidi.Event): event is Bidi.Cdp.Event {
return event.method.startsWith('cdp.');
}

View File

@ -40,7 +40,7 @@ export class ElementHandle<
constructor(
realm: Realm,
remoteValue: Bidi.CommonDataTypes.RemoteValue,
remoteValue: Bidi.Script.RemoteValue,
frame: Frame
) {
super(new JSHandle(realm, remoteValue));
@ -59,7 +59,7 @@ export class ElementHandle<
return this.handle.isPrimitiveValue;
}
remoteValue(): Bidi.CommonDataTypes.RemoteValue {
remoteValue(): Bidi.Script.RemoteValue {
return this.handle.remoteValue();
}
@ -102,7 +102,7 @@ export class ElementHandle<
Object.assign({}, options, {
origin: {
type: 'element' as const,
element: remoteValue as Bidi.CommonDataTypes.SharedReference,
element: remoteValue as Bidi.Script.SharedReference,
},
})
);
@ -115,7 +115,7 @@ export class ElementHandle<
return this.#frame.page().mouse.move(0, 0, {
origin: {
type: 'element' as const,
element: remoteValue as Bidi.CommonDataTypes.SharedReference,
element: remoteValue as Bidi.Script.SharedReference,
},
});
}
@ -127,7 +127,7 @@ export class ElementHandle<
return this.#frame.page().touchscreen.tap(0, 0, {
origin: {
type: 'element' as const,
element: remoteValue as Bidi.CommonDataTypes.SharedReference,
element: remoteValue as Bidi.Script.SharedReference,
},
});
}
@ -139,7 +139,7 @@ export class ElementHandle<
return this.#frame.page().touchscreen.touchStart(0, 0, {
origin: {
type: 'element' as const,
element: remoteValue as Bidi.CommonDataTypes.SharedReference,
element: remoteValue as Bidi.Script.SharedReference,
},
});
}
@ -151,7 +151,7 @@ export class ElementHandle<
return this.#frame.page().touchscreen.touchMove(0, 0, {
origin: {
type: 'element' as const,
element: remoteValue as Bidi.CommonDataTypes.SharedReference,
element: remoteValue as Bidi.Script.SharedReference,
},
});
}

View File

@ -227,6 +227,8 @@ export class Frame extends BaseFrame {
) as string;
const [info] = await Promise.all([
// TODO(lightning00blade): Should also keep tack of
// navigationAborted and navigationFailed
waitForEvent<Bidi.BrowsingContext.NavigationInfo>(
this.#context,
waitUntilEvent,
@ -236,15 +238,26 @@ export class Frame extends BaseFrame {
timeout,
this.#abortDeferred.valueOrThrow()
),
waitForEvent(
this.#context,
Bidi.BrowsingContext.EventNames.FragmentNavigated,
() => {
return true;
},
timeout,
this.#abortDeferred.valueOrThrow()
),
Deferred.race([
waitForEvent(
this.#context,
Bidi.ChromiumBidi.BrowsingContext.EventNames.NavigationStarted,
() => {
return true;
},
timeout,
this.#abortDeferred.valueOrThrow()
),
waitForEvent(
this.#context,
Bidi.ChromiumBidi.BrowsingContext.EventNames.FragmentNavigated,
() => {
return true;
},
timeout,
this.#abortDeferred.valueOrThrow()
),
]),
]);
return this.#page.getNavigationResponse(info.navigation);

View File

@ -41,7 +41,7 @@ export class HTTPRequest extends BaseHTTPRequest {
#frame: Frame | null;
constructor(
event: Bidi.Network.BeforeRequestSentParams,
event: Bidi.Network.BeforeRequestSentParameters,
frame: Frame | null,
redirectChain: HTTPRequest[]
) {
@ -58,11 +58,11 @@ export class HTTPRequest extends BaseHTTPRequest {
this._redirectChain = redirectChain ?? [];
this._navigationId = event.navigation;
for (const {name, value} of event.request.headers) {
for (const header of event.request.headers) {
// TODO: How to handle Binary Headers
// https://w3c.github.io/webdriver-bidi/#type-network-Header
if (value) {
this.#headers[name.toLowerCase()] = value;
if (header.value.type === 'string') {
this.#headers[header.name.toLowerCase()] = header.value.value;
}
}
}

View File

@ -39,10 +39,9 @@ export class HTTPResponse extends BaseHTTPResponse {
constructor(
request: HTTPRequest,
responseEvent: Bidi.Network.ResponseCompletedParams
{response}: Bidi.Network.ResponseCompletedParameters
) {
super();
const {response} = responseEvent;
this.#request = request;
this.#remoteAddress = {
@ -54,12 +53,16 @@ export class HTTPResponse extends BaseHTTPResponse {
this.#fromCache = response.fromCache;
this.#status = response.status;
this.#statusText = response.statusText;
// TODO: update once BiDi has types
this.#timings = (response as any).timings ?? null;
// TODO: File and issue with BiDi spec
this.#timings = null;
// TODO: Removed once the Firefox implementation is compliant with https://w3c.github.io/webdriver-bidi/#get-the-response-data.
for (const header of response.headers || []) {
this.#headers[header.name] = header.value ?? '';
// TODO: How to handle Binary Headers
// https://w3c.github.io/webdriver-bidi/#type-network-Header
if (header.value.type === 'string') {
this.#headers[header.name.toLowerCase()] = header.value.value;
}
}
}

View File

@ -41,6 +41,23 @@ const enum InputId {
Finger = '__puppeteer_finger',
}
enum SourceActionsType {
None = 'none',
Key = 'key',
Pointer = 'pointer',
Wheel = 'wheel',
}
enum ActionType {
Pause = 'pause',
KeyDown = 'keyDown',
KeyUp = 'keyUp',
PointerUp = 'pointerUp',
PointerDown = 'pointerDown',
PointerMove = 'pointerMove',
Scroll = 'scroll',
}
const getBidiKeyValue = (key: KeyInput) => {
switch (key) {
case '\r':
@ -286,11 +303,11 @@ export class Keyboard extends BaseKeyboard {
context: this.#context.id,
actions: [
{
type: Bidi.Input.SourceActionsType.Key,
type: SourceActionsType.Key,
id: InputId.Keyboard,
actions: [
{
type: Bidi.Input.ActionType.KeyDown,
type: ActionType.KeyDown,
value: getBidiKeyValue(key),
},
],
@ -304,11 +321,11 @@ export class Keyboard extends BaseKeyboard {
context: this.#context.id,
actions: [
{
type: Bidi.Input.SourceActionsType.Key,
type: SourceActionsType.Key,
id: InputId.Keyboard,
actions: [
{
type: Bidi.Input.ActionType.KeyUp,
type: ActionType.KeyUp,
value: getBidiKeyValue(key),
},
],
@ -324,25 +341,25 @@ export class Keyboard extends BaseKeyboard {
const {delay = 0} = options;
const actions: Bidi.Input.KeySourceAction[] = [
{
type: Bidi.Input.ActionType.KeyDown,
type: ActionType.KeyDown,
value: getBidiKeyValue(key),
},
];
if (delay > 0) {
actions.push({
type: Bidi.Input.ActionType.Pause,
type: ActionType.Pause,
duration: delay,
});
}
actions.push({
type: Bidi.Input.ActionType.KeyUp,
type: ActionType.KeyUp,
value: getBidiKeyValue(key),
});
await this.#context.connection.send('input.performActions', {
context: this.#context.id,
actions: [
{
type: Bidi.Input.SourceActionsType.Key,
type: SourceActionsType.Key,
id: InputId.Keyboard,
actions,
},
@ -363,11 +380,11 @@ export class Keyboard extends BaseKeyboard {
for (const value of values) {
actions.push(
{
type: Bidi.Input.ActionType.KeyDown,
type: ActionType.KeyDown,
value,
},
{
type: Bidi.Input.ActionType.KeyUp,
type: ActionType.KeyUp,
value,
}
);
@ -376,15 +393,15 @@ export class Keyboard extends BaseKeyboard {
for (const value of values) {
actions.push(
{
type: Bidi.Input.ActionType.KeyDown,
type: ActionType.KeyDown,
value,
},
{
type: Bidi.Input.ActionType.Pause,
type: ActionType.Pause,
duration: delay,
},
{
type: Bidi.Input.ActionType.KeyUp,
type: ActionType.KeyUp,
value,
}
);
@ -394,7 +411,7 @@ export class Keyboard extends BaseKeyboard {
context: this.#context.id,
actions: [
{
type: Bidi.Input.SourceActionsType.Key,
type: SourceActionsType.Key,
id: InputId.Keyboard,
actions,
},
@ -474,11 +491,11 @@ export class Mouse extends BaseMouse {
context: this.#context.id,
actions: [
{
type: Bidi.Input.SourceActionsType.Pointer,
type: SourceActionsType.Pointer,
id: InputId.Mouse,
actions: [
{
type: Bidi.Input.ActionType.PointerMove,
type: ActionType.PointerMove,
x,
y,
duration: (options.steps ?? 0) * 50,
@ -495,11 +512,11 @@ export class Mouse extends BaseMouse {
context: this.#context.id,
actions: [
{
type: Bidi.Input.SourceActionsType.Pointer,
type: SourceActionsType.Pointer,
id: InputId.Mouse,
actions: [
{
type: Bidi.Input.ActionType.PointerDown,
type: ActionType.PointerDown,
button: getBidiButton(options.button ?? MouseButton.Left),
},
],
@ -513,11 +530,11 @@ export class Mouse extends BaseMouse {
context: this.#context.id,
actions: [
{
type: Bidi.Input.SourceActionsType.Pointer,
type: SourceActionsType.Pointer,
id: InputId.Mouse,
actions: [
{
type: Bidi.Input.ActionType.PointerUp,
type: ActionType.PointerUp,
button: getBidiButton(options.button ?? MouseButton.Left),
},
],
@ -533,18 +550,18 @@ export class Mouse extends BaseMouse {
): Promise<void> {
const actions: Bidi.Input.PointerSourceAction[] = [
{
type: Bidi.Input.ActionType.PointerMove,
type: ActionType.PointerMove,
x,
y,
origin: options.origin,
},
];
const pointerDownAction = {
type: Bidi.Input.ActionType.PointerDown,
type: ActionType.PointerDown,
button: getBidiButton(options.button ?? MouseButton.Left),
} as const;
const pointerUpAction = {
type: Bidi.Input.ActionType.PointerUp,
type: ActionType.PointerUp,
button: pointerDownAction.button,
} as const;
for (let i = 1; i < (options.count ?? 1); ++i) {
@ -553,7 +570,7 @@ export class Mouse extends BaseMouse {
actions.push(pointerDownAction);
if (options.delay) {
actions.push({
type: Bidi.Input.ActionType.Pause,
type: ActionType.Pause,
duration: options.delay,
});
}
@ -562,7 +579,7 @@ export class Mouse extends BaseMouse {
context: this.#context.id,
actions: [
{
type: Bidi.Input.SourceActionsType.Pointer,
type: SourceActionsType.Pointer,
id: InputId.Mouse,
actions,
},
@ -577,11 +594,11 @@ export class Mouse extends BaseMouse {
context: this.#context.id,
actions: [
{
type: Bidi.Input.SourceActionsType.Wheel,
type: SourceActionsType.Wheel,
id: InputId.Wheel,
actions: [
{
type: Bidi.Input.ActionType.Scroll,
type: ActionType.Scroll,
...(this.#lastMovePoint ?? {
x: 0,
y: 0,
@ -628,20 +645,20 @@ export class Touchscreen extends BaseTouchscreen {
context: this.#context.id,
actions: [
{
type: Bidi.Input.SourceActionsType.Pointer,
type: SourceActionsType.Pointer,
id: InputId.Finger,
parameters: {
pointerType: Bidi.Input.PointerType.Touch,
},
actions: [
{
type: Bidi.Input.ActionType.PointerMove,
type: ActionType.PointerMove,
x,
y,
origin: options.origin,
},
{
type: Bidi.Input.ActionType.PointerDown,
type: ActionType.PointerDown,
button: 0,
},
],
@ -659,14 +676,14 @@ export class Touchscreen extends BaseTouchscreen {
context: this.#context.id,
actions: [
{
type: Bidi.Input.SourceActionsType.Pointer,
type: SourceActionsType.Pointer,
id: InputId.Finger,
parameters: {
pointerType: Bidi.Input.PointerType.Touch,
},
actions: [
{
type: Bidi.Input.ActionType.PointerMove,
type: ActionType.PointerMove,
x,
y,
origin: options.origin,
@ -682,14 +699,14 @@ export class Touchscreen extends BaseTouchscreen {
context: this.#context.id,
actions: [
{
type: Bidi.Input.SourceActionsType.Pointer,
type: SourceActionsType.Pointer,
id: InputId.Finger,
parameters: {
pointerType: Bidi.Input.PointerType.Touch,
},
actions: [
{
type: Bidi.Input.ActionType.PointerUp,
type: ActionType.PointerUp,
button: 0,
},
],

View File

@ -28,9 +28,9 @@ import {releaseReference} from './utils.js';
export class JSHandle<T = unknown> extends BaseJSHandle<T> {
#disposed = false;
#realm: Realm;
#remoteValue;
#remoteValue: Bidi.Script.RemoteValue;
constructor(realm: Realm, remoteValue: Bidi.CommonDataTypes.RemoteValue) {
constructor(realm: Realm, remoteValue: Bidi.Script.RemoteValue) {
super();
this.#realm = realm;
this.#remoteValue = remoteValue;
@ -130,7 +130,10 @@ export class JSHandle<T = unknown> extends BaseJSHandle<T> {
}
this.#disposed = true;
if ('handle' in this.#remoteValue) {
await releaseReference(this.#realm, this.#remoteValue);
await releaseReference(
this.#realm,
this.#remoteValue as Bidi.Script.RemoteReference
);
}
}
@ -161,7 +164,7 @@ export class JSHandle<T = unknown> extends BaseJSHandle<T> {
return 'handle' in this.#remoteValue ? this.#remoteValue.handle : undefined;
}
remoteValue(): Bidi.CommonDataTypes.RemoteValue {
remoteValue(): Bidi.Script.RemoteValue {
return this.#remoteValue;
}
}

View File

@ -36,7 +36,7 @@ export class NetworkManager extends EventEmitter {
['network.responseStarted', this.#onResponseStarted.bind(this)],
['network.responseCompleted', this.#onResponseCompleted.bind(this)],
['network.fetchError', this.#onFetchError.bind(this)],
]) as Map<Bidi.Message.EventNames, Handler>;
]) as Map<Bidi.Event['method'], Handler>;
#requestMap = new Map<string, HTTPRequest>();
#navigationMap = new Map<string, HTTPResponse>();
@ -52,7 +52,7 @@ export class NetworkManager extends EventEmitter {
}
}
#onBeforeRequestSent(event: Bidi.Network.BeforeRequestSentParams): void {
#onBeforeRequestSent(event: Bidi.Network.BeforeRequestSentParameters): void {
const frame = this.#page.frame(event.context ?? '');
if (!frame) {
return;
@ -73,7 +73,7 @@ export class NetworkManager extends EventEmitter {
#onResponseStarted(_event: any) {}
#onResponseCompleted(event: Bidi.Network.ResponseCompletedParams): void {
#onResponseCompleted(event: Bidi.Network.ResponseCompletedParameters): void {
const request = this.#requestMap.get(event.request.request);
if (!request) {
return;
@ -91,7 +91,7 @@ export class NetworkManager extends EventEmitter {
this.#requestMap.delete(event.request.request);
}
#onFetchError(event: Bidi.Network.FetchErrorParams) {
#onFetchError(event: Bidi.Network.FetchErrorParameters) {
const request = this.#requestMap.get(event.request.request);
if (!request) {
return;

View File

@ -78,15 +78,18 @@ export class Page extends PageBase {
#networkManager: NetworkManager;
#viewport: Viewport | null = null;
#closedDeferred = Deferred.create<TargetCloseError>();
#subscribedEvents = new Map<string, Handler<any>>([
#subscribedEvents = new Map<Bidi.Event['method'], Handler<any>>([
['log.entryAdded', this.#onLogEntryAdded.bind(this)],
['browsingContext.load', this.#onFrameLoaded.bind(this)],
[
'browsingContext.domContentLoaded',
this.#onFrameDOMContentLoaded.bind(this),
],
['browsingContext.fragmentNavigated', this.#onFrameNavigated.bind(this)],
]) as Map<Bidi.Session.SubscriptionRequestEvent, Handler>;
[
'browsingContext.navigationStarted',
this.#onFrameNavigationStarted.bind(this),
],
]);
#networkManagerEvents = new Map<symbol, Handler<any>>([
[
NetworkManagerEmittedEvents.Request,
@ -252,19 +255,47 @@ export class Page extends PageBase {
context.parent
);
this.#frameTree.addFrame(frame);
this.emit(PageEmittedEvents.FrameAttached, frame);
if (frame !== this.mainFrame()) {
this.emit(PageEmittedEvents.FrameAttached, frame);
}
}
}
async #onFrameNavigated(
async #onFrameNavigationStarted(
info: Bidi.BrowsingContext.NavigationInfo
): Promise<void> {
const frameId = info.context;
let frame = this.frame(frameId);
// Detach all child frames first.
const frame = this.frame(frameId);
if (frame) {
frame = await this.#frameTree.waitForFrame(frameId);
// TODO: Investigate if a navigationCompleted event should be in Spec
const predicate = (
event: Bidi.BrowsingContext.DomContentLoaded['params']
) => {
if (event.context === frame?._id) {
return true;
}
return false;
};
await Deferred.race([
waitForEvent(
this.#connection,
'browsingContext.domContentLoaded',
predicate,
0,
this.#closedDeferred.valueOrThrow()
).catch(debugError),
waitForEvent(
this.#connection,
'browsingContext.fragmentNavigated',
predicate,
0,
this.#closedDeferred.valueOrThrow()
).catch(debugError),
]);
this.emit(PageEmittedEvents.FrameNavigated, frame);
}
}
@ -290,7 +321,7 @@ export class Page extends PageBase {
this.emit(PageEmittedEvents.FrameDetached, frame);
}
#onLogEntryAdded(event: Bidi.Log.LogEntry): void {
#onLogEntryAdded(event: Bidi.Log.Entry): void {
const frame = this.frame(event.source.context);
if (!frame) {
return;
@ -514,11 +545,12 @@ export class Page extends PageBase {
landscape,
width,
height,
pageRanges,
pageRanges: ranges,
scale,
preferCSSPageSize,
timeout,
} = this._getPDFOptions(options, 'cm');
const pageRanges = ranges ? ranges.split(', ') : [];
const {result} = await waitWithTimeout(
this.#connection.send('browsingContext.print', {
context: this.mainFrame()._id,
@ -529,7 +561,7 @@ export class Page extends PageBase {
width,
height,
},
pageRanges: pageRanges.split(', '),
pageRanges,
scale,
shrinkToFit: !preferCSSPageSize,
}),
@ -667,13 +699,13 @@ export class Page extends PageBase {
}
function isConsoleLogEntry(
event: Bidi.Log.LogEntry
event: Bidi.Log.Entry
): event is Bidi.Log.ConsoleLogEntry {
return event.type === 'console';
}
function isJavaScriptLogEntry(
event: Bidi.Log.LogEntry
event: Bidi.Log.Entry
): event is Bidi.Log.JavascriptLogEntry {
return event.type === 'javascript';
}

View File

@ -114,7 +114,9 @@ export class Realm extends EventEmitter {
);
let responsePromise;
const resultOwnership = returnByValue ? 'none' : 'root';
const resultOwnership = returnByValue
? Bidi.Script.ResultOwnership.None
: Bidi.Script.ResultOwnership.Root;
if (isString(pageFunction)) {
const expression = SOURCE_URL_REGEX.test(pageFunction)
? pageFunction
@ -161,7 +163,7 @@ export class Realm extends EventEmitter {
*/
export function getBidiHandle(
realmOrContext: Realm,
result: Bidi.CommonDataTypes.RemoteValue,
result: Bidi.Script.RemoteValue,
frame: Frame
): JSHandle | ElementHandle<Node> {
if (result.type === 'node' || result.type === 'window') {

View File

@ -32,8 +32,8 @@ class UnserializableError extends Error {}
* @internal
*/
export class BidiSerializer {
static serializeNumber(arg: number): Bidi.CommonDataTypes.LocalValue {
let value: Bidi.CommonDataTypes.SpecialNumber | number;
static serializeNumber(arg: number): Bidi.Script.LocalValue {
let value: Bidi.Script.SpecialNumber | number;
if (Object.is(arg, -0)) {
value = '-0';
} else if (Object.is(arg, Infinity)) {
@ -51,7 +51,7 @@ export class BidiSerializer {
};
}
static serializeObject(arg: object | null): Bidi.CommonDataTypes.LocalValue {
static serializeObject(arg: object | null): Bidi.Script.LocalValue {
if (arg === null) {
return {
type: 'null',
@ -78,7 +78,7 @@ export class BidiSerializer {
throw error;
}
const parsedObject: Bidi.CommonDataTypes.MappingLocalValue = [];
const parsedObject: Bidi.Script.MappingLocalValue = [];
for (const key in arg) {
parsedObject.push([
BidiSerializer.serializeRemoveValue(key),
@ -110,7 +110,7 @@ export class BidiSerializer {
);
}
static serializeRemoveValue(arg: unknown): Bidi.CommonDataTypes.LocalValue {
static serializeRemoveValue(arg: unknown): Bidi.Script.LocalValue {
switch (typeof arg) {
case 'symbol':
case 'function':
@ -145,9 +145,7 @@ export class BidiSerializer {
static async serialize(
arg: unknown,
context: BrowsingContext
): Promise<
Bidi.CommonDataTypes.LocalValue | Bidi.CommonDataTypes.RemoteValue
> {
): Promise<Bidi.Script.LocalValue> {
if (arg instanceof LazyArg) {
arg = await arg.get(context);
}
@ -167,15 +165,13 @@ export class BidiSerializer {
if (objectHandle.disposed) {
throw new Error('JSHandle is disposed!');
}
return objectHandle.remoteValue();
return objectHandle.remoteValue() as Bidi.Script.RemoteReference;
}
return BidiSerializer.serializeRemoveValue(arg);
}
static deserializeNumber(
value: Bidi.CommonDataTypes.SpecialNumber | number
): number {
static deserializeNumber(value: Bidi.Script.SpecialNumber | number): number {
switch (value) {
case '-0':
return -0;
@ -190,20 +186,22 @@ export class BidiSerializer {
}
}
static deserializeLocalValue(
result: Bidi.CommonDataTypes.RemoteValue
): unknown {
static deserializeLocalValue(result: Bidi.Script.RemoteValue): unknown {
switch (result.type) {
case 'array':
// TODO: Check expected output when value is undefined
return result.value?.map(value => {
return BidiSerializer.deserializeLocalValue(value);
});
if (result.value) {
return result.value.map(value => {
return BidiSerializer.deserializeLocalValue(value);
});
}
break;
case 'set':
// TODO: Check expected output when value is undefined
return result.value.reduce((acc: Set<unknown>, value) => {
return acc.add(BidiSerializer.deserializeLocalValue(value));
}, new Set());
if (result.value) {
return result.value.reduce((acc: Set<unknown>, value) => {
return acc.add(BidiSerializer.deserializeLocalValue(value));
}, new Set());
}
break;
case 'object':
if (result.value) {
return result.value.reduce((acc: Record<any, unknown>, tuple) => {
@ -213,12 +211,14 @@ export class BidiSerializer {
}, {});
}
break;
case 'map':
return result.value.reduce((acc: Map<unknown, unknown>, tuple) => {
const {key, value} = BidiSerializer.deserializeTuple(tuple);
return acc.set(key, value);
}, new Map());
if (result.value) {
return result.value?.reduce((acc: Map<unknown, unknown>, tuple) => {
const {key, value} = BidiSerializer.deserializeTuple(tuple);
return acc.set(key, value);
}, new Map());
}
break;
case 'promise':
return {};
case 'regexp':
@ -246,8 +246,8 @@ export class BidiSerializer {
}
static deserializeTuple([serializedKey, serializedValue]: [
Bidi.CommonDataTypes.RemoteValue | string,
Bidi.CommonDataTypes.RemoteValue,
Bidi.Script.RemoteValue | string,
Bidi.Script.RemoteValue,
]): {key: unknown; value: unknown} {
const key =
typeof serializedKey === 'string'
@ -258,7 +258,7 @@ export class BidiSerializer {
return {key, value};
}
static deserialize(result: Bidi.CommonDataTypes.RemoteValue): any {
static deserialize(result: Bidi.Script.RemoteValue): any {
if (!result) {
debugError('Service did not produce a result.');
return undefined;

View File

@ -31,7 +31,7 @@ export const debugError = debug('puppeteer:error');
*/
export async function releaseReference(
client: Realm,
remoteReference: Bidi.CommonDataTypes.RemoteReference
remoteReference: Bidi.Script.RemoteReference
): Promise<void> {
if (!remoteReference.handle) {
return;

View File

@ -394,19 +394,19 @@ export async function waitForEvent<T>(
deferred.resolve(event);
}
});
return Deferred.race<T | Error>([deferred, abortPromise]).then(
r => {
removeEventListeners([listener]);
if (isErrorLike(r)) {
throw r;
}
return r;
},
error => {
removeEventListeners([listener]);
throw error;
try {
const response = await Deferred.race<T | Error>([deferred, abortPromise]);
if (isErrorLike(response)) {
throw response;
}
);
return response;
} catch (error) {
throw error;
} finally {
removeEventListeners([listener]);
}
}
/**

View File

@ -1067,18 +1067,6 @@
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL", "PASS"]
},
{
"testIdPattern": "[network.spec] network raw network headers Same-origin set-cookie navigation",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[network.spec] network raw network headers Same-origin set-cookie subresource",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[network.spec] network Request.frame should work for subframe navigation request",
"platforms": ["darwin", "linux", "win32"],
@ -1169,12 +1157,6 @@
"parameters": ["cdp", "firefox"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[page.spec] Page Page.close should *not* run beforeunload by default",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[page.spec] Page Page.close should reject all promises when page is closed",
"platforms": ["darwin", "linux", "win32"],
@ -1907,6 +1889,18 @@
"parameters": ["cdp", "firefox"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.click should throw for hidden nodes",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.click should throw for recursively hidden nodes",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[emulation.spec] Emulation Page.emulate should support clicking",
"platforms": ["darwin", "linux", "win32"],
@ -2048,14 +2042,14 @@
{
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work right after framenavigated",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"]
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work right after framenavigated",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[fixtures.spec] Fixtures should close the browser when the node process closes",
@ -2115,7 +2109,7 @@
"testIdPattern": "[frame.spec] Frame specs Frame Management should support framesets",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"]
"expectations": ["FAIL", "PASS"]
},
{
"testIdPattern": "[frame.spec] Frame specs Frame Management should support lazy frames",
@ -2603,6 +2597,12 @@
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[navigation.spec] navigation Page.goto should navigate to dataURL and fire dataURL requests",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["FAIL", "PASS"]
},
{
"testIdPattern": "[navigation.spec] navigation Page.goto should navigate to empty page with domcontentloaded",
"platforms": ["darwin", "linux", "win32"],
@ -2641,9 +2641,9 @@
},
{
"testIdPattern": "[navigation.spec] navigation Page.goto should not leak listeners during navigation of 11 pages",
"platforms": ["darwin"],
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS", "TIMEOUT"]
"expectations": ["SKIP"]
},
{
"testIdPattern": "[navigation.spec] navigation Page.goto should return last response in redirect chain",
@ -2741,6 +2741,12 @@
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[navigation.spec] navigation Page.waitForNavigation should work when subframe issues window.stop()",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[navigation.spec] navigation Page.waitForNavigation should work with both domcontentloaded and load",
"platforms": ["darwin", "linux", "win32"],
@ -2873,6 +2879,30 @@
"parameters": ["cdp", "firefox"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[network.spec] network raw network headers Same-origin set-cookie navigation",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[network.spec] network raw network headers Same-origin set-cookie navigation",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[network.spec] network raw network headers Same-origin set-cookie subresource",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[network.spec] network raw network headers Same-origin set-cookie subresource",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[network.spec] network raw network headers Same-origin set-cookie subresource",
"platforms": ["darwin", "linux", "win32"],
@ -2889,7 +2919,7 @@
"testIdPattern": "[network.spec] network Request.headers should define Firefox as user agent header",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
"expectations": ["PASS"]
},
{
"testIdPattern": "[network.spec] network Request.initiator should return the initiator",
@ -2961,7 +2991,7 @@
"testIdPattern": "[network.spec] network Response.headers should work",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
"expectations": ["PASS"]
},
{
"testIdPattern": "[network.spec] network Response.json should work",

View File

@ -295,7 +295,7 @@ describe('ElementHandle specs', function () {
});
expect(error.message).atLeastOneToContain([
'Node is either not clickable or not an HTMLElement',
'no such node',
'no such element',
]);
});
it('should throw for recursively hidden nodes', async () => {
@ -311,7 +311,7 @@ describe('ElementHandle specs', function () {
});
expect(error.message).atLeastOneToContain([
'Node is either not clickable or not an HTMLElement',
'no such node',
'no such element',
]);
});
it('should throw for <br> elements', async () => {

View File

@ -213,6 +213,7 @@ describe('Frame specs', function () {
return navigatedFrames.push(frame);
});
await page.goto(server.PREFIX + '/frames/nested-frames.html');
expect(attachedFrames).toHaveLength(4);
expect(detachedFrames).toHaveLength(0);
expect(navigatedFrames).toHaveLength(5);

View File

@ -387,18 +387,21 @@ describe('Launcher specs', function () {
expect(puppeteer.product).toBe('firefox');
}
});
it('should work with no default arguments', async () => {
const {context, close} = await launch({
ignoreDefaultArgs: true,
});
try {
const page = await context.newPage();
expect(await page.evaluate('11 * 11')).toBe(121);
await page.close();
} finally {
await close();
(!isHeadless ? it : it.skip)(
'should work with no default arguments',
async () => {
const {context, close} = await launch({
ignoreDefaultArgs: true,
});
try {
const page = await context.newPage();
expect(await page.evaluate('11 * 11')).toBe(121);
await page.close();
} finally {
await close();
}
}
});
);
it('should filter out ignored default arguments in Chrome', async () => {
const {defaultBrowserOptions, puppeteer} = await getTestState({
skipLaunch: true,

View File

@ -145,7 +145,8 @@ export const setupTestBrowserHooks = (): void => {
timeout: this.timeout() - 1_000,
});
}
} catch {
} catch (error) {
console.error(error);
// Intentionally empty as `getTestState` will throw
// if browser is not found
}
@ -459,7 +460,7 @@ const closeLaunched = (storage: Array<() => Promise<void>>) => {
};
export const launch = async (
launchOptions: PuppeteerLaunchOptions,
launchOptions: Readonly<PuppeteerLaunchOptions>,
options: {
after?: 'each' | 'all';
createContext?: boolean;

View File

@ -704,7 +704,6 @@ describe('navigation', function () {
server.setRoute('/frames/style.css', () => {});
let frame: Frame | undefined;
let timeout: NodeJS.Timeout | undefined;
const eventPromises = Deferred.race([
Promise.all([
waitEvent(page, 'frameattached').then(_frame => {
@ -724,7 +723,6 @@ describe('navigation', function () {
);
try {
await eventPromises;
clearTimeout(timeout);
} catch (error) {
navigationPromise.catch(() => {});
throw error;

View File

@ -25,6 +25,7 @@ const FILENAME = __filename.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');
const parseStackTrace = (stack: string): string => {
stack = stack.replace(new RegExp(FILENAME, 'g'), '<filename>');
stack = stack.replace(/<filename>:(\d+):(\d+)/g, '<filename>:<line>:<col>');
stack = stack.replace(/<anonymous>:(\d+):(\d+)/g, '<anonymous>:<line>:<col>');
return stack;
};
@ -51,7 +52,7 @@ describe('Stack trace', function () {
).toMatchObject({
...[
'Error: Test',
'evaluate (evaluate at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:1:18)',
'evaluate (evaluate at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:<line>:<col>)',
],
});
});
@ -75,7 +76,7 @@ describe('Stack trace', function () {
).toMatchObject({
...[
'Error: Test',
'evaluateHandle (evaluateHandle at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:1:18)',
'evaluateHandle (evaluateHandle at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:<line>:<col>)',
],
});
});
@ -104,8 +105,8 @@ describe('Stack trace', function () {
).toMatchObject({
...[
'Error: Test',
'evaluateHandle (evaluateHandle at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:2:22)',
'evaluate (evaluate at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:1:12)',
'evaluateHandle (evaluateHandle at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:<line>:<col>)',
'evaluate (evaluate at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:<line>:<col>)',
],
});
});
@ -141,11 +142,11 @@ describe('Stack trace', function () {
).toMatchObject({
...[
'Error: Test',
'a (evaluate at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:2:22)',
'b (evaluate at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:5:16)',
'c (evaluate at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:8:16)',
'd (evaluate at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:11:16)',
'evaluate (evaluate at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:13:12)',
'a (evaluate at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:<line>:<col>)',
'b (evaluate at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:<line>:<col>)',
'c (evaluate at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:<line>:<col>)',
'd (evaluate at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:<line>:<col>)',
'evaluate (evaluate at Context.<anonymous> (<filename>:<line>:<col>), <anonymous>:<line>:<col>)',
],
});
});

View File

@ -167,9 +167,6 @@ export function getExpectationUpdates(
}
for (const failure of results.failures) {
if (passesByKey.has(getTestId(failure.file, failure.fullTitle))) {
continue;
}
// If an error occurs during a hook
// the error not have a file associated with it
if (!failure.file) {
@ -185,6 +182,10 @@ export function getExpectationUpdates(
continue;
}
if (passesByKey.has(getTestId(failure.file, failure.fullTitle))) {
continue;
}
const expectationEntry = findEffectiveExpectationForTest(
expectations,
failure