diff --git a/docs/api.md b/docs/api.md
index 6f77b22c5b..9df72c0ced 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -614,6 +614,7 @@ page.removeListener('request', logRequest);
- [page.exposeFunction(name, playwrightFunction)](#pageexposefunctionname-playwrightfunction)
- [page.fill(selector, value[, options])](#pagefillselector-value-options)
- [page.focus(selector[, options])](#pagefocusselector-options)
+- [page.frame(options)](#pageframeoptions)
- [page.frames()](#pageframes)
- [page.goBack([options])](#pagegobackoptions)
- [page.goForward([options])](#pagegoforwardoptions)
@@ -1170,6 +1171,14 @@ If there's no element matching `selector`, the method throws an error.
Shortcut for [page.mainFrame().focus(selector)](#framefocusselector).
+#### page.frame(options)
+- `options` <[Object]>
+ - `name` <[string]> frame name specified in the `iframe`'s `name` attribute
+ - `url` <[string]|[RegExp]|[Function]> A glob pattern, regex pattern or predicate receiving frame's `url` as a [URL] object.
+- returns: <[Frame]> frame matching the criteria.
+
+Returns frame matching the specified criteria. Either `name` or `url` must be specified.
+
#### page.frames()
- returns: <[Array]<[Frame]>> An array of all frames attached to the page.
diff --git a/src/page.ts b/src/page.ts
index 8564948d3f..d56045e2ce 100644
--- a/src/page.ts
+++ b/src/page.ts
@@ -206,6 +206,15 @@ export class Page extends platform.EventEmitter {
return this._frameManager.mainFrame();
}
+ frame(options: { name?: string, url?: types.URLMatch }): frames.Frame | null {
+ assert(options.name || options.url, 'Either name or url matcher should be specified');
+ return this.frames().find(f => {
+ if (options.name)
+ return f.name() === options.name;
+ return platform.urlMatches(f.url(), options.url);
+ }) || null;
+ }
+
frames(): frames.Frame[] {
return this._frameManager.frames();
}
diff --git a/test/page.spec.js b/test/page.spec.js
index 4ebb48f32e..096832f539 100644
--- a/test/page.spec.js
+++ b/test/page.spec.js
@@ -1120,4 +1120,29 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF
expect(page.context()).toBe(context);
});
});
+
+ describe('Page.frame', function() {
+ it('should respect name', async function({page, server}) {
+ await page.setContent(`
+ empty.html
+
+ `);
+ expect(page.frame({ name: 'bogus' })).toBe(null);
+ const frame = page.frame({ name: 'target' });
+ expect(frame).toBeTruthy();
+ await Promise.all([
+ frame.waitForNavigation(),
+ page.click('a')
+ ]);
+ expect(frame.url()).toBe(server.EMPTY_PAGE);
+ });
+ it('should respect url', async function({page, server}) {
+ await page.setContent(`
+ empty.html target=target>empty.html
+
+ `);
+ expect(page.frame({ url: /bogus/ })).toBe(null);
+ expect(page.frame({ url: /empty/ }).url()).toBe(server.EMPTY_PAGE);
+ });
+ });
};