feat(api): introduce BrowserContext.waitForEvent (#1252)
This commit is contained in:
parent
8c9933e0f5
commit
9bc6dcea1d
17
docs/api.md
17
docs/api.md
|
|
@ -291,6 +291,7 @@ await context.close();
|
|||
- [browserContext.setGeolocation(geolocation)](#browsercontextsetgeolocationgeolocation)
|
||||
- [browserContext.setOffline(offline)](#browsercontextsetofflineoffline)
|
||||
- [browserContext.setPermissions(origin, permissions[])](#browsercontextsetpermissionsorigin-permissions)
|
||||
- [browserContext.waitForEvent(event[, optionsOrPredicate])](#browsercontextwaitforeventevent-optionsorpredicate)
|
||||
<!-- GEN:stop -->
|
||||
|
||||
#### event: 'close'
|
||||
|
|
@ -545,6 +546,15 @@ await browserContext.setGeolocation({latitude: 59.95, longitude: 30.31667});
|
|||
- `'payment-handler'`
|
||||
- returns: <[Promise]>
|
||||
|
||||
#### browserContext.waitForEvent(event[, optionsOrPredicate])
|
||||
- `event` <[string]> Event name, same one would pass into `browserContext.on(event)`.
|
||||
- `optionsOrPredicate` <[Function]|[Object]> Either a predicate that receives an event or an options object.
|
||||
- `predicate` <[Function]> receives the event data and resolves to truthy value when the waiting should resolve.
|
||||
- `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can be changed by using the [browserContext.setDefaultTimeout(timeout)](#browsercontextsetdefaulttimeouttimeout).
|
||||
- returns: <[Promise]<[any]>> Promise which resolves to the event data value.
|
||||
|
||||
Waits for event to fire and passes its value into the predicate function. Resolves when the predicate returns truthy value. Will throw an error if the context closes before the event
|
||||
is fired.
|
||||
|
||||
```js
|
||||
const context = await browser.newContext();
|
||||
|
|
@ -1611,13 +1621,11 @@ Shortcut for [page.mainFrame().waitFor(selectorOrFunctionOrTimeout[, options[, .
|
|||
- `event` <[string]> Event name, same one would pass into `page.on(event)`.
|
||||
- `optionsOrPredicate` <[Function]|[Object]> Either a predicate that receives an event or an options object.
|
||||
- `predicate` <[Function]> receives the event data and resolves to truthy value when the waiting should resolve.
|
||||
- `polling` <[number]|"raf"|"mutation"> An interval at which the `pageFunction` is executed, defaults to `raf`. If `polling` is a number, then it is treated as an interval in milliseconds at which the function would be executed. If `polling` is a string, then it can be one of the following values:
|
||||
- `'raf'` - to constantly execute `pageFunction` in `requestAnimationFrame` callback. This is the tightest polling mode which is suitable to observe styling changes.
|
||||
- `'mutation'` - to execute `pageFunction` on every DOM mutation.
|
||||
- `timeout` <[number]> maximum time to wait for in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value can be changed by using the [browserContext.setDefaultTimeout(timeout)](#browsercontextsetdefaulttimeouttimeout) or [page.setDefaultTimeout(timeout)](#pagesetdefaulttimeouttimeout) methods.
|
||||
- returns: <[Promise]<[any]>> Promise which resolves to the event data value.
|
||||
|
||||
Waits for event to fire and passes its value into the predicate function. Resolves when the predicate returns truthy value.
|
||||
Waits for event to fire and passes its value into the predicate function. Resolves when the predicate returns truthy value. Will throw an error if the page is closed before the event
|
||||
is fired.
|
||||
|
||||
#### page.waitForFunction(pageFunction[, options[, ...args]])
|
||||
- `pageFunction` <[function]|[string]> Function to be evaluated in browser context
|
||||
|
|
@ -3729,6 +3737,7 @@ const backgroundPage = await backroundPageTarget.page();
|
|||
- [browserContext.setGeolocation(geolocation)](#browsercontextsetgeolocationgeolocation)
|
||||
- [browserContext.setOffline(offline)](#browsercontextsetofflineoffline)
|
||||
- [browserContext.setPermissions(origin, permissions[])](#browsercontextsetpermissionsorigin-permissions)
|
||||
- [browserContext.waitForEvent(event[, optionsOrPredicate])](#browsercontextwaitforeventevent-optionsorpredicate)
|
||||
<!-- GEN:stop -->
|
||||
|
||||
#### event: 'backgroundpage'
|
||||
|
|
|
|||
|
|
@ -15,11 +15,13 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Page, PageBinding } from './page';
|
||||
import * as network from './network';
|
||||
import * as types from './types';
|
||||
import { helper } from './helper';
|
||||
import * as network from './network';
|
||||
import { Page, PageBinding } from './page';
|
||||
import * as platform from './platform';
|
||||
import { TimeoutSettings } from './timeoutSettings';
|
||||
import * as types from './types';
|
||||
import { Events } from './events';
|
||||
|
||||
export type BrowserContextOptions = {
|
||||
viewport?: types.Viewport | null,
|
||||
|
|
@ -50,15 +52,74 @@ export interface BrowserContext {
|
|||
setOffline(offline: boolean): Promise<void>;
|
||||
addInitScript(script: Function | string | { path?: string, content?: string }, ...args: any[]): Promise<void>;
|
||||
exposeFunction(name: string, playwrightFunction: Function): Promise<void>;
|
||||
waitForEvent(event: string, optionsOrPredicate?: Function | (types.TimeoutOptions & { predicate?: Function })): Promise<any>;
|
||||
close(): Promise<void>;
|
||||
|
||||
_existingPages(): Page[];
|
||||
readonly _timeoutSettings: TimeoutSettings;
|
||||
readonly _options: BrowserContextOptions;
|
||||
readonly _pageBindings: Map<string, PageBinding>;
|
||||
}
|
||||
|
||||
export function assertBrowserContextIsNotOwned(context: BrowserContext) {
|
||||
export abstract class BrowserContextBase extends platform.EventEmitter implements BrowserContext {
|
||||
readonly _timeoutSettings = new TimeoutSettings();
|
||||
readonly _pageBindings = new Map<string, PageBinding>();
|
||||
readonly _options: BrowserContextOptions;
|
||||
_closed = false;
|
||||
private readonly _closePromise: Promise<Error>;
|
||||
private _closePromiseFulfill: ((error: Error) => void) | undefined;
|
||||
|
||||
constructor(options: BrowserContextOptions) {
|
||||
super();
|
||||
this._options = options;
|
||||
this._closePromise = new Promise(fulfill => this._closePromiseFulfill = fulfill);
|
||||
}
|
||||
|
||||
abstract _existingPages(): Page[];
|
||||
|
||||
_browserClosed() {
|
||||
for (const page of this._existingPages())
|
||||
page._didClose();
|
||||
this._didCloseInternal();
|
||||
}
|
||||
|
||||
_didCloseInternal() {
|
||||
this._closed = true;
|
||||
this.emit(Events.BrowserContext.Close);
|
||||
this._closePromiseFulfill!(new Error('Context closed'));
|
||||
}
|
||||
|
||||
// BrowserContext methods.
|
||||
abstract pages(): Promise<Page[]>;
|
||||
abstract newPage(): Promise<Page>;
|
||||
abstract cookies(...urls: string[]): Promise<network.NetworkCookie[]>;
|
||||
abstract setCookies(cookies: network.SetNetworkCookieParam[]): Promise<void>;
|
||||
abstract clearCookies(): Promise<void>;
|
||||
abstract setPermissions(origin: string, permissions: string[]): Promise<void>;
|
||||
abstract clearPermissions(): Promise<void>;
|
||||
abstract setGeolocation(geolocation: types.Geolocation | null): Promise<void>;
|
||||
abstract setExtraHTTPHeaders(headers: network.Headers): Promise<void>;
|
||||
abstract setOffline(offline: boolean): Promise<void>;
|
||||
abstract addInitScript(script: string | Function | { path?: string | undefined; content?: string | undefined; }, ...args: any[]): Promise<void>;
|
||||
abstract exposeFunction(name: string, playwrightFunction: Function): Promise<void>;
|
||||
abstract close(): Promise<void>;
|
||||
|
||||
setDefaultNavigationTimeout(timeout: number) {
|
||||
this._timeoutSettings.setDefaultNavigationTimeout(timeout);
|
||||
}
|
||||
|
||||
setDefaultTimeout(timeout: number) {
|
||||
this._timeoutSettings.setDefaultTimeout(timeout);
|
||||
}
|
||||
|
||||
async waitForEvent(event: string, optionsOrPredicate?: Function | (types.TimeoutOptions & { predicate?: Function })): Promise<any> {
|
||||
if (!optionsOrPredicate)
|
||||
optionsOrPredicate = {};
|
||||
if (typeof optionsOrPredicate === 'function')
|
||||
optionsOrPredicate = { predicate: optionsOrPredicate };
|
||||
const { timeout = this._timeoutSettings.timeout(), predicate = () => true } = optionsOrPredicate;
|
||||
|
||||
const abortPromise = (event === Events.BrowserContext.Close) ? new Promise<Error>(() => { }) : this._closePromise;
|
||||
return helper.waitForEvent(this, event, (...args: any[]) => !!predicate(...args), timeout, abortPromise);
|
||||
}
|
||||
}
|
||||
|
||||
export function assertBrowserContextIsNotOwned(context: BrowserContextBase) {
|
||||
const pages = context._existingPages();
|
||||
for (const page of pages) {
|
||||
if (page._ownedContext)
|
||||
|
|
|
|||
|
|
@ -15,22 +15,21 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Events } from './events';
|
||||
import { Events as CommonEvents } from '../events';
|
||||
import { assert, helper, debugError } from '../helper';
|
||||
import { BrowserContext, BrowserContextOptions, validateBrowserContextOptions, assertBrowserContextIsNotOwned, verifyGeolocation } from '../browserContext';
|
||||
import { CRConnection, ConnectionEvents, CRSession } from './crConnection';
|
||||
import { Page, PageEvent, PageBinding } from '../page';
|
||||
import { CRTarget } from './crTarget';
|
||||
import { Protocol } from './protocol';
|
||||
import { CRPage } from './crPage';
|
||||
import { Browser, createPageInNewContext } from '../browser';
|
||||
import { assertBrowserContextIsNotOwned, BrowserContext, BrowserContextBase, BrowserContextOptions, validateBrowserContextOptions, verifyGeolocation } from '../browserContext';
|
||||
import { Events as CommonEvents } from '../events';
|
||||
import { assert, debugError, helper } from '../helper';
|
||||
import * as network from '../network';
|
||||
import * as types from '../types';
|
||||
import { Page, PageBinding, PageEvent } from '../page';
|
||||
import * as platform from '../platform';
|
||||
import { readProtocolStream } from './crProtocolHelper';
|
||||
import { ConnectionTransport, SlowMoTransport } from '../transport';
|
||||
import { TimeoutSettings } from '../timeoutSettings';
|
||||
import * as types from '../types';
|
||||
import { ConnectionEvents, CRConnection, CRSession } from './crConnection';
|
||||
import { CRPage } from './crPage';
|
||||
import { readProtocolStream } from './crProtocolHelper';
|
||||
import { CRTarget } from './crTarget';
|
||||
import { Events } from './events';
|
||||
import { Protocol } from './protocol';
|
||||
|
||||
export class CRBrowser extends platform.EventEmitter implements Browser {
|
||||
_connection: CRConnection;
|
||||
|
|
@ -226,21 +225,15 @@ export class CRBrowser extends platform.EventEmitter implements Browser {
|
|||
}
|
||||
}
|
||||
|
||||
export class CRBrowserContext extends platform.EventEmitter implements BrowserContext {
|
||||
export class CRBrowserContext extends BrowserContextBase {
|
||||
readonly _browser: CRBrowser;
|
||||
readonly _browserContextId: string | null;
|
||||
readonly _options: BrowserContextOptions;
|
||||
readonly _timeoutSettings: TimeoutSettings;
|
||||
readonly _evaluateOnNewDocumentSources: string[];
|
||||
readonly _pageBindings = new Map<string, PageBinding>();
|
||||
private _closed = false;
|
||||
|
||||
constructor(browser: CRBrowser, browserContextId: string | null, options: BrowserContextOptions) {
|
||||
super();
|
||||
super(options);
|
||||
this._browser = browser;
|
||||
this._browserContextId = browserContextId;
|
||||
this._timeoutSettings = new TimeoutSettings();
|
||||
this._options = options;
|
||||
this._evaluateOnNewDocumentSources = [];
|
||||
}
|
||||
|
||||
|
|
@ -262,14 +255,6 @@ export class CRBrowserContext extends platform.EventEmitter implements BrowserCo
|
|||
return pages;
|
||||
}
|
||||
|
||||
setDefaultNavigationTimeout(timeout: number) {
|
||||
this._timeoutSettings.setDefaultNavigationTimeout(timeout);
|
||||
}
|
||||
|
||||
setDefaultTimeout(timeout: number) {
|
||||
this._timeoutSettings.setDefaultTimeout(timeout);
|
||||
}
|
||||
|
||||
async pages(): Promise<Page[]> {
|
||||
const targets = this._browser._allTargets().filter(target => target.context() === this && target.type() === 'page');
|
||||
const pages = await Promise.all(targets.map(target => target.pageOrError()));
|
||||
|
|
@ -385,8 +370,7 @@ export class CRBrowserContext extends platform.EventEmitter implements BrowserCo
|
|||
assert(this._browserContextId, 'Non-incognito profiles cannot be closed!');
|
||||
await this._browser._client.send('Target.disposeBrowserContext', { browserContextId: this._browserContextId });
|
||||
this._browser._contexts.delete(this._browserContextId);
|
||||
this._closed = true;
|
||||
this.emit(CommonEvents.BrowserContext.Close);
|
||||
this._didCloseInternal();
|
||||
}
|
||||
|
||||
async backgroundPages(): Promise<Page[]> {
|
||||
|
|
@ -398,11 +382,4 @@ export class CRBrowserContext extends platform.EventEmitter implements BrowserCo
|
|||
async createSession(page: Page): Promise<CRSession> {
|
||||
return CRTarget.fromPage(page).sessionFactory();
|
||||
}
|
||||
|
||||
_browserClosed() {
|
||||
this._closed = true;
|
||||
for (const page of this._existingPages())
|
||||
page._didClose();
|
||||
this.emit(CommonEvents.BrowserContext.Close);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ export class CRPage implements PageDelegate {
|
|||
this._client.send('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: true, flatten: true }),
|
||||
this._client.send('Emulation.setFocusEmulationEnabled', { enabled: true }),
|
||||
];
|
||||
const options = this._page.context()._options;
|
||||
const options = this._browserContext._options;
|
||||
if (options.bypassCSP)
|
||||
promises.push(this._client.send('Page.setBypassCSP', { enabled: true }));
|
||||
if (options.ignoreHTTPSErrors)
|
||||
|
|
@ -336,7 +336,7 @@ export class CRPage implements PageDelegate {
|
|||
|
||||
async updateExtraHTTPHeaders(): Promise<void> {
|
||||
const headers = network.mergeHeaders([
|
||||
this._page.context()._options.extraHTTPHeaders,
|
||||
this._browserContext._options.extraHTTPHeaders,
|
||||
this._page._state.extraHTTPHeaders
|
||||
]);
|
||||
await this._client.send('Network.setExtraHTTPHeaders', { headers });
|
||||
|
|
@ -348,7 +348,7 @@ export class CRPage implements PageDelegate {
|
|||
}
|
||||
|
||||
async _updateViewport(updateTouch: boolean): Promise<void> {
|
||||
let viewport = this._page.context()._options.viewport || { width: 0, height: 0 };
|
||||
let viewport = this._browserContext._options.viewport || { width: 0, height: 0 };
|
||||
const viewportSize = this._page._state.viewportSize;
|
||||
if (viewportSize)
|
||||
viewport = { ...viewport, ...viewportSize };
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
|
|||
const frameId = await this._page._delegate.getOwnerFrame(this);
|
||||
if (!frameId)
|
||||
return null;
|
||||
const pages = this._page.context()._existingPages();
|
||||
const pages = this._page._browserContext._existingPages();
|
||||
for (const page of pages) {
|
||||
const frame = page._frameManager.frame(frameId);
|
||||
if (frame)
|
||||
|
|
|
|||
|
|
@ -16,19 +16,18 @@
|
|||
*/
|
||||
|
||||
import { Browser, createPageInNewContext } from '../browser';
|
||||
import { BrowserContext, BrowserContextOptions, validateBrowserContextOptions, assertBrowserContextIsNotOwned } from '../browserContext';
|
||||
import { assertBrowserContextIsNotOwned, BrowserContext, BrowserContextBase, BrowserContextOptions, validateBrowserContextOptions } from '../browserContext';
|
||||
import { Events } from '../events';
|
||||
import { assert, helper, RegisteredListener } from '../helper';
|
||||
import * as network from '../network';
|
||||
import * as types from '../types';
|
||||
import { Page, PageEvent, PageBinding } from '../page';
|
||||
import { ConnectionEvents, FFConnection, FFSessionEvents, FFSession } from './ffConnection';
|
||||
import { FFPage } from './ffPage';
|
||||
import { Page, PageBinding, PageEvent } from '../page';
|
||||
import * as platform from '../platform';
|
||||
import { Protocol } from './protocol';
|
||||
import { ConnectionTransport, SlowMoTransport } from '../transport';
|
||||
import { TimeoutSettings } from '../timeoutSettings';
|
||||
import * as types from '../types';
|
||||
import { ConnectionEvents, FFConnection, FFSession, FFSessionEvents } from './ffConnection';
|
||||
import { headersArray } from './ffNetworkManager';
|
||||
import { FFPage } from './ffPage';
|
||||
import { Protocol } from './protocol';
|
||||
|
||||
export class FFBrowser extends platform.EventEmitter implements Browser {
|
||||
_connection: FFConnection;
|
||||
|
|
@ -269,21 +268,15 @@ class Target {
|
|||
}
|
||||
}
|
||||
|
||||
export class FFBrowserContext extends platform.EventEmitter implements BrowserContext {
|
||||
export class FFBrowserContext extends BrowserContextBase {
|
||||
readonly _browser: FFBrowser;
|
||||
readonly _browserContextId: string | null;
|
||||
readonly _options: BrowserContextOptions;
|
||||
readonly _timeoutSettings: TimeoutSettings;
|
||||
private _closed = false;
|
||||
private readonly _evaluateOnNewDocumentSources: string[];
|
||||
readonly _pageBindings = new Map<string, PageBinding>();
|
||||
|
||||
constructor(browser: FFBrowser, browserContextId: string | null, options: BrowserContextOptions) {
|
||||
super();
|
||||
super(options);
|
||||
this._browser = browser;
|
||||
this._browserContextId = browserContextId;
|
||||
this._timeoutSettings = new TimeoutSettings();
|
||||
this._options = options;
|
||||
this._evaluateOnNewDocumentSources = [];
|
||||
}
|
||||
|
||||
|
|
@ -412,14 +405,6 @@ export class FFBrowserContext extends platform.EventEmitter implements BrowserCo
|
|||
assert(this._browserContextId, 'Non-incognito profiles cannot be closed!');
|
||||
await this._browser._connection.send('Target.removeBrowserContext', { browserContextId: this._browserContextId });
|
||||
this._browser._contexts.delete(this._browserContextId);
|
||||
this._closed = true;
|
||||
this.emit(Events.BrowserContext.Close);
|
||||
}
|
||||
|
||||
_browserClosed() {
|
||||
this._closed = true;
|
||||
for (const page of this._existingPages())
|
||||
page._didClose();
|
||||
this.emit(Events.BrowserContext.Close);
|
||||
this._didCloseInternal();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,22 +15,22 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as frames from '../frames';
|
||||
import { helper, RegisteredListener, debugError, assert } from '../helper';
|
||||
import * as dom from '../dom';
|
||||
import { FFSession } from './ffConnection';
|
||||
import { FFExecutionContext } from './ffExecutionContext';
|
||||
import { Page, PageDelegate, Worker, PageBinding } from '../page';
|
||||
import { FFNetworkManager, headersArray } from './ffNetworkManager';
|
||||
import { Events } from '../events';
|
||||
import * as dialog from '../dialog';
|
||||
import { Protocol } from './protocol';
|
||||
import { RawMouseImpl, RawKeyboardImpl } from './ffInput';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import { getAccessibilityTree } from './ffAccessibility';
|
||||
import * as types from '../types';
|
||||
import * as dom from '../dom';
|
||||
import { Events } from '../events';
|
||||
import * as frames from '../frames';
|
||||
import { assert, debugError, helper, RegisteredListener } from '../helper';
|
||||
import { Page, PageBinding, PageDelegate, Worker } from '../page';
|
||||
import * as platform from '../platform';
|
||||
import { kScreenshotDuringNavigationError } from '../screenshotter';
|
||||
import * as types from '../types';
|
||||
import { getAccessibilityTree } from './ffAccessibility';
|
||||
import { FFBrowserContext } from './ffBrowser';
|
||||
import { FFSession } from './ffConnection';
|
||||
import { FFExecutionContext } from './ffExecutionContext';
|
||||
import { RawKeyboardImpl, RawMouseImpl } from './ffInput';
|
||||
import { FFNetworkManager, headersArray } from './ffNetworkManager';
|
||||
import { Protocol } from './protocol';
|
||||
|
||||
const UTILITY_WORLD_NAME = '__playwright_utility_world__';
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ export class FFPage implements PageDelegate {
|
|||
private _eventListeners: RegisteredListener[];
|
||||
private _workers = new Map<string, { frameId: string, session: FFSession }>();
|
||||
|
||||
constructor(session: FFSession, browserContext: BrowserContext, openerResolver: () => Promise<Page | null>) {
|
||||
constructor(session: FFSession, browserContext: FFBrowserContext, openerResolver: () => Promise<Page | null>) {
|
||||
this._session = session;
|
||||
this._openerResolver = openerResolver;
|
||||
this.rawKeyboard = new RawKeyboardImpl(session);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import { Screenshotter } from './screenshotter';
|
|||
import { TimeoutSettings } from './timeoutSettings';
|
||||
import * as types from './types';
|
||||
import { Events } from './events';
|
||||
import { BrowserContext } from './browserContext';
|
||||
import { BrowserContext, BrowserContextBase } from './browserContext';
|
||||
import { ConsoleMessage, ConsoleMessageLocation } from './console';
|
||||
import * as accessibility from './accessibility';
|
||||
import * as platform from './platform';
|
||||
|
|
@ -113,7 +113,7 @@ export class Page extends platform.EventEmitter {
|
|||
private _disconnected = false;
|
||||
private _disconnectedCallback: (e: Error) => void;
|
||||
readonly _disconnectedPromise: Promise<Error>;
|
||||
private _browserContext: BrowserContext;
|
||||
readonly _browserContext: BrowserContextBase;
|
||||
readonly keyboard: input.Keyboard;
|
||||
readonly mouse: input.Mouse;
|
||||
readonly _timeoutSettings: TimeoutSettings;
|
||||
|
|
@ -129,7 +129,7 @@ export class Page extends platform.EventEmitter {
|
|||
readonly _requestHandlers: { url: types.URLMatch, handler: (request: network.Request) => void }[] = [];
|
||||
_ownedContext: BrowserContext | undefined;
|
||||
|
||||
constructor(delegate: PageDelegate, browserContext: BrowserContext) {
|
||||
constructor(delegate: PageDelegate, browserContext: BrowserContextBase) {
|
||||
super();
|
||||
this._delegate = delegate;
|
||||
this._closedCallback = () => {};
|
||||
|
|
@ -580,7 +580,7 @@ export class PageBinding {
|
|||
try {
|
||||
let binding = page._pageBindings.get(name);
|
||||
if (!binding)
|
||||
binding = page.context()._pageBindings.get(name);
|
||||
binding = page._browserContext._pageBindings.get(name);
|
||||
const result = await binding!.playwrightFunction(...args);
|
||||
expression = helper.evaluationString(deliverResult, name, seq, result);
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -16,19 +16,18 @@
|
|||
*/
|
||||
|
||||
import { Browser, createPageInNewContext } from '../browser';
|
||||
import { BrowserContext, BrowserContextOptions, validateBrowserContextOptions, assertBrowserContextIsNotOwned, verifyGeolocation } from '../browserContext';
|
||||
import { assertBrowserContextIsNotOwned, BrowserContext, BrowserContextBase, BrowserContextOptions, validateBrowserContextOptions, verifyGeolocation } from '../browserContext';
|
||||
import { Events } from '../events';
|
||||
import { assert, helper, RegisteredListener } from '../helper';
|
||||
import * as network from '../network';
|
||||
import { Page, PageBinding, PageEvent } from '../page';
|
||||
import * as platform from '../platform';
|
||||
import { ConnectionTransport, SlowMoTransport } from '../transport';
|
||||
import * as types from '../types';
|
||||
import { Events } from '../events';
|
||||
import { Protocol } from './protocol';
|
||||
import { WKConnection, WKSession, kPageProxyMessageReceived, PageProxyMessageReceivedPayload } from './wkConnection';
|
||||
import { WKPageProxy } from './wkPageProxy';
|
||||
import * as platform from '../platform';
|
||||
import { TimeoutSettings } from '../timeoutSettings';
|
||||
import { kPageProxyMessageReceived, PageProxyMessageReceivedPayload, WKConnection, WKSession } from './wkConnection';
|
||||
import { WKPage } from './wkPage';
|
||||
import { WKPageProxy } from './wkPageProxy';
|
||||
|
||||
const DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15';
|
||||
|
||||
|
|
@ -177,21 +176,15 @@ export class WKBrowser extends platform.EventEmitter implements Browser {
|
|||
}
|
||||
}
|
||||
|
||||
export class WKBrowserContext extends platform.EventEmitter implements BrowserContext {
|
||||
export class WKBrowserContext extends BrowserContextBase {
|
||||
readonly _browser: WKBrowser;
|
||||
readonly _browserContextId: string | undefined;
|
||||
readonly _options: BrowserContextOptions;
|
||||
readonly _timeoutSettings: TimeoutSettings;
|
||||
private _closed = false;
|
||||
readonly _evaluateOnNewDocumentSources: string[];
|
||||
readonly _pageBindings = new Map<string, PageBinding>();
|
||||
|
||||
constructor(browser: WKBrowser, browserContextId: string | undefined, options: BrowserContextOptions) {
|
||||
super();
|
||||
super(options);
|
||||
this._browser = browser;
|
||||
this._browserContextId = browserContextId;
|
||||
this._timeoutSettings = new TimeoutSettings();
|
||||
this._options = options;
|
||||
this._evaluateOnNewDocumentSources = [];
|
||||
}
|
||||
|
||||
|
|
@ -220,14 +213,6 @@ export class WKBrowserContext extends platform.EventEmitter implements BrowserCo
|
|||
return pages;
|
||||
}
|
||||
|
||||
setDefaultNavigationTimeout(timeout: number) {
|
||||
this._timeoutSettings.setDefaultNavigationTimeout(timeout);
|
||||
}
|
||||
|
||||
setDefaultTimeout(timeout: number) {
|
||||
this._timeoutSettings.setDefaultTimeout(timeout);
|
||||
}
|
||||
|
||||
async pages(): Promise<Page[]> {
|
||||
const pageProxies = Array.from(this._browser._pageProxies.values()).filter(proxy => proxy._browserContext === this);
|
||||
const pages = await Promise.all(pageProxies.map(proxy => proxy.pageOrError()));
|
||||
|
|
@ -327,14 +312,6 @@ export class WKBrowserContext extends platform.EventEmitter implements BrowserCo
|
|||
assert(this._browserContextId, 'Non-incognito profiles cannot be closed!');
|
||||
await this._browser._browserSession.send('Browser.deleteContext', { browserContextId: this._browserContextId });
|
||||
this._browser._contexts.delete(this._browserContextId);
|
||||
this._closed = true;
|
||||
this.emit(Events.BrowserContext.Close);
|
||||
}
|
||||
|
||||
_browserClosed() {
|
||||
this._closed = true;
|
||||
for (const page of this._existingPages())
|
||||
page._didClose();
|
||||
this.emit(Events.BrowserContext.Close);
|
||||
this._didCloseInternal();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ export class WKPage implements PageDelegate {
|
|||
this._pageProxySession.send('Emulation.setActiveAndFocused', { active: true }),
|
||||
this.authenticate(this._page._state.credentials)
|
||||
];
|
||||
const contextOptions = this._page.context()._options;
|
||||
const contextOptions = this._browserContext._options;
|
||||
if (contextOptions.javaScriptEnabled === false)
|
||||
promises.push(this._pageProxySession.send('Emulation.setJavaScriptEnabled', { enabled: false }));
|
||||
if (this._page._state.viewportSize || contextOptions.viewport)
|
||||
|
|
@ -130,7 +130,7 @@ export class WKPage implements PageDelegate {
|
|||
if (this._page._state.interceptNetwork)
|
||||
promises.push(session.send('Network.setInterceptionEnabled', { enabled: true, interceptRequests: true }));
|
||||
|
||||
const contextOptions = this._page.context()._options;
|
||||
const contextOptions = this._browserContext._options;
|
||||
if (contextOptions.userAgent)
|
||||
promises.push(session.send('Page.overrideUserAgent', { value: contextOptions.userAgent }));
|
||||
if (this._page._state.mediaType || this._page._state.colorScheme)
|
||||
|
|
@ -384,10 +384,10 @@ export class WKPage implements PageDelegate {
|
|||
|
||||
_calculateExtraHTTPHeaders(): network.Headers {
|
||||
const headers = network.mergeHeaders([
|
||||
this._page.context()._options.extraHTTPHeaders,
|
||||
this._browserContext._options.extraHTTPHeaders,
|
||||
this._page._state.extraHTTPHeaders
|
||||
]);
|
||||
const locale = this._page.context()._options.locale;
|
||||
const locale = this._browserContext._options.locale;
|
||||
if (locale)
|
||||
headers['Accept-Language'] = locale;
|
||||
return headers;
|
||||
|
|
@ -403,7 +403,7 @@ export class WKPage implements PageDelegate {
|
|||
}
|
||||
|
||||
async _updateViewport(updateTouch: boolean): Promise<void> {
|
||||
let viewport = this._page.context()._options.viewport || { width: 0, height: 0 };
|
||||
let viewport = this._browserContext._options.viewport || { width: 0, height: 0 };
|
||||
const viewportSize = this._page._state.viewportSize;
|
||||
if (viewportSize)
|
||||
viewport = { ...viewport, ...viewportSize };
|
||||
|
|
@ -425,7 +425,7 @@ export class WKPage implements PageDelegate {
|
|||
}
|
||||
|
||||
async updateOffline() {
|
||||
await this._updateState('Network.setEmulateOfflineState', { offline: !!this._page.context()._options.offline });
|
||||
await this._updateState('Network.setEmulateOfflineState', { offline: !!this._browserContext._options.offline });
|
||||
}
|
||||
|
||||
async authenticate(credentials: types.Credentials | null) {
|
||||
|
|
|
|||
|
|
@ -113,6 +113,13 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, FF
|
|||
const context = await browser.newContext();
|
||||
await context.close();
|
||||
});
|
||||
it('close() should abort waitForEvent', async({ browser }) => {
|
||||
const context = await browser.newContext();
|
||||
const promise = context.waitForEvent('page').catch(e => e);
|
||||
await context.close();
|
||||
let error = await promise;
|
||||
expect(error.message).toContain('Context closed');
|
||||
});
|
||||
});
|
||||
|
||||
describe('BrowserContext({userAgent})', function() {
|
||||
|
|
@ -389,7 +396,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, FF
|
|||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
const [otherPage] = await Promise.all([
|
||||
new Promise(r => context.once('page', async event => r(await event.page()))),
|
||||
context.waitForEvent('page').then(event => event.page()),
|
||||
page.evaluate(url => window.open(url), server.CROSS_PROCESS_PREFIX + '/empty.html').catch(e => console.log('eee = ' + e)),
|
||||
]);
|
||||
await otherPage.waitForLoadState();
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ module.exports.describe = function({testRunner, expect, playwright, FFOX, CHROMI
|
|||
describe('ChromiumBrowserContext', function() {
|
||||
it('should create a worker from a service worker', async({browser, page, server, context}) => {
|
||||
const [worker] = await Promise.all([
|
||||
new Promise(fulfill => context.once('serviceworker', fulfill)),
|
||||
context.waitForEvent('serviceworker'),
|
||||
page.goto(server.PREFIX + '/serviceworkers/empty/sw.html')
|
||||
]);
|
||||
expect(await worker.evaluate(() => self.toString())).toBe('[object ServiceWorkerGlobalScope]');
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
|
|||
const backgroundPages = await context.backgroundPages();
|
||||
let backgroundPage = backgroundPages.length
|
||||
? backgroundPages[0]
|
||||
: await new Promise(fulfill => context.once('backgroundpage', async event => fulfill(await event.page())));
|
||||
: await context.waitForEvent('backgroundpage').then(event => event.page());
|
||||
expect(backgroundPage).toBeTruthy();
|
||||
expect(await context.backgroundPages()).toContain(backgroundPage);
|
||||
expect(await context.pages()).not.toContain(backgroundPage);
|
||||
|
|
|
|||
|
|
@ -226,6 +226,14 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
|
|||
expect(message).not.toContain('Timeout');
|
||||
}
|
||||
});
|
||||
it('should fire close event for all contexts', async() => {
|
||||
const browser = await playwright.launch(defaultBrowserOptions);
|
||||
const context = await browser.newContext();
|
||||
let closed = false;
|
||||
context.on('close', () => closed = true);
|
||||
await browser.close();
|
||||
expect(closed).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Playwright.launch |webSocket| option', function() {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, WE
|
|||
await page.setContent('<a target=_blank rel=noopener href="/popup/popup.html">link</a>');
|
||||
const requestPromise = server.waitForRequest('/popup/popup.html');
|
||||
const [popup] = await Promise.all([
|
||||
new Promise(fulfill => context.once('page', async pageEvent => fulfill(await pageEvent.page()))),
|
||||
context.waitForEvent('page').then(pageEvent => pageEvent.page()),
|
||||
page.click('a'),
|
||||
]);
|
||||
await popup.waitForLoadState();
|
||||
|
|
|
|||
Loading…
Reference in a new issue