Родитель
1489fbdbff
Коммит
25f2a32af3
|
@ -467,6 +467,7 @@ page.removeListener('request', logRequest);
|
|||
- [page.keyboard](#pagekeyboard)
|
||||
- [page.mainFrame()](#pagemainframe)
|
||||
- [page.mouse](#pagemouse)
|
||||
- [page.opener()](#pageopener)
|
||||
- [page.pdf([options])](#pagepdfoptions)
|
||||
- [page.reload([options])](#pagereloadoptions)
|
||||
- [page.screenshot([options])](#pagescreenshotoptions)
|
||||
|
@ -1098,6 +1099,10 @@ Page is guaranteed to have a main frame which persists during navigations.
|
|||
|
||||
- returns: <[Mouse]>
|
||||
|
||||
#### page.opener()
|
||||
|
||||
- returns: <[Promise]<?[Page]>> Promise which resolves to the opener for popup pages and `null` for others. If the opener has been closed already the promise may resolve to `null`.
|
||||
|
||||
#### page.pdf([options])
|
||||
- `options` <[Object]> Options object which might have the following properties:
|
||||
- `path` <[string]> The file path to save the PDF to. If `path` is a relative path, then it is resolved relative to [current working directory](https://nodejs.org/api/process.html#process_process_cwd). If no path is provided, the PDF won't be saved to the disk.
|
||||
|
|
|
@ -38,6 +38,7 @@ import { BrowserContext } from '../browserContext';
|
|||
import * as types from '../types';
|
||||
import { ConsoleMessage } from '../console';
|
||||
import * as platform from '../platform';
|
||||
import { CRTarget } from './crTarget';
|
||||
|
||||
const UTILITY_WORLD_NAME = '__playwright_utility_world__';
|
||||
|
||||
|
@ -349,6 +350,13 @@ export class CRPage implements PageDelegate {
|
|||
await this._client.send('Page.setInterceptFileChooserDialog', { enabled }).catch(e => {}); // target can be closed.
|
||||
}
|
||||
|
||||
async opener() : Promise<Page | null> {
|
||||
const openerTarget = CRTarget.fromPage(this._page).opener();
|
||||
if (!openerTarget)
|
||||
return null;
|
||||
return await openerTarget.page();
|
||||
}
|
||||
|
||||
async reload(): Promise<void> {
|
||||
await this._client.send('Page.reload');
|
||||
}
|
||||
|
|
|
@ -280,7 +280,12 @@ class Target {
|
|||
if (!this._pagePromise) {
|
||||
this._pagePromise = new Promise(async f => {
|
||||
const session = await this._connection.createSession(this._targetId);
|
||||
this._ffPage = new FFPage(session, this._context);
|
||||
this._ffPage = new FFPage(session, this._context, async () => {
|
||||
const openerTarget = this.opener();
|
||||
if (!openerTarget)
|
||||
return null;
|
||||
return await openerTarget.page();
|
||||
});
|
||||
const page = this._ffPage._page;
|
||||
session.once(FFSessionEvents.Disconnected, () => page._didDisconnect());
|
||||
await this._ffPage._initialize();
|
||||
|
|
|
@ -41,12 +41,14 @@ export class FFPage implements PageDelegate {
|
|||
readonly _session: FFSession;
|
||||
readonly _page: Page;
|
||||
readonly _networkManager: FFNetworkManager;
|
||||
private readonly _openerResolver: () => Promise<Page | null>;
|
||||
private readonly _contextIdToContext: Map<string, dom.FrameExecutionContext>;
|
||||
private _eventListeners: RegisteredListener[];
|
||||
private _workers = new Map<string, { frameId: string, session: FFSession }>();
|
||||
|
||||
constructor(session: FFSession, browserContext: BrowserContext) {
|
||||
constructor(session: FFSession, browserContext: BrowserContext, openerResolver: () => Promise<Page | null>) {
|
||||
this._session = session;
|
||||
this._openerResolver = openerResolver;
|
||||
this.rawKeyboard = new RawKeyboardImpl(session);
|
||||
this.rawMouse = new RawMouseImpl(session);
|
||||
this._contextIdToContext = new Map();
|
||||
|
@ -305,6 +307,10 @@ export class FFPage implements PageDelegate {
|
|||
await this._session.send('Page.setInterceptFileChooserDialog', { enabled }).catch(e => {}); // target can be closed.
|
||||
}
|
||||
|
||||
async opener() : Promise<Page | null> {
|
||||
return await this._openerResolver();
|
||||
}
|
||||
|
||||
async reload(): Promise<void> {
|
||||
await this._session.send('Page.reload', { frameId: this._page.mainFrame()._id });
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ export interface PageDelegate {
|
|||
readonly rawMouse: input.RawMouse;
|
||||
readonly rawKeyboard: input.RawKeyboard;
|
||||
|
||||
opener(): Promise<Page | null>;
|
||||
|
||||
reload(): Promise<void>;
|
||||
goBack(): Promise<boolean>;
|
||||
goForward(): Promise<boolean>;
|
||||
|
@ -173,6 +175,10 @@ export class Page extends platform.EventEmitter {
|
|||
return this._browserContext;
|
||||
}
|
||||
|
||||
async opener(): Promise<Page | null> {
|
||||
return await this._delegate.opener();
|
||||
}
|
||||
|
||||
mainFrame(): frames.Frame {
|
||||
return this._frameManager.mainFrame();
|
||||
}
|
||||
|
|
|
@ -113,7 +113,14 @@ export class WKBrowser extends platform.EventEmitter implements Browser {
|
|||
const pageProxySession = new WKSession(this._connection, pageProxyId, `The page has been closed.`, (message: any) => {
|
||||
this._connection.rawSend({ ...message, pageProxyId });
|
||||
});
|
||||
const pageProxy = new WKPageProxy(pageProxySession, context);
|
||||
const pageProxy = new WKPageProxy(pageProxySession, context, () => {
|
||||
if (!pageProxyInfo.openerId)
|
||||
return null;
|
||||
const opener = this._pageProxies.get(pageProxyInfo.openerId);
|
||||
if (!opener)
|
||||
return null;
|
||||
return opener;
|
||||
});
|
||||
this._pageProxies.set(pageProxyId, pageProxy);
|
||||
|
||||
if (pageProxyInfo.openerId) {
|
||||
|
|
|
@ -45,6 +45,7 @@ export class WKPage implements PageDelegate {
|
|||
private _provisionalPage: WKProvisionalPage | null = null;
|
||||
readonly _page: Page;
|
||||
private readonly _pageProxySession: WKSession;
|
||||
private readonly _openerResolver: () => Promise<Page | null>;
|
||||
private readonly _requestIdToRequest = new Map<string, WKInterceptableRequest>();
|
||||
private readonly _workers: WKWorkers;
|
||||
private readonly _contextIdToContext: Map<number, dom.FrameExecutionContext>;
|
||||
|
@ -52,8 +53,9 @@ export class WKPage implements PageDelegate {
|
|||
private _sessionListeners: RegisteredListener[] = [];
|
||||
private readonly _bootstrapScripts: string[] = [];
|
||||
|
||||
constructor(browserContext: BrowserContext, pageProxySession: WKSession) {
|
||||
constructor(browserContext: BrowserContext, pageProxySession: WKSession, openerResolver: () => Promise<Page | null>) {
|
||||
this._pageProxySession = pageProxySession;
|
||||
this._openerResolver = openerResolver;
|
||||
this.rawKeyboard = new RawKeyboardImpl(pageProxySession);
|
||||
this.rawMouse = new RawMouseImpl(pageProxySession);
|
||||
this._contextIdToContext = new Map();
|
||||
|
@ -415,6 +417,10 @@ export class WKPage implements PageDelegate {
|
|||
await this._session.send('Page.setInterceptFileChooserDialog', { enabled }).catch(e => {}); // target can be closed.
|
||||
}
|
||||
|
||||
async opener() {
|
||||
return await this._openerResolver();
|
||||
}
|
||||
|
||||
async reload(): Promise<void> {
|
||||
await this._session.send('Page.reload');
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ const isPovisionalSymbol = Symbol('isPovisional');
|
|||
export class WKPageProxy {
|
||||
private readonly _pageProxySession: WKSession;
|
||||
readonly _browserContext: BrowserContext;
|
||||
private readonly _openerResolver: () => WKPageProxy | null;
|
||||
private _pagePromise: Promise<Page> | null = null;
|
||||
private _wkPage: WKPage | null = null;
|
||||
private readonly _firstTargetPromise: Promise<void>;
|
||||
|
@ -36,9 +37,10 @@ export class WKPageProxy {
|
|||
private readonly _sessions = new Map<string, WKSession>();
|
||||
private readonly _eventListeners: RegisteredListener[];
|
||||
|
||||
constructor(pageProxySession: WKSession, browserContext: BrowserContext) {
|
||||
constructor(pageProxySession: WKSession, browserContext: BrowserContext, openerResolver: () => (WKPageProxy | null)) {
|
||||
this._pageProxySession = pageProxySession;
|
||||
this._browserContext = browserContext;
|
||||
this._openerResolver = openerResolver;
|
||||
this._firstTargetPromise = new Promise(r => this._firstTargetCallback = r);
|
||||
this._eventListeners = [
|
||||
helper.addEventListener(this._pageProxySession, 'Target.targetCreated', this._onTargetCreated.bind(this)),
|
||||
|
@ -111,7 +113,12 @@ export class WKPageProxy {
|
|||
}
|
||||
}
|
||||
assert(session, 'One non-provisional target session must exist');
|
||||
this._wkPage = new WKPage(this._browserContext, this._pageProxySession);
|
||||
this._wkPage = new WKPage(this._browserContext, this._pageProxySession, async () => {
|
||||
const pageProxy = this._openerResolver();
|
||||
if (!pageProxy)
|
||||
return null;
|
||||
return await pageProxy.page();
|
||||
});
|
||||
await this._wkPage.initialize(session!);
|
||||
if (this._pagePausedOnStart) {
|
||||
this._resumeTarget(session!.sessionId);
|
||||
|
|
|
@ -186,6 +186,26 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF
|
|||
});
|
||||
});
|
||||
|
||||
describe('Page.opener', function() {
|
||||
it('should provide access to the opener page', async({page}) => {
|
||||
const [popup] = await Promise.all([
|
||||
new Promise(x => page.once('popup', x)),
|
||||
page.evaluate(() => window.open('about:blank')),
|
||||
]);
|
||||
const opener = await popup.opener();
|
||||
expect(opener).toBe(page);
|
||||
});
|
||||
it('should return null if parent page has been closed', async({page}) => {
|
||||
const [popup] = await Promise.all([
|
||||
new Promise(x => page.once('popup', x)),
|
||||
page.evaluate(() => window.open('about:blank')),
|
||||
]);
|
||||
await page.close();
|
||||
const opener = await popup.opener();
|
||||
expect(opener).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Page.Events.Console', function() {
|
||||
it('should work', async({page, server}) => {
|
||||
let message = null;
|
||||
|
|
Загрузка…
Ссылка в новой задаче