diff --git a/docs/api.md b/docs/api.md index 8d92d5b3cfb27..819648b1261f1 100644 --- a/docs/api.md +++ b/docs/api.md @@ -2092,6 +2092,7 @@ console.log(text); - [frame.innerText(selector[, options])](#frameinnertextselector-options) - [frame.isDetached()](#frameisdetached) - [frame.name()](#framename) +- [frame.page()](#framepage) - [frame.parentFrame()](#frameparentframe) - [frame.press(selector, key[, options])](#framepressselector-key-options) - [frame.selectOption(selector, values[, options])](#frameselectoptionselector-values-options) @@ -2458,6 +2459,11 @@ If the name is empty, returns the id attribute instead. > **NOTE** This value is calculated once when the frame is created, and will not update if the attribute is changed later. +#### frame.page() +- returns: <[Page]> + +Returns the page containing this frame. + #### frame.parentFrame() - returns: <[null]|[Frame]> Parent frame, if any. Detached frames and main frames return `null`. diff --git a/src/frames.ts b/src/frames.ts index 1d94cfc170183..fa5cdf3c585f6 100644 --- a/src/frames.ts +++ b/src/frames.ts @@ -374,6 +374,10 @@ export class Frame { this._parentFrame._childFrames.add(this); } + page(): Page { + return this._page; + } + private _apiName(method: string) { const subject = this._page._callingPageAPI ? 'page' : 'frame'; return `${subject}.${method}`; diff --git a/src/rpc/client/frame.ts b/src/rpc/client/frame.ts index 756fb0b947462..d1a00b5845d03 100644 --- a/src/rpc/client/frame.ts +++ b/src/rpc/client/frame.ts @@ -88,6 +88,10 @@ export class Frame extends ChannelOwner { return this._page!._isPageCall ? 'page.' + method : 'frame.' + method; } + page(): Page { + return this._page!; + } + async goto(url: string, options: FrameGotoOptions = {}): Promise { return this._wrapApiCall(this._apiName('goto'), async () => { const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil); diff --git a/test/frame-hierarchy.spec.ts b/test/frame-hierarchy.spec.ts index ea8b85b493f6b..5eda2cb38d22b 100644 --- a/test/frame-hierarchy.spec.ts +++ b/test/frame-hierarchy.spec.ts @@ -189,3 +189,9 @@ it.fail(FFOX)('should refuse to display x-frame-options:deny iframe', async({pag await page.setContent(``); expect(await refusalText).toMatch(/Refused to display 'http.*\/x-frame-options-deny\.html' in a frame because it set 'X-Frame-Options' to 'deny'./i) }); + +it('should return frame.page()', async({page, server}) => { + await page.goto(server.PREFIX + '/frames/one-frame.html'); + expect(page.mainFrame().page()).toBe(page); + expect(page.mainFrame().childFrames()[0].page()).toBe(page); +});