Skip to content

Commit

Permalink
feat(page): introduce "Popup" event (#3661)
Browse files Browse the repository at this point in the history
This patch adds a new "popup" event for page.
"Popup" event is fired whenever page opens another page with
given opener.
  • Loading branch information
aslushnikov committed Dec 13, 2018
1 parent c90392b commit 8aaca4e
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 1 deletion.
20 changes: 20 additions & 0 deletions docs/api.md
Expand Up @@ -79,6 +79,7 @@
* [event: 'load'](#event-load)
* [event: 'metrics'](#event-metrics)
* [event: 'pageerror'](#event-pageerror)
* [event: 'popup'](#event-popup)
* [event: 'request'](#event-request)
* [event: 'requestfailed'](#event-requestfailed)
* [event: 'requestfinished'](#event-requestfinished)
Expand Down Expand Up @@ -963,6 +964,25 @@ of metrics see `page.metrics`.

Emitted when an uncaught exception happens within the page.

#### event: 'popup'
- <[Page]> Page corresponding to "popup" window

Emitted when the page opens a new tab or window.

```js
const [popup] = await Promise.all([
new Promise(resolve => page.once('popup', resolve)),
page.click('a[target=_blank]'),
]);
```

```js
const [popup] = await Promise.all([
new Promise(resolve => page.once('popup', resolve)),
page.evaluate(() => window.open('https://example.com')),
]);
```

#### event: 'request'
- <[Request]>

Expand Down
1 change: 1 addition & 0 deletions lib/Page.js
Expand Up @@ -1192,6 +1192,7 @@ Page.Events = {
FrameNavigated: 'framenavigated',
Load: 'load',
Metrics: 'metrics',
Popup: 'popup',
WorkerCreated: 'workercreated',
WorkerDestroyed: 'workerdestroyed',
};
Expand Down
14 changes: 13 additions & 1 deletion lib/Target.js
Expand Up @@ -20,7 +20,19 @@ class Target {
this._screenshotTaskQueue = screenshotTaskQueue;
/** @type {?Promise<!Puppeteer.Page>} */
this._pagePromise = null;
this._initializedPromise = new Promise(fulfill => this._initializedCallback = fulfill);
this._initializedPromise = new Promise(fulfill => this._initializedCallback = fulfill).then(async success => {
if (!success)
return false;
const opener = this.opener();
if (!opener || !opener._pagePromise || this.type() !== 'page')
return true;
const openerPage = await opener._pagePromise;
if (!openerPage.listenerCount(Page.Events.Popup))
return true;
const popupPage = await this.page();
openerPage.emit(Page.Events.Popup, popupPage);
return true;
});
this._isClosedPromise = new Promise(fulfill => this._closedCallback = fulfill);
this._isInitialized = this._targetInfo.type !== 'page' || this._targetInfo.url !== '';
if (this._isInitialized)
Expand Down
49 changes: 49 additions & 0 deletions test/page.spec.js
Expand Up @@ -93,6 +93,55 @@ module.exports.addTests = function({testRunner, expect, headless}) {
});
});

describe('Page.Events.Popup', function() {
it('should work', async({page}) => {
const [popup] = await Promise.all([
new Promise(x => page.once('popup', x)),
page.evaluate(() => window.open('about:blank')),
]);
expect(await page.evaluate(() => !!window.opener)).toBe(false);
expect(await popup.evaluate(() => !!window.opener)).toBe(true);
});
it('should work with noopener', async({page}) => {
const [popup] = await Promise.all([
new Promise(x => page.once('popup', x)),
page.evaluate(() => window.open('about:blank', null, 'noopener')),
]);
expect(await page.evaluate(() => !!window.opener)).toBe(false);
expect(await popup.evaluate(() => !!window.opener)).toBe(false);
});
it('should work with clicking target=_blank', async({page, server}) => {
await page.goto(server.EMPTY_PAGE);
await page.setContent('<a target=_blank href="/one-style.html">yo</a>');
const [popup] = await Promise.all([
new Promise(x => page.once('popup', x)),
page.click('a'),
]);
expect(await page.evaluate(() => !!window.opener)).toBe(false);
expect(await popup.evaluate(() => !!window.opener)).toBe(true);
});
it('should work with fake-clicking target=_blank and rel=noopener', async({page, server}) => {
await page.goto(server.EMPTY_PAGE);
await page.setContent('<a target=_blank rel=noopener href="/one-style.html">yo</a>');
const [popup] = await Promise.all([
new Promise(x => page.once('popup', x)),
page.$eval('a', a => a.click()),
]);
expect(await page.evaluate(() => !!window.opener)).toBe(false);
expect(await popup.evaluate(() => !!window.opener)).toBe(false);
});
it('should work with clicking target=_blank and rel=noopener', async({page, server}) => {
await page.goto(server.EMPTY_PAGE);
await page.setContent('<a target=_blank rel=noopener href="/one-style.html">yo</a>');
const [popup] = await Promise.all([
new Promise(x => page.once('popup', x)),
page.click('a'),
]);
expect(await page.evaluate(() => !!window.opener)).toBe(false);
expect(await popup.evaluate(() => !!window.opener)).toBe(false);
});
});

describe('BrowserContext.overridePermissions', function() {
function getPermission(page, name) {
return page.evaluate(name => navigator.permissions.query({name}).then(result => result.state), name);
Expand Down

0 comments on commit 8aaca4e

Please sign in to comment.