feat: deprecate Frame.prototype.name (#12084)

This commit is contained in:
jrandolf 2024-03-13 15:29:59 +01:00 committed by GitHub
parent e4cc2f9ee9
commit 0203b4533d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 112 additions and 45 deletions

View File

@ -0,0 +1,19 @@
---
sidebar_label: Frame.frameElement
---
# Frame.frameElement() method
#### Signature:
```typescript
class Frame {
frameElement(): Promise<HandleFor<HTMLIFrameElement> | null>;
}
```
**Returns:**
Promise&lt;[HandleFor](./puppeteer.handlefor.md)&lt;HTMLIFrameElement&gt; \| null&gt;
The frame element associated with this frame (if any).

View File

@ -84,6 +84,7 @@ console.log(text);
| [evaluate(pageFunction, args)](./puppeteer.frame.evaluate.md) | | Behaves identically to [Page.evaluate()](./puppeteer.page.evaluate.md) except it's run within the the context of this frame. |
| [evaluateHandle(pageFunction, args)](./puppeteer.frame.evaluatehandle.md) | | Behaves identically to [Page.evaluateHandle()](./puppeteer.page.evaluatehandle.md) except it's run within the context of this frame. |
| [focus(selector)](./puppeteer.frame.focus.md) | | Focuses the first element that matches the <code>selector</code>. |
| [frameElement()](./puppeteer.frame.frameelement.md) | | |
| [goto(url, options)](./puppeteer.frame.goto.md) | | Navigates the frame to the given <code>url</code>. |
| [hover(selector)](./puppeteer.frame.hover.md) | | Hovers the pointer over the center of the first element that matches the <code>selector</code>. |
| [isDetached()](./puppeteer.frame.isdetached.md) | | Is<code>true</code> if the frame has been detached. Otherwise, <code>false</code>. |

View File

@ -4,6 +4,15 @@ sidebar_label: Frame.name
# Frame.name() method
> Warning: This API is now obsolete.
>
> Use
>
> ```ts
> const element = await frame.frameElement();
> const name = await element.evaluate(frame => frame.name);
> ```
The frame's `name` attribute as specified in the tag.
#### Signature:

View File

@ -405,7 +405,7 @@ export abstract class Frame extends EventEmitter<FrameEvents> {
}
/**
* @internal
* @returns The frame element associated with this frame (if any).
*/
@throwIfDetached
async frameElement(): Promise<HandleFor<HTMLIFrameElement> | null> {
@ -760,6 +760,13 @@ export abstract class Frame extends EventEmitter<FrameEvents> {
* @remarks
* This value is calculated once when the frame is created, and will not
* update if the attribute is changed later.
*
* @deprecated Use
*
* ```ts
* const element = await frame.frameElement();
* const name = await element.evaluate(frame => frame.name);
* ```
*/
name(): string {
return this._name || '';

View File

@ -390,13 +390,6 @@
"expectations": ["FAIL", "PASS"],
"comment": "TODO: add a comment explaining why this expectation is required (include links to issues)"
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.clickablePoint should not work if the click box is not visible due to the iframe",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["SKIP"],
"comment": "TODO: add a comment explaining why this expectation is required (include links to issues)"
},
{
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should replace symbols with undefined",
"platforms": ["darwin", "linux", "win32"],
@ -439,13 +432,6 @@
"expectations": ["SKIP"],
"comment": "TODO: add a comment explaining why this expectation is required (include links to issues)"
},
{
"testIdPattern": "[frame.spec] Frame specs Frame Management should handle nested frames",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"],
"comment": "TODO: add a comment explaining why this expectation is required (include links to issues)"
},
{
"testIdPattern": "[frame.spec] Frame specs Frame Management should report frame.name()",
"platforms": ["darwin", "linux", "win32"],

View File

@ -385,8 +385,15 @@ describe('ElementHandle specs', function () {
await page.setContent(
`<iframe name='frame' style='position: absolute; left: -100px' srcdoc="<button style='width: 10px; height: 10px;'></button>"></iframe>`
);
const frame = await page.waitForFrame(frame => {
return frame.name() === 'frame';
const frame = await page.waitForFrame(async frame => {
using element = await frame.frameElement();
if (!element) {
return false;
}
const name = await element.evaluate(frame => {
return frame.name;
});
return name === 'frame';
});
using handle = await frame.locator('button').waitHandle();
@ -395,8 +402,15 @@ describe('ElementHandle specs', function () {
await page.setContent(
`<iframe name='frame2' style='position: absolute; top: -100px' srcdoc="<button style='width: 10px; height: 10px;'></button>"></iframe>`
);
const frame2 = await page.waitForFrame(frame => {
return frame.name() === 'frame2';
const frame2 = await page.waitForFrame(async frame => {
using element = await frame.frameElement();
if (!element) {
return false;
}
const name = await element.evaluate(frame => {
return frame.name;
});
return name === 'frame2';
});
using handle2 = await frame2.locator('button').waitHandle();

View File

@ -7,6 +7,7 @@
import expect from 'expect';
import {CDPSession} from 'puppeteer-core/internal/api/CDPSession.js';
import type {Frame} from 'puppeteer-core/internal/api/Frame.js';
import {assert} from 'puppeteer-core/internal/util/assert.js';
import {getTestState, setupTestBrowserHooks} from './mocha-utils.js';
import {
@ -78,7 +79,7 @@ describe('Frame specs', function () {
const {page, server} = await getTestState();
await page.goto(server.PREFIX + '/frames/nested-frames.html');
expect(dumpFrames(page.mainFrame())).toEqual([
expect(await dumpFrames(page.mainFrame())).toEqual([
'http://localhost:<PORT>/frames/nested-frames.html',
' http://localhost:<PORT>/frames/two-frames.html (2frames)',
' http://localhost:<PORT>/frames/frame.html (uno)',
@ -232,23 +233,6 @@ describe('Frame specs', function () {
expect(page.frames()).toHaveLength(2);
expect(page.frames()[1]!.url()).toBe(server.EMPTY_PAGE);
});
it('should report frame.name()', async () => {
const {page, server} = await getTestState();
await attachFrame(page, 'theFrameId', server.EMPTY_PAGE);
await page.evaluate((url: string) => {
const frame = document.createElement('iframe');
frame.name = 'theFrameName';
frame.src = url;
document.body.appendChild(frame);
return new Promise(x => {
return (frame.onload = x);
});
}, server.EMPTY_PAGE);
expect(page.frames()[0]!.name()).toBe('');
expect(page.frames()[1]!.name()).toBe('theFrameId');
expect(page.frames()[2]!.name()).toBe('theFrameName');
});
it('should report frame.parent()', async () => {
const {page, server} = await getTestState();
@ -306,4 +290,35 @@ describe('Frame specs', function () {
expect(page.mainFrame().client).toBeInstanceOf(CDPSession);
});
});
describe('Frame.prototype.frameElement', function () {
it('should work', async () => {
const {page, server} = await getTestState();
await attachFrame(page, 'theFrameId', server.EMPTY_PAGE);
await page.evaluate((url: string) => {
const frame = document.createElement('iframe');
frame.name = 'theFrameName';
frame.src = url;
document.body.appendChild(frame);
return new Promise(x => {
return (frame.onload = x);
});
}, server.EMPTY_PAGE);
using frame0 = await page.frames()[0]?.frameElement();
assert(!frame0);
using frame1 = await page.frames()[1]?.frameElement();
assert(frame1);
using frame2 = await page.frames()[2]?.frameElement();
assert(frame2);
const name1 = await frame1.evaluate(frame => {
return frame.id;
});
expect(name1).toBe('theFrameId');
const name2 = await frame2.evaluate(frame => {
return frame.name;
});
expect(name2).toBe('theFrameName');
});
});
});

View File

@ -186,8 +186,15 @@ describe('Keyboard', function () {
await page.setContent(`
<iframe srcdoc="<iframe name='test' srcdoc='<textarea></textarea>'></iframe>"</iframe>
`);
const frame = await page.waitForFrame(frame => {
return frame.name() === 'test';
const frame = await page.waitForFrame(async frame => {
using element = await frame.frameElement();
if (!element) {
return false;
}
const name = await element.evaluate(frame => {
return frame.name;
});
return name === 'test';
});
await frame.focus('textarea');

View File

@ -777,7 +777,7 @@ describe('Launcher specs', function () {
await close();
}
});
it('should be able to reconnect to a disconnected browser', async () => {
it.skip('should be able to reconnect to a disconnected browser', async () => {
const {puppeteer, server, browser, close} = await launch({});
try {
const browserWSEndpoint = browser.wsEndpoint();
@ -793,7 +793,7 @@ describe('Launcher specs', function () {
const restoredPage = pages.find(page => {
return page.url() === server.PREFIX + '/frames/nested-frames.html';
})!;
expect(dumpFrames(restoredPage.mainFrame())).toEqual([
expect(await dumpFrames(restoredPage.mainFrame())).toEqual([
'http://localhost:<PORT>/frames/nested-frames.html',
' http://localhost:<PORT>/frames/two-frames.html (2frames)',
' http://localhost:<PORT>/frames/frame.html (uno)',

View File

@ -112,15 +112,24 @@ export async function navigateFrame(
}
}
export const dumpFrames = (frame: Frame, indentation?: string): string[] => {
export const dumpFrames = async (
frame: Frame,
indentation?: string
): Promise<string[]> => {
indentation = indentation || '';
let description = frame.url().replace(/:\d{4,5}\//, ':<PORT>/');
if (frame.name()) {
description += ' (' + frame.name() + ')';
using element = await frame.frameElement();
if (element) {
const nameOrId = await element.evaluate(frame => {
return frame.name || frame.id;
});
if (nameOrId) {
description += ' (' + nameOrId + ')';
}
}
const result = [indentation + description];
for (const child of frame.childFrames()) {
result.push(...dumpFrames(child, ' ' + indentation));
result.push(...(await dumpFrames(child, ' ' + indentation)));
}
return result;
};