mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore: implement basic evaluate in BiDi (#8989)
Only the basic return values are supported. The follow-up PRs will re-use the shared code from the ExecutionContext and introduce Frame in BiDi.
This commit is contained in:
parent
692b48ab0e
commit
31e7b608d5
25
docs/api/puppeteer.page.addstyletag_2.md
Normal file
25
docs/api/puppeteer.page.addstyletag_2.md
Normal file
@ -0,0 +1,25 @@
|
||||
---
|
||||
sidebar_label: Page.addStyleTag_2
|
||||
---
|
||||
|
||||
# Page.addStyleTag() method
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
class Page {
|
||||
addStyleTag(
|
||||
options: FrameAddStyleTagOptions
|
||||
): Promise<ElementHandle<HTMLStyleElement | HTMLLinkElement>>;
|
||||
}
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ----------------------------------------------------------------- | ----------- |
|
||||
| options | [FrameAddStyleTagOptions](./puppeteer.frameaddstyletagoptions.md) | |
|
||||
|
||||
**Returns:**
|
||||
|
||||
Promise<[ElementHandle](./puppeteer.elementhandle.md)<HTMLStyleElement \| HTMLLinkElement>>
|
@ -84,6 +84,7 @@ page.off('request', logRequest);
|
||||
| [addScriptTag(options)](./puppeteer.page.addscripttag.md) | | Adds a <code><script></code> tag into the page with the desired URL or content. |
|
||||
| [addStyleTag(options)](./puppeteer.page.addstyletag.md) | | <p>Adds a <code><link rel="stylesheet"></code> tag into the page with the desired URL or a <code><style type="text/css"></code> tag with the content.</p><p>Shortcut for .</p> |
|
||||
| [addStyleTag(options)](./puppeteer.page.addstyletag_1.md) | | |
|
||||
| [addStyleTag(options)](./puppeteer.page.addstyletag_2.md) | | |
|
||||
| [authenticate(credentials)](./puppeteer.page.authenticate.md) | | Provide credentials for <code>HTTP authentication</code>. |
|
||||
| [bringToFront()](./puppeteer.page.bringtofront.md) | | Brings page to front (activates tab). |
|
||||
| [browser()](./puppeteer.page.browser.md) | | Get the browser the page belongs to. |
|
||||
|
@ -19,7 +19,7 @@
|
||||
import {ChildProcess} from 'child_process';
|
||||
import {Protocol} from 'devtools-protocol';
|
||||
import {EventEmitter} from '../common/EventEmitter.js';
|
||||
import type {Page} from '../common/Page.js'; // TODO: move to ./api
|
||||
import type {Page} from './Page.js'; // TODO: move to ./api
|
||||
import type {Target} from '../common/Target.js'; // TODO: move to ./api
|
||||
|
||||
/**
|
||||
|
2587
src/api/Page.ts
Normal file
2587
src/api/Page.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -19,7 +19,7 @@ import {Protocol} from 'devtools-protocol';
|
||||
import {assert} from '../util/assert.js';
|
||||
import {CDPSession, Connection, ConnectionEmittedEvents} from './Connection.js';
|
||||
import {waitWithTimeout} from './util.js';
|
||||
import {Page} from './Page.js';
|
||||
import {Page} from '../api/Page.js';
|
||||
import {Viewport} from './PuppeteerViewport.js';
|
||||
import {Target} from './Target.js';
|
||||
import {TaskQueue} from './TaskQueue.js';
|
||||
|
@ -29,11 +29,12 @@ import {
|
||||
Point,
|
||||
PressOptions,
|
||||
} from './JSHandle.js';
|
||||
import {Page, ScreenshotOptions} from './Page.js';
|
||||
import {Page, ScreenshotOptions} from '../api/Page.js';
|
||||
import {getQueryHandlerAndSelector} from './QueryHandler.js';
|
||||
import {EvaluateFunc, HandleFor, NodeFor} from './types.js';
|
||||
import {KeyInput} from './USKeyboardLayout.js';
|
||||
import {debugError, isString} from './util.js';
|
||||
import {CDPPage} from './Page.js';
|
||||
|
||||
const applyOffsetsToQuad = (
|
||||
quad: Point[],
|
||||
@ -510,7 +511,7 @@ export class ElementHandle<
|
||||
objectId: this.remoteObject().objectId,
|
||||
})
|
||||
.catch(debugError),
|
||||
this.#page._client().send('Page.getLayoutMetrics'),
|
||||
(this.#page as CDPPage)._client().send('Page.getLayoutMetrics'),
|
||||
]);
|
||||
if (!result || !result.quads.length) {
|
||||
throw new Error('Node is either not clickable or not an HTMLElement');
|
||||
|
@ -31,7 +31,7 @@ import {
|
||||
WaitForSelectorOptions,
|
||||
} from './IsolatedWorld.js';
|
||||
import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js';
|
||||
import {Page} from './Page.js';
|
||||
import {Page} from '../api/Page.js';
|
||||
import {getQueryHandlerAndSelector} from './QueryHandler.js';
|
||||
import {EvaluateFunc, HandleFor, NodeFor} from './types.js';
|
||||
import {importFS} from './util.js';
|
||||
|
@ -24,7 +24,7 @@ import {Frame} from './Frame.js';
|
||||
import {FrameTree} from './FrameTree.js';
|
||||
import {IsolatedWorld, MAIN_WORLD, PUPPETEER_WORLD} from './IsolatedWorld.js';
|
||||
import {NetworkManager} from './NetworkManager.js';
|
||||
import {Page} from './Page.js';
|
||||
import {Page} from '../api/Page.js';
|
||||
import {Target} from './Target.js';
|
||||
import {TimeoutSettings} from './TimeoutSettings.js';
|
||||
import {debugError} from './util.js';
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {Page, PageEmittedEvents} from './Page.js';
|
||||
import {Page, PageEmittedEvents} from '../api/Page.js';
|
||||
import {WebWorker} from './WebWorker.js';
|
||||
import {CDPSession} from './Connection.js';
|
||||
import type {
|
||||
@ -26,6 +26,7 @@ import {Viewport} from './PuppeteerViewport.js';
|
||||
import {Protocol} from 'devtools-protocol';
|
||||
import {TaskQueue} from './TaskQueue.js';
|
||||
import {TargetManager} from './TargetManager.js';
|
||||
import {CDPPage} from './Page.js';
|
||||
|
||||
/**
|
||||
* @public
|
||||
@ -163,7 +164,7 @@ export class Target {
|
||||
? Promise.resolve(this.#session)
|
||||
: this.#sessionFactory(true)
|
||||
).then(client => {
|
||||
return Page._create(
|
||||
return CDPPage._create(
|
||||
client,
|
||||
this,
|
||||
this.#ignoreHTTPSErrors,
|
||||
|
@ -1,9 +1,28 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import {
|
||||
Browser as BrowserBase,
|
||||
BrowserCloseCallback,
|
||||
BrowserContextOptions,
|
||||
BrowserContext as BrowserContextBase,
|
||||
} from '../../api/Browser.js';
|
||||
import {Connection} from './Connection.js';
|
||||
import {ChildProcess} from 'child_process';
|
||||
import {BrowserContext} from './BrowserContext.js';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -14,6 +33,7 @@ export class Browser extends BrowserBase {
|
||||
*/
|
||||
static async create(opts: Options): Promise<Browser> {
|
||||
// TODO: await until the connection is established.
|
||||
(await opts.connection.send('session.new', {})) as {sessionId: string};
|
||||
return new Browser(opts);
|
||||
}
|
||||
|
||||
@ -43,6 +63,12 @@ export class Browser extends BrowserBase {
|
||||
override process(): ChildProcess | null {
|
||||
return this.#process ?? null;
|
||||
}
|
||||
|
||||
override async createIncognitoBrowserContext(
|
||||
_options?: BrowserContextOptions
|
||||
): Promise<BrowserContextBase> {
|
||||
return new BrowserContext(this.#connection);
|
||||
}
|
||||
}
|
||||
|
||||
interface Options {
|
||||
|
41
src/common/bidi/BrowserContext.ts
Normal file
41
src/common/bidi/BrowserContext.ts
Normal file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import {BrowserContext as BrowserContextBase} from '../../api/Browser.js';
|
||||
import {Page as PageBase} from '../../api/Page.js';
|
||||
import {Connection} from './Connection.js';
|
||||
import {Page} from './Page.js';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class BrowserContext extends BrowserContextBase {
|
||||
#connection: Connection;
|
||||
|
||||
constructor(connection: Connection) {
|
||||
super();
|
||||
this.#connection = connection;
|
||||
}
|
||||
|
||||
override async newPage(): Promise<PageBase> {
|
||||
const result = (await this.#connection.send('browsingContext.create', {
|
||||
type: 'tab',
|
||||
})) as {context: string};
|
||||
return new Page(this.#connection, result.context);
|
||||
}
|
||||
|
||||
override async close(): Promise<void> {}
|
||||
}
|
@ -69,7 +69,7 @@ export class Connection extends EventEmitter {
|
||||
return this.#closed;
|
||||
}
|
||||
|
||||
send(method: string, params: object): Promise<any> {
|
||||
send(method: string, params: object): Promise<CommandResponse['result']> {
|
||||
const id = ++this.#lastId;
|
||||
const stringifiedMessage = JSON.stringify({
|
||||
id,
|
||||
|
56
src/common/bidi/Page.ts
Normal file
56
src/common/bidi/Page.ts
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import {Page as PageBase} from '../../api/Page.js';
|
||||
import {Connection} from './Connection.js';
|
||||
import type {EvaluateFunc} from '..//types.js';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class Page extends PageBase {
|
||||
#connection: Connection;
|
||||
#contextId: string;
|
||||
|
||||
constructor(connection: Connection, contextId: string) {
|
||||
super();
|
||||
this.#connection = connection;
|
||||
this.#contextId = contextId;
|
||||
}
|
||||
|
||||
override async close(): Promise<void> {
|
||||
await this.#connection.send('browsingContext.close', {
|
||||
context: this.#contextId,
|
||||
});
|
||||
}
|
||||
|
||||
override async evaluate<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
pageFunction: Func | string,
|
||||
..._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;
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
// AUTOGENERATED - Use `npm run generate:sources` to regenerate.
|
||||
|
||||
export * from './api/Browser.js';
|
||||
export * from './api/Page.js';
|
||||
export * from './common/Accessibility.js';
|
||||
export * from './common/AriaQueryHandler.js';
|
||||
export * from './common/Browser.js';
|
||||
|
@ -1960,5 +1960,35 @@
|
||||
"platforms": ["darwin", "win32", "linux"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work",
|
||||
"platforms": ["darwin", "win32", "linux"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work with function shorthands",
|
||||
"platforms": ["darwin", "win32", "linux"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work with unicode chars",
|
||||
"platforms": ["darwin", "win32", "linux"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work right after framenavigated",
|
||||
"platforms": ["darwin", "win32", "linux"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should work from-inside an exposed function",
|
||||
"platforms": ["darwin", "win32", "linux"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
}
|
||||
]
|
||||
|
@ -17,7 +17,7 @@
|
||||
import expect from 'expect';
|
||||
import {TLSSocket} from 'tls';
|
||||
import {Browser, BrowserContext} from '../../lib/cjs/puppeteer/api/Browser.js';
|
||||
import {Page} from '../../lib/cjs/puppeteer/common/Page.js';
|
||||
import {Page} from '../../lib/cjs/puppeteer/api/Page.js';
|
||||
import {HTTPResponse} from '../../lib/cjs/puppeteer/common/HTTPResponse.js';
|
||||
import {getTestState} from './mocha-utils.js';
|
||||
|
||||
|
@ -22,7 +22,7 @@ import rimraf from 'rimraf';
|
||||
import sinon from 'sinon';
|
||||
import {TLSSocket} from 'tls';
|
||||
import {promisify} from 'util';
|
||||
import {Page} from '../../lib/cjs/puppeteer/common/Page.js';
|
||||
import {Page} from '../../lib/cjs/puppeteer/api/Page.js';
|
||||
import {Product} from '../../lib/cjs/puppeteer/common/Product.js';
|
||||
import {getTestState, itOnlyRegularInstall} from './mocha-utils.js';
|
||||
import utils from './utils.js';
|
||||
|
@ -21,7 +21,7 @@ import * as path from 'path';
|
||||
import rimraf from 'rimraf';
|
||||
import sinon from 'sinon';
|
||||
import {Browser, BrowserContext} from '../../lib/cjs/puppeteer/api/Browser.js';
|
||||
import {Page} from '../../lib/cjs/puppeteer/common/Page.js';
|
||||
import {Page} from '../../lib/cjs/puppeteer/api/Page.js';
|
||||
import {isErrorLike} from '../../lib/cjs/puppeteer/util/ErrorLike.js';
|
||||
import {
|
||||
PuppeteerLaunchOptions,
|
||||
|
@ -18,7 +18,7 @@ import utils from './utils.js';
|
||||
import expect from 'expect';
|
||||
import {getTestState} from './mocha-utils.js';
|
||||
import {Browser, BrowserContext} from '../../lib/cjs/puppeteer/api/Browser.js';
|
||||
import {Page} from '../../lib/cjs/puppeteer/common/Page.js';
|
||||
import {Page} from '../../lib/cjs/puppeteer/api/Page.js';
|
||||
|
||||
describe('OOPIF', function () {
|
||||
/* We use a special browser for this test as we need the --site-per-process flag */
|
||||
|
@ -20,13 +20,14 @@ import path from 'path';
|
||||
import sinon from 'sinon';
|
||||
import {CDPSession} from '../../lib/cjs/puppeteer/common/Connection.js';
|
||||
import {ConsoleMessage} from '../../lib/cjs/puppeteer/common/ConsoleMessage.js';
|
||||
import {Metrics, Page} from '../../lib/cjs/puppeteer/common/Page.js';
|
||||
import {Metrics, Page} from '../../lib/cjs/puppeteer/api/Page.js';
|
||||
import {
|
||||
getTestState,
|
||||
setupTestBrowserHooks,
|
||||
setupTestPageAndContextHooks,
|
||||
} from './mocha-utils.js';
|
||||
import utils, {attachFrame, waitEvent} from './utils.js';
|
||||
import {CDPPage} from '../../lib/cjs/puppeteer/common/Page.js';
|
||||
|
||||
describe('Page', function () {
|
||||
setupTestBrowserHooks();
|
||||
@ -2317,7 +2318,7 @@ describe('Page', function () {
|
||||
describe('Page.client', function () {
|
||||
it('should return the client instance', async () => {
|
||||
const {page} = getTestState();
|
||||
expect(page._client()).toBeInstanceOf(CDPSession);
|
||||
expect((page as CDPPage)._client()).toBeInstanceOf(CDPSession);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
import expect from 'expect';
|
||||
import {ServerResponse} from 'http';
|
||||
import {Page} from '../../lib/cjs/puppeteer/common/Page.js';
|
||||
import {Page} from '../../lib/cjs/puppeteer/api/Page.js';
|
||||
import {Target} from '../../lib/cjs/puppeteer/common/Target.js';
|
||||
import {
|
||||
getTestState,
|
||||
|
@ -19,7 +19,7 @@ import path from 'path';
|
||||
import expect from 'expect';
|
||||
import {getTestState} from './mocha-utils.js';
|
||||
import {Browser} from '../../lib/cjs/puppeteer/api/Browser.js';
|
||||
import {Page} from '../../lib/cjs/puppeteer/common/Page.js';
|
||||
import {Page} from '../../lib/cjs/puppeteer/api/Page.js';
|
||||
|
||||
describe('Tracing', function () {
|
||||
let outputFile!: string;
|
||||
|
@ -17,7 +17,7 @@
|
||||
import expect from 'expect';
|
||||
import path from 'path';
|
||||
import {Frame} from '../../lib/cjs/puppeteer/common/Frame.js';
|
||||
import {Page} from '../../lib/cjs/puppeteer/common/Page.js';
|
||||
import {Page} from '../../lib/cjs/puppeteer/api/Page.js';
|
||||
import {EventEmitter} from '../../lib/cjs/puppeteer/common/EventEmitter.js';
|
||||
import {compare} from './golden-utils.js';
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user