mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore: Add BiDi Page.evaluate (#9609)
This commit is contained in:
parent
45b7197a73
commit
abcc1756dd
11
package-lock.json
generated
11
package-lock.json
generated
@ -40,7 +40,6 @@
|
||||
"@typescript-eslint/eslint-plugin": "5.46.1",
|
||||
"@typescript-eslint/parser": "5.46.1",
|
||||
"c8": "7.12.0",
|
||||
"chromium-bidi": "0.4.3",
|
||||
"commonmark": "0.30.0",
|
||||
"cross-env": "7.0.3",
|
||||
"diff": "5.1.0",
|
||||
@ -2663,7 +2662,6 @@
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.3.tgz",
|
||||
"integrity": "sha512-A40H1rdpJqkTdnGhnYDzMhtDdIbkXNFj2wgIfivMXL7LyHFDmBtv1hdyycDhnxtYunbPLDZtTs/n+ZT5j7Vnew==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"devtools-protocol": "*",
|
||||
"mitt": "*"
|
||||
@ -6036,8 +6034,7 @@
|
||||
"node_modules/mitt": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz",
|
||||
"integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ=="
|
||||
},
|
||||
"node_modules/mkdirp-classic": {
|
||||
"version": "0.5.3",
|
||||
@ -8677,6 +8674,7 @@
|
||||
"version": "19.6.3",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"chromium-bidi": "0.4.3",
|
||||
"cross-fetch": "3.1.5",
|
||||
"debug": "4.3.4",
|
||||
"devtools-protocol": "0.0.1082910",
|
||||
@ -11003,7 +11001,6 @@
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.3.tgz",
|
||||
"integrity": "sha512-A40H1rdpJqkTdnGhnYDzMhtDdIbkXNFj2wgIfivMXL7LyHFDmBtv1hdyycDhnxtYunbPLDZtTs/n+ZT5j7Vnew==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"cli-cursor": {
|
||||
@ -13404,8 +13401,7 @@
|
||||
"mitt": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz",
|
||||
"integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ=="
|
||||
},
|
||||
"mkdirp-classic": {
|
||||
"version": "0.5.3",
|
||||
@ -14106,6 +14102,7 @@
|
||||
"puppeteer-core": {
|
||||
"version": "file:packages/puppeteer-core",
|
||||
"requires": {
|
||||
"chromium-bidi": "0.4.3",
|
||||
"cross-fetch": "3.1.5",
|
||||
"debug": "4.3.4",
|
||||
"devtools-protocol": "0.0.1082910",
|
||||
|
@ -66,7 +66,6 @@
|
||||
"@typescript-eslint/eslint-plugin": "5.46.1",
|
||||
"@typescript-eslint/parser": "5.46.1",
|
||||
"c8": "7.12.0",
|
||||
"chromium-bidi": "0.4.3",
|
||||
"commonmark": "0.30.0",
|
||||
"cross-env": "7.0.3",
|
||||
"diff": "5.1.0",
|
||||
|
@ -163,6 +163,7 @@
|
||||
"author": "The Chromium Authors",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"chromium-bidi": "0.4.3",
|
||||
"cross-fetch": "3.1.5",
|
||||
"debug": "4.3.4",
|
||||
"devtools-protocol": "0.0.1082910",
|
||||
|
@ -26,6 +26,7 @@ import {
|
||||
createJSHandle,
|
||||
getExceptionMessage,
|
||||
isString,
|
||||
stringifyFunction,
|
||||
valueFromRemoteObject,
|
||||
} from './util.js';
|
||||
|
||||
@ -266,29 +267,11 @@ export class ExecutionContext {
|
||||
: createJSHandle(this, remoteObject);
|
||||
}
|
||||
|
||||
let functionText = pageFunction.toString();
|
||||
try {
|
||||
new Function('(' + functionText + ')');
|
||||
} catch (error) {
|
||||
// This means we might have a function shorthand. Try another
|
||||
// time prefixing 'function '.
|
||||
if (functionText.startsWith('async ')) {
|
||||
functionText =
|
||||
'async function ' + functionText.substring('async '.length);
|
||||
} else {
|
||||
functionText = 'function ' + functionText;
|
||||
}
|
||||
try {
|
||||
new Function('(' + functionText + ')');
|
||||
} catch (error) {
|
||||
// We tried hard to serialize, but there's a weird beast here.
|
||||
throw new Error('Passed function is not well-serializable!');
|
||||
}
|
||||
}
|
||||
let callFunctionOnPromise;
|
||||
try {
|
||||
callFunctionOnPromise = this._client.send('Runtime.callFunctionOn', {
|
||||
functionDeclaration: functionText + '\n' + suffix + '\n',
|
||||
functionDeclaration:
|
||||
stringifyFunction(pageFunction) + '\n' + suffix + '\n',
|
||||
executionContextId: this._contextId,
|
||||
arguments: await Promise.all(args.map(convertArgument.bind(this))),
|
||||
returnByValue,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import {CDPSession, Connection as CDPPPtrConnection} from '../Connection.js';
|
||||
import {Connection as BidiPPtrConnection} from './Connection.js';
|
||||
import {Bidi, BidiMapper} from '../../../third_party/chromium-bidi/index.js';
|
||||
import * as BidiMapper from 'chromium-bidi/lib/cjs/bidiMapper/bidiMapper.js';
|
||||
import * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
||||
import type {ProtocolMapping} from 'devtools-protocol/types/protocol-mapping.js';
|
||||
import {Handler} from '../EventEmitter.js';
|
||||
|
||||
|
@ -34,7 +34,10 @@ export class Browser extends BrowserBase {
|
||||
static async create(opts: Options): Promise<Browser> {
|
||||
// TODO: await until the connection is established.
|
||||
try {
|
||||
(await opts.connection.send('session.new', {})) as {sessionId: string};
|
||||
// TODO: Add 'session.new' to BiDi types
|
||||
(await opts.connection.send('session.new' as any, {})) as unknown as {
|
||||
sessionId: string;
|
||||
};
|
||||
} catch {}
|
||||
return new Browser(opts);
|
||||
}
|
||||
|
@ -31,10 +31,10 @@ export class BrowserContext extends BrowserContextBase {
|
||||
}
|
||||
|
||||
override async newPage(): Promise<PageBase> {
|
||||
const result = (await this.#connection.send('browsingContext.create', {
|
||||
const response = await this.#connection.send('browsingContext.create', {
|
||||
type: 'tab',
|
||||
})) as {context: string};
|
||||
return new Page(this.#connection, result.context);
|
||||
});
|
||||
return new Page(this.#connection, response.result.context);
|
||||
}
|
||||
|
||||
override async close(): Promise<void> {}
|
||||
|
@ -22,28 +22,32 @@ import {ConnectionTransport} from '../ConnectionTransport.js';
|
||||
import {EventEmitter} from '../EventEmitter.js';
|
||||
import {ProtocolError} from '../Errors.js';
|
||||
import {ConnectionCallback} from '../Connection.js';
|
||||
import * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
||||
|
||||
interface Command {
|
||||
id: number;
|
||||
method: string;
|
||||
params: object;
|
||||
}
|
||||
|
||||
interface CommandResponse {
|
||||
id: number;
|
||||
result: object;
|
||||
}
|
||||
|
||||
interface ErrorResponse {
|
||||
id: number;
|
||||
error: string;
|
||||
message: string;
|
||||
stacktrace?: string;
|
||||
}
|
||||
|
||||
interface Event {
|
||||
method: string;
|
||||
params: object;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
interface Commands {
|
||||
'script.evaluate': {
|
||||
params: Bidi.Script.EvaluateParameters;
|
||||
returnType: Bidi.Script.EvaluateResult;
|
||||
};
|
||||
'script.callFunction': {
|
||||
params: Bidi.Script.CallFunctionParameters;
|
||||
returnType: Bidi.Script.CallFunctionResult;
|
||||
};
|
||||
'browsingContext.create': {
|
||||
params: Bidi.BrowsingContext.CreateParameters;
|
||||
returnType: Bidi.BrowsingContext.CreateResult;
|
||||
};
|
||||
'browsingContext.close': {
|
||||
params: Bidi.BrowsingContext.CloseParameters;
|
||||
returnType: Bidi.BrowsingContext.CloseResult;
|
||||
};
|
||||
'session.status': {
|
||||
params: {context: string}; // TODO: Update Types in chromium bidi
|
||||
returnType: Bidi.Session.StatusResult;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,13 +73,16 @@ export class Connection extends EventEmitter {
|
||||
return this.#closed;
|
||||
}
|
||||
|
||||
send(method: string, params: object): Promise<CommandResponse['result']> {
|
||||
send<T extends keyof Commands>(
|
||||
method: T,
|
||||
params: Commands[T]['params']
|
||||
): Promise<Commands[T]['returnType']> {
|
||||
const id = ++this.#lastId;
|
||||
const stringifiedMessage = JSON.stringify({
|
||||
id,
|
||||
method,
|
||||
params,
|
||||
} as Command);
|
||||
} as Bidi.Message.CommandRequest);
|
||||
debugProtocolSend(stringifiedMessage);
|
||||
this.#transport.send(stringifiedMessage);
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -99,9 +106,8 @@ export class Connection extends EventEmitter {
|
||||
}
|
||||
debugProtocolReceive(message);
|
||||
const object = JSON.parse(message) as
|
||||
| Event
|
||||
| ErrorResponse
|
||||
| CommandResponse;
|
||||
| Bidi.Message.CommandResponse
|
||||
| Bidi.EventResponse<string, unknown>;
|
||||
if ('id' in object) {
|
||||
const callback = this.#callbacks.get(object.id);
|
||||
// Callbacks could be all rejected if someone has called `.dispose()`.
|
||||
@ -112,7 +118,7 @@ export class Connection extends EventEmitter {
|
||||
createProtocolError(callback.error, callback.method, object)
|
||||
);
|
||||
} else {
|
||||
callback.resolve(object.result);
|
||||
callback.resolve(object);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -154,10 +160,13 @@ function rewriteError(
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function createProtocolError(
|
||||
error: ProtocolError,
|
||||
method: string,
|
||||
object: ErrorResponse
|
||||
object: Bidi.Message.ErrorResult
|
||||
): Error {
|
||||
let message = `Protocol error (${method}): ${object.error} ${object.message}`;
|
||||
if (object.stacktrace) {
|
||||
|
@ -16,8 +16,9 @@
|
||||
|
||||
import {Page as PageBase} from '../../api/Page.js';
|
||||
import {Connection} from './Connection.js';
|
||||
import type {EvaluateFunc} from '..//types.js';
|
||||
|
||||
import type {EvaluateFunc} from '../types.js';
|
||||
import {isString, stringifyFunction} from '../util.js';
|
||||
import {BidiSerializer} from './Serializer.js';
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ -42,15 +43,32 @@ export class Page extends PageBase {
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
pageFunction: Func | string,
|
||||
..._args: Params
|
||||
...args: Params
|
||||
): Promise<Awaited<ReturnType<Func>>> {
|
||||
// TODO: re-use evaluate logic from Execution context.
|
||||
const str = `(${pageFunction.toString()})()`;
|
||||
const result = (await this.#connection.send('script.evaluate', {
|
||||
expression: str,
|
||||
target: {context: this.#contextId},
|
||||
awaitPromise: true,
|
||||
})) as {result: {type: string; value: any}};
|
||||
return result.result.value;
|
||||
let responsePromise;
|
||||
if (isString(pageFunction)) {
|
||||
responsePromise = this.#connection.send('script.evaluate', {
|
||||
expression: pageFunction,
|
||||
target: {context: this.#contextId},
|
||||
awaitPromise: true,
|
||||
});
|
||||
} else {
|
||||
responsePromise = this.#connection.send('script.callFunction', {
|
||||
functionDeclaration: stringifyFunction(pageFunction),
|
||||
arguments: await Promise.all(args.map(BidiSerializer.serialize)),
|
||||
target: {context: this.#contextId},
|
||||
awaitPromise: true,
|
||||
});
|
||||
}
|
||||
|
||||
const {result} = await responsePromise;
|
||||
|
||||
if ('type' in result && result.type === 'exception') {
|
||||
throw new Error(result.exceptionDetails.text);
|
||||
}
|
||||
|
||||
return BidiSerializer.deserialize(result.result) as Awaited<
|
||||
ReturnType<Func>
|
||||
>;
|
||||
}
|
||||
}
|
||||
|
203
packages/puppeteer-core/src/common/bidi/Serializer.ts
Normal file
203
packages/puppeteer-core/src/common/bidi/Serializer.ts
Normal file
@ -0,0 +1,203 @@
|
||||
import * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
||||
import {debugError, isPlainObject} from '../util.js';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class UnserializableError extends Error {}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class BidiSerializer {
|
||||
static serializeNumber(arg: number): Bidi.CommonDataTypes.LocalOrRemoteValue {
|
||||
let value: Bidi.CommonDataTypes.SpecialNumber | number;
|
||||
if (Object.is(arg, -0)) {
|
||||
value = '-0';
|
||||
} else if (Object.is(arg, Infinity)) {
|
||||
value = 'Infinity';
|
||||
} else if (Object.is(arg, -Infinity)) {
|
||||
value = '-Infinity';
|
||||
} else if (Object.is(arg, NaN)) {
|
||||
value = 'NaN';
|
||||
} else {
|
||||
value = arg;
|
||||
}
|
||||
return {
|
||||
type: 'number',
|
||||
value,
|
||||
};
|
||||
}
|
||||
|
||||
static serializeObject(
|
||||
arg: object | null
|
||||
): Bidi.CommonDataTypes.LocalOrRemoteValue {
|
||||
if (arg === null) {
|
||||
return {
|
||||
type: 'null',
|
||||
};
|
||||
} else if (Array.isArray(arg)) {
|
||||
const parsedArray = arg.map(subArg => {
|
||||
return BidiSerializer.serializeRemoveValue(subArg);
|
||||
});
|
||||
|
||||
return {
|
||||
type: 'array',
|
||||
value: parsedArray,
|
||||
};
|
||||
} else if (isPlainObject(arg)) {
|
||||
const parsedObject: Bidi.CommonDataTypes.MappingLocalValue = [];
|
||||
for (const key in arg) {
|
||||
parsedObject.push([
|
||||
BidiSerializer.serializeRemoveValue(key),
|
||||
BidiSerializer.serializeRemoveValue(arg[key]),
|
||||
]);
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'object',
|
||||
value: parsedObject,
|
||||
};
|
||||
}
|
||||
|
||||
throw new UnserializableError(
|
||||
'Custom object sterilization not possible. Use plain objects instead.'
|
||||
);
|
||||
}
|
||||
|
||||
static serializeRemoveValue(
|
||||
arg: unknown
|
||||
): Bidi.CommonDataTypes.LocalOrRemoteValue {
|
||||
switch (typeof arg) {
|
||||
case 'symbol':
|
||||
case 'function':
|
||||
throw new UnserializableError(`Unable to serializable ${typeof arg}`);
|
||||
case 'object':
|
||||
return BidiSerializer.serializeObject(arg);
|
||||
|
||||
case 'undefined':
|
||||
return {
|
||||
type: 'undefined',
|
||||
};
|
||||
case 'number':
|
||||
return BidiSerializer.serializeNumber(arg);
|
||||
case 'bigint':
|
||||
return {
|
||||
type: 'bigint',
|
||||
value: arg.toString(),
|
||||
};
|
||||
case 'string':
|
||||
return {
|
||||
type: 'string',
|
||||
value: arg,
|
||||
};
|
||||
case 'boolean':
|
||||
return {
|
||||
type: 'boolean',
|
||||
value: arg,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static serialize(arg: unknown): Bidi.CommonDataTypes.LocalOrRemoteValue {
|
||||
// TODO: See use case of LazyArgs
|
||||
return BidiSerializer.serializeRemoveValue(arg);
|
||||
}
|
||||
|
||||
static deserializeNumber(
|
||||
value: Bidi.CommonDataTypes.SpecialNumber | number
|
||||
): number {
|
||||
switch (value) {
|
||||
case '-0':
|
||||
return -0;
|
||||
case 'NaN':
|
||||
return NaN;
|
||||
case 'Infinity':
|
||||
case '+Infinity':
|
||||
return Infinity;
|
||||
case '-Infinity':
|
||||
return -Infinity;
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
static deserializeLocalValue(
|
||||
result: Bidi.CommonDataTypes.RemoteValue
|
||||
): unknown {
|
||||
switch (result.type) {
|
||||
case 'array':
|
||||
// TODO: Check expected output when value is undefined
|
||||
return result.value?.map(value => {
|
||||
return BidiSerializer.deserializeLocalValue(value);
|
||||
});
|
||||
case 'set':
|
||||
// TODO: Check expected output when value is undefined
|
||||
return result.value.reduce((acc: Set<unknown>, value: unknown) => {
|
||||
return acc.add(value);
|
||||
}, new Set());
|
||||
case 'object':
|
||||
if (result.value) {
|
||||
return result.value.reduce((acc: Record<any, unknown>, tuple) => {
|
||||
const {key, value} = BidiSerializer.deserializeTuple(tuple);
|
||||
acc[key as any] = value;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
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());
|
||||
case 'promise':
|
||||
return {};
|
||||
case 'undefined':
|
||||
return undefined;
|
||||
case 'null':
|
||||
return null;
|
||||
case 'number':
|
||||
return BidiSerializer.deserializeNumber(result.value);
|
||||
case 'bigint':
|
||||
return BigInt(result.value);
|
||||
case 'boolean':
|
||||
return Boolean(result.value);
|
||||
case 'string':
|
||||
return result.value;
|
||||
}
|
||||
|
||||
throw new UnserializableError(
|
||||
`Deserialization of type ${result.type} not supported.`
|
||||
);
|
||||
}
|
||||
|
||||
static deserializeTuple([serializedKey, serializedValue]: [
|
||||
Bidi.CommonDataTypes.RemoteValue | string,
|
||||
Bidi.CommonDataTypes.RemoteValue
|
||||
]): {key: unknown; value: unknown} {
|
||||
const key =
|
||||
typeof serializedKey === 'string'
|
||||
? serializedKey
|
||||
: BidiSerializer.deserializeLocalValue(serializedKey);
|
||||
const value = BidiSerializer.deserializeLocalValue(serializedValue);
|
||||
|
||||
return {key, value};
|
||||
}
|
||||
|
||||
static deserialize(result: Bidi.CommonDataTypes.RemoteValue): unknown {
|
||||
if (!result) {
|
||||
debugError('Service did not produce a result.');
|
||||
return undefined;
|
||||
}
|
||||
|
||||
try {
|
||||
return BidiSerializer.deserializeLocalValue(result);
|
||||
} catch (error) {
|
||||
if (error instanceof UnserializableError) {
|
||||
debugError(error.message);
|
||||
return undefined;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
@ -159,6 +159,13 @@ export const isNumber = (obj: unknown): obj is number => {
|
||||
return typeof obj === 'number' || obj instanceof Number;
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const isPlainObject = (obj: unknown): obj is Record<any, unknown> => {
|
||||
return typeof obj === 'object' && obj?.constructor === Object;
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ -440,3 +447,29 @@ export async function getReadableFromProtocolStream(
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export function stringifyFunction(expression: Function): string {
|
||||
let functionText = expression.toString();
|
||||
try {
|
||||
new Function('(' + functionText + ')');
|
||||
} catch (error) {
|
||||
// This means we might have a function shorthand. Try another
|
||||
// time prefixing 'function '.
|
||||
if (functionText.startsWith('async ')) {
|
||||
functionText =
|
||||
'async function ' + functionText.substring('async '.length);
|
||||
} else {
|
||||
functionText = 'function ' + functionText;
|
||||
}
|
||||
try {
|
||||
new Function('(' + functionText + ')');
|
||||
} catch (error) {
|
||||
// We tried hard to serialize, but there's a weird beast here.
|
||||
throw new Error('Passed function is not well-serializable!');
|
||||
}
|
||||
}
|
||||
return functionText;
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
/**
|
||||
* Copyright 2022 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * as BidiMapper from 'chromium-bidi/lib/cjs/bidiMapper/bidiMapper.js';
|
||||
export * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
@ -379,7 +379,7 @@
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should not throw an error when evaluation does a navigation",
|
||||
"platforms": ["darwin", "win32"],
|
||||
"platforms": ["darwin", "win32", "linux"],
|
||||
"parameters": ["firefox"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
@ -3174,9 +3174,111 @@
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work",
|
||||
"testIdPattern": "[evaluation.spec]",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should evaluate in the page context",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work right after framenavigated",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work from-inside an exposed function",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should be able to throw a tricky error",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should accept element handle as an argument",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should throw if underlying element was disposed",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should throw if elementHandles are from other frames",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should throw a nice error after a navigation",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should throw when evaluation triggers reload",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should simulate a user gesture",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should not throw an error when evaluation does a navigation",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should not throw an error when evaluation does a navigation",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluateOnNewDocument should evaluate before anything else on the page",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluateOnNewDocument should work with CSP",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Frame.evaluate should have different execution contexts",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Frame.evaluate should have correct execution contexts",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Frame.evaluate should execute after cross-site navigation",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
}
|
||||
]
|
||||
|
@ -51,7 +51,7 @@ describe('WebDriver BiDi', () => {
|
||||
JSON.stringify(rawResponse)
|
||||
);
|
||||
const response = await responsePromise;
|
||||
expect(response).toEqual(rawResponse.result);
|
||||
expect(response).toEqual(rawResponse);
|
||||
connection.dispose();
|
||||
expect(transport.closed).toBeTruthy();
|
||||
});
|
||||
|
@ -328,6 +328,20 @@ describe('Evaluation specs', function () {
|
||||
})
|
||||
).toBe(undefined);
|
||||
});
|
||||
it('should return promise as empty object', async () => {
|
||||
const {page} = getTestState();
|
||||
|
||||
const result = await page.evaluate(() => {
|
||||
return {
|
||||
promise: new Promise(resolve => {
|
||||
setTimeout(resolve, 1000);
|
||||
}),
|
||||
};
|
||||
});
|
||||
expect(result).toEqual({
|
||||
promise: {},
|
||||
});
|
||||
});
|
||||
it('should fail for circular object', async () => {
|
||||
const {page} = getTestState();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user