feat(ElementHandle): implement ElementHandle.contentFrame() (#2094)

This patch adds ElementHandle.contentFrame() method that allows
to get a reference to the Frame owned by the iframe.

Fixes #433.
This commit is contained in:
Andrey Lushnikov 2018-02-23 21:22:53 -08:00 committed by GitHub
parent e2b96df4d7
commit 223b59254c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 2 deletions

View File

@ -187,6 +187,7 @@
* [elementHandle.asElement()](#elementhandleaselement) * [elementHandle.asElement()](#elementhandleaselement)
* [elementHandle.boundingBox()](#elementhandleboundingbox) * [elementHandle.boundingBox()](#elementhandleboundingbox)
* [elementHandle.click([options])](#elementhandleclickoptions) * [elementHandle.click([options])](#elementhandleclickoptions)
* [elementHandle.contentFrame()](#elementhandlecontentframe)
* [elementHandle.dispose()](#elementhandledispose) * [elementHandle.dispose()](#elementhandledispose)
* [elementHandle.executionContext()](#elementhandleexecutioncontext) * [elementHandle.executionContext()](#elementhandleexecutioncontext)
* [elementHandle.focus()](#elementhandlefocus) * [elementHandle.focus()](#elementhandlefocus)
@ -2187,6 +2188,9 @@ This method returns the bounding box of the element (relative to the main frame)
This method scrolls element into view if needed, and then uses [page.mouse](#pagemouse) to click in the center of the element. This method scrolls element into view if needed, and then uses [page.mouse](#pagemouse) to click in the center of the element.
If the element is detached from DOM, the method throws an error. If the element is detached from DOM, the method throws an error.
#### elementHandle.contentFrame()
- returns: <[Promise]<?[Frame]>> Resolves to the content frame for element handles referencing iframe nodes, or null otherwise
#### elementHandle.dispose() #### elementHandle.dispose()
- returns: <[Promise]> Promise which resolves when the element handle is successfully disposed. - returns: <[Promise]> Promise which resolves when the element handle is successfully disposed.

View File

@ -23,12 +23,14 @@ class ElementHandle extends JSHandle {
* @param {!Puppeteer.CDPSession} client * @param {!Puppeteer.CDPSession} client
* @param {!Object} remoteObject * @param {!Object} remoteObject
* @param {!Puppeteer.Page} page * @param {!Puppeteer.Page} page
* @param {!Puppeteer.FrameManager} frameManager
*/ */
constructor(context, client, remoteObject, page) { constructor(context, client, remoteObject, page, frameManager) {
super(context, client, remoteObject); super(context, client, remoteObject);
this._client = client; this._client = client;
this._remoteObject = remoteObject; this._remoteObject = remoteObject;
this._page = page; this._page = page;
this._frameManager = frameManager;
this._disposed = false; this._disposed = false;
} }
@ -40,6 +42,18 @@ class ElementHandle extends JSHandle {
return this; return this;
} }
/**
* @return {!Promise<?Puppeteer.Frame>}
*/
async contentFrame() {
const nodeInfo = await this._client.send('DOM.describeNode', {
objectId: this._remoteObject.objectId
});
if (typeof nodeInfo.node.frameId !== 'string')
return null;
return this._frameManager.frame(nodeInfo.node.frameId);
}
async _scrollIntoViewIfNeeded() { async _scrollIntoViewIfNeeded() {
const error = await this.executionContext().evaluate(element => { const error = await this.executionContext().evaluate(element => {
if (!element.isConnected) if (!element.isConnected)

View File

@ -196,7 +196,7 @@ class FrameManager extends EventEmitter {
const context = this._contextIdToContext.get(contextId); const context = this._contextIdToContext.get(contextId);
console.assert(context, 'INTERNAL ERROR: missing context with id = ' + contextId); console.assert(context, 'INTERNAL ERROR: missing context with id = ' + contextId);
if (remoteObject.subtype === 'node') if (remoteObject.subtype === 'node')
return new ElementHandle(context, this._client, remoteObject, this._page); return new ElementHandle(context, this._client, remoteObject, this._page, this);
return new JSHandle(context, this._client, remoteObject); return new JSHandle(context, this._client, remoteObject);
} }

View File

@ -2039,6 +2039,16 @@ describe('Page', function() {
}); });
}); });
describe('ElementHandle.contentFrame', function() {
it('should work', async({page,server}) => {
await page.goto(server.EMPTY_PAGE);
await FrameUtils.attachFrame(page, 'frame1', server.EMPTY_PAGE);
const elementHandle = await page.$('#frame1');
const frame = await elementHandle.contentFrame();
expect(frame).toBe(page.frames()[1]);
});
});
describe('ElementHandle.click', function() { describe('ElementHandle.click', function() {
it('should work', async({page, server}) => { it('should work', async({page, server}) => {
await page.goto(server.PREFIX + '/input/button.html'); await page.goto(server.PREFIX + '/input/button.html');