Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@
* [elementHandle.asElement()](#elementhandleaselement)
* [elementHandle.boundingBox()](#elementhandleboundingbox)
* [elementHandle.click([options])](#elementhandleclickoptions)
* [elementHandle.contentFrame()](#elementhandlecontentframe)
* [elementHandle.dispose()](#elementhandledispose)
* [elementHandle.executionContext()](#elementhandleexecutioncontext)
* [elementHandle.focus()](#elementhandlefocus)
Expand Down Expand Up @@ -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.
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()
- returns: <[Promise]> Promise which resolves when the element handle is successfully disposed.

Expand Down
16 changes: 15 additions & 1 deletion lib/ElementHandle.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ class ElementHandle extends JSHandle {
* @param {!Puppeteer.CDPSession} client
* @param {!Object} remoteObject
* @param {!Puppeteer.Page} page
* @param {!Puppeteer.FrameManager} frameManager
*/
constructor(context, client, remoteObject, page) {
constructor(context, client, remoteObject, page, frameManager) {
super(context, client, remoteObject);
this._client = client;
this._remoteObject = remoteObject;
this._page = page;
this._frameManager = frameManager;
this._disposed = false;
}

Expand All @@ -40,6 +42,18 @@ class ElementHandle extends JSHandle {
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() {
const error = await this.executionContext().evaluate(element => {
if (!element.isConnected)
Expand Down
2 changes: 1 addition & 1 deletion lib/FrameManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ class FrameManager extends EventEmitter {
const context = this._contextIdToContext.get(contextId);
console.assert(context, 'INTERNAL ERROR: missing context with id = ' + contextId);
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);
}

Expand Down
10 changes: 10 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
it('should work', async({page, server}) => {
await page.goto(server.PREFIX + '/input/button.html');
Expand Down