feat: allow converting other targets to pages (#11604)

This commit is contained in:
Alex Rudenko 2024-01-02 11:32:03 +01:00 committed by GitHub
parent 80143def96
commit 66aa770038
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 70 additions and 12 deletions

View File

@ -0,0 +1,19 @@
---
sidebar_label: Target.asPage
---
# Target.asPage() method
Forcefully creates a page for a target of any type. It is useful if you want to handle a CDP target of type `other` as a page. If you deal with a regular page target, use [Target.page()](./puppeteer.target.page.md).
#### Signature:
```typescript
class Target {
abstract asPage(): Promise<Page>;
}
```
**Returns:**
Promise&lt;[Page](./puppeteer.page.md)&gt;

View File

@ -18,13 +18,14 @@ The constructor for this class is marked as internal. Third-party code should no
## Methods
| Method | Modifiers | Description |
| ------------------------------------------------------------ | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [browser()](./puppeteer.target.browser.md) | | Get the browser the target belongs to. |
| [browserContext()](./puppeteer.target.browsercontext.md) | | Get the browser context the target belongs to. |
| [createCDPSession()](./puppeteer.target.createcdpsession.md) | | Creates a Chrome Devtools Protocol session attached to the target. |
| [opener()](./puppeteer.target.opener.md) | | Get the target that opened this target. Top-level targets return <code>null</code>. |
| [page()](./puppeteer.target.page.md) | | If the target is not of type <code>&quot;page&quot;</code>, <code>&quot;webview&quot;</code> or <code>&quot;background_page&quot;</code>, returns <code>null</code>. |
| [type()](./puppeteer.target.type.md) | | Identifies what kind of target this is. |
| [url()](./puppeteer.target.url.md) | | |
| [worker()](./puppeteer.target.worker.md) | | If the target is not of type <code>&quot;service_worker&quot;</code> or <code>&quot;shared_worker&quot;</code>, returns <code>null</code>. |
| Method | Modifiers | Description |
| ------------------------------------------------------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [asPage()](./puppeteer.target.aspage.md) | | Forcefully creates a page for a target of any type. It is useful if you want to handle a CDP target of type <code>other</code> as a page. If you deal with a regular page target, use [Target.page()](./puppeteer.target.page.md). |
| [browser()](./puppeteer.target.browser.md) | | Get the browser the target belongs to. |
| [browserContext()](./puppeteer.target.browsercontext.md) | | Get the browser context the target belongs to. |
| [createCDPSession()](./puppeteer.target.createcdpsession.md) | | Creates a Chrome Devtools Protocol session attached to the target. |
| [opener()](./puppeteer.target.opener.md) | | Get the target that opened this target. Top-level targets return <code>null</code>. |
| [page()](./puppeteer.target.page.md) | | If the target is not of type <code>&quot;page&quot;</code>, <code>&quot;webview&quot;</code> or <code>&quot;background_page&quot;</code>, returns <code>null</code>. |
| [type()](./puppeteer.target.type.md) | | Identifies what kind of target this is. |
| [url()](./puppeteer.target.url.md) | | |
| [worker()](./puppeteer.target.worker.md) | | If the target is not of type <code>&quot;service_worker&quot;</code> or <code>&quot;shared_worker&quot;</code>, returns <code>null</code>. |

View File

@ -65,6 +65,13 @@ export abstract class Target {
return null;
}
/**
* Forcefully creates a page for a target of any type. It is useful if you
* want to handle a CDP target of type `other` as a page. If you deal with a
* regular page target, use {@link Target.page}.
*/
abstract asPage(): Promise<Page>;
abstract url(): string;
/**

View File

@ -15,6 +15,7 @@
*/
import type {CDPSession} from '../api/CDPSession.js';
import type {Page} from '../api/Page.js';
import {Target, TargetType} from '../api/Target.js';
import {UnsupportedOperation} from '../common/Errors.js';
@ -38,8 +39,8 @@ export abstract class BidiTarget extends Target {
this._browserContext = browserContext;
}
override async worker(): Promise<null> {
return null;
override asPage(): Promise<Page> {
throw new UnsupportedOperation();
}
override browser(): BidiBrowser {

View File

@ -80,6 +80,16 @@ export class CdpTarget extends Target {
}
}
override async asPage(): Promise<Page> {
const session = this._session();
if (!session) {
return await this.createCDPSession().then(client => {
return CdpPage._create(client, this, false, null);
});
}
return await CdpPage._create(session, this, false, null);
}
_subtype(): string | undefined {
return this.#targetInfo.subtype;
}

View File

@ -187,6 +187,26 @@ const serviceWorkerExtensionPath = path.join(
).toBe(6);
expect(await browser.pages()).toContainEqual(page);
});
it('target.page() should return a DevTools page if asPage is used', async function () {
const {puppeteer} = await getTestState({skipLaunch: true});
const originalBrowser = await launchBrowser(devtoolsOptions);
const browserWSEndpoint = originalBrowser.wsEndpoint();
const browser = await puppeteer.connect({
browserWSEndpoint,
});
const devtoolsPageTarget = await browser.waitForTarget(target => {
return target.type() === 'other';
});
const page = (await devtoolsPageTarget.asPage())!;
expect(
await page.evaluate(() => {
return 2 * 3;
})
).toBe(6);
expect(await browser.pages()).toContainEqual(page);
});
it('should have default url when launching browser', async function () {
const browser = await launchBrowser(extensionOptions);
const pages = (await browser.pages()).map((page: {url: () => any}) => {