feat(api): page.unroute to remove routes (#1813)
This commit is contained in:
parent
0426354451
commit
ba36860d79
17
docs/api.md
17
docs/api.md
|
|
@ -305,6 +305,7 @@ await context.close();
|
||||||
- [browserContext.setGeolocation(geolocation)](#browsercontextsetgeolocationgeolocation)
|
- [browserContext.setGeolocation(geolocation)](#browsercontextsetgeolocationgeolocation)
|
||||||
- [browserContext.setHTTPCredentials(httpCredentials)](#browsercontextsethttpcredentialshttpcredentials)
|
- [browserContext.setHTTPCredentials(httpCredentials)](#browsercontextsethttpcredentialshttpcredentials)
|
||||||
- [browserContext.setOffline(offline)](#browsercontextsetofflineoffline)
|
- [browserContext.setOffline(offline)](#browsercontextsetofflineoffline)
|
||||||
|
- [browserContext.unroute(url[, handler])](#browsercontextunrouteurl-handler)
|
||||||
- [browserContext.waitForEvent(event[, optionsOrPredicate])](#browsercontextwaitforeventevent-optionsorpredicate)
|
- [browserContext.waitForEvent(event[, optionsOrPredicate])](#browsercontextwaitforeventevent-optionsorpredicate)
|
||||||
<!-- GEN:stop -->
|
<!-- GEN:stop -->
|
||||||
|
|
||||||
|
|
@ -576,6 +577,13 @@ To disable authentication, pass `null`.
|
||||||
- `offline` <[boolean]> Whether to emulate network being offline for the browser context.
|
- `offline` <[boolean]> Whether to emulate network being offline for the browser context.
|
||||||
- returns: <[Promise]>
|
- returns: <[Promise]>
|
||||||
|
|
||||||
|
#### browserContext.unroute(url[, handler])
|
||||||
|
- `url` <[string]|[RegExp]|[function]\([string]\):[boolean]> A glob pattern, regex pattern or predicate receiving [URL] to match while routing.
|
||||||
|
- `handler` <[function]\([Route], [Request]\)> Handler function to route the request.
|
||||||
|
- returns: <[Promise]>
|
||||||
|
|
||||||
|
Removes a route created with [browserContext.route(url, handler)](#browsercontextrouteurl-handler). When `handler` is not specified, removes all routes for the `url`.
|
||||||
|
|
||||||
#### browserContext.waitForEvent(event[, optionsOrPredicate])
|
#### browserContext.waitForEvent(event[, optionsOrPredicate])
|
||||||
- `event` <[string]> Event name, same one would pass into `browserContext.on(event)`.
|
- `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.
|
- `optionsOrPredicate` <[Function]|[Object]> Either a predicate that receives an event or an options object.
|
||||||
|
|
@ -694,6 +702,7 @@ page.removeListener('request', logRequest);
|
||||||
- [page.title()](#pagetitle)
|
- [page.title()](#pagetitle)
|
||||||
- [page.type(selector, text[, options])](#pagetypeselector-text-options)
|
- [page.type(selector, text[, options])](#pagetypeselector-text-options)
|
||||||
- [page.uncheck(selector, [options])](#pageuncheckselector-options)
|
- [page.uncheck(selector, [options])](#pageuncheckselector-options)
|
||||||
|
- [page.unroute(url[, handler])](#pageunrouteurl-handler)
|
||||||
- [page.url()](#pageurl)
|
- [page.url()](#pageurl)
|
||||||
- [page.viewportSize()](#pageviewportsize)
|
- [page.viewportSize()](#pageviewportsize)
|
||||||
- [page.waitFor(selectorOrFunctionOrTimeout[, options[, arg]])](#pagewaitforselectororfunctionortimeout-options-arg)
|
- [page.waitFor(selectorOrFunctionOrTimeout[, options[, arg]])](#pagewaitforselectororfunctionortimeout-options-arg)
|
||||||
|
|
@ -1654,6 +1663,13 @@ If there's no element matching `selector`, the method throws an error.
|
||||||
|
|
||||||
Shortcut for [page.mainFrame().uncheck(selector[, options])](#frameuncheckselector-options).
|
Shortcut for [page.mainFrame().uncheck(selector[, options])](#frameuncheckselector-options).
|
||||||
|
|
||||||
|
#### page.unroute(url[, handler])
|
||||||
|
- `url` <[string]|[RegExp]|[function]\([string]\):[boolean]> A glob pattern, regex pattern or predicate receiving [URL] to match while routing.
|
||||||
|
- `handler` <[function]\([Route], [Request]\)> Handler function to route the request.
|
||||||
|
- returns: <[Promise]>
|
||||||
|
|
||||||
|
Removes a route created with [page.route(url, handler)](#pagerouteurl-handler). When `handler` is not specified, removes all routes for the `url`.
|
||||||
|
|
||||||
#### page.url()
|
#### page.url()
|
||||||
- returns: <[string]>
|
- returns: <[string]>
|
||||||
|
|
||||||
|
|
@ -3976,6 +3992,7 @@ const backgroundPage = await context.waitForEvent('backgroundpage');
|
||||||
- [browserContext.setGeolocation(geolocation)](#browsercontextsetgeolocationgeolocation)
|
- [browserContext.setGeolocation(geolocation)](#browsercontextsetgeolocationgeolocation)
|
||||||
- [browserContext.setHTTPCredentials(httpCredentials)](#browsercontextsethttpcredentialshttpcredentials)
|
- [browserContext.setHTTPCredentials(httpCredentials)](#browsercontextsethttpcredentialshttpcredentials)
|
||||||
- [browserContext.setOffline(offline)](#browsercontextsetofflineoffline)
|
- [browserContext.setOffline(offline)](#browsercontextsetofflineoffline)
|
||||||
|
- [browserContext.unroute(url[, handler])](#browsercontextunrouteurl-handler)
|
||||||
- [browserContext.waitForEvent(event[, optionsOrPredicate])](#browsercontextwaitforeventevent-optionsorpredicate)
|
- [browserContext.waitForEvent(event[, optionsOrPredicate])](#browsercontextwaitforeventevent-optionsorpredicate)
|
||||||
<!-- GEN:stop -->
|
<!-- GEN:stop -->
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ export interface BrowserContext {
|
||||||
addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any): Promise<void>;
|
addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any): Promise<void>;
|
||||||
exposeFunction(name: string, playwrightFunction: Function): Promise<void>;
|
exposeFunction(name: string, playwrightFunction: Function): Promise<void>;
|
||||||
route(url: types.URLMatch, handler: network.RouteHandler): Promise<void>;
|
route(url: types.URLMatch, handler: network.RouteHandler): Promise<void>;
|
||||||
|
unroute(url: types.URLMatch, handler?: network.RouteHandler): Promise<void>;
|
||||||
waitForEvent(event: string, optionsOrPredicate?: Function | (types.TimeoutOptions & { predicate?: Function })): Promise<any>;
|
waitForEvent(event: string, optionsOrPredicate?: Function | (types.TimeoutOptions & { predicate?: Function })): Promise<any>;
|
||||||
close(): Promise<void>;
|
close(): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +70,7 @@ export abstract class BrowserContextBase extends ExtendedEventEmitter implements
|
||||||
readonly _timeoutSettings = new TimeoutSettings();
|
readonly _timeoutSettings = new TimeoutSettings();
|
||||||
readonly _pageBindings = new Map<string, PageBinding>();
|
readonly _pageBindings = new Map<string, PageBinding>();
|
||||||
readonly _options: BrowserContextOptions;
|
readonly _options: BrowserContextOptions;
|
||||||
readonly _routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
|
_routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
|
||||||
_closed = false;
|
_closed = false;
|
||||||
private readonly _closePromise: Promise<Error>;
|
private readonly _closePromise: Promise<Error>;
|
||||||
private _closePromiseFulfill: ((error: Error) => void) | undefined;
|
private _closePromiseFulfill: ((error: Error) => void) | undefined;
|
||||||
|
|
@ -120,6 +121,7 @@ export abstract class BrowserContextBase extends ExtendedEventEmitter implements
|
||||||
abstract addInitScript(script: string | Function | { path?: string | undefined; content?: string | undefined; }, arg?: any): Promise<void>;
|
abstract addInitScript(script: string | Function | { path?: string | undefined; content?: string | undefined; }, arg?: any): Promise<void>;
|
||||||
abstract exposeFunction(name: string, playwrightFunction: Function): Promise<void>;
|
abstract exposeFunction(name: string, playwrightFunction: Function): Promise<void>;
|
||||||
abstract route(url: types.URLMatch, handler: network.RouteHandler): Promise<void>;
|
abstract route(url: types.URLMatch, handler: network.RouteHandler): Promise<void>;
|
||||||
|
abstract unroute(url: types.URLMatch, handler?: network.RouteHandler): Promise<void>;
|
||||||
abstract close(): Promise<void>;
|
abstract close(): Promise<void>;
|
||||||
|
|
||||||
async grantPermissions(permissions: string[], options?: { origin?: string }) {
|
async grantPermissions(permissions: string[], options?: { origin?: string }) {
|
||||||
|
|
|
||||||
|
|
@ -422,6 +422,12 @@ export class CRBrowserContext extends BrowserContextBase {
|
||||||
await (page._delegate as CRPage).updateRequestInterception();
|
await (page._delegate as CRPage).updateRequestInterception();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async unroute(url: types.URLMatch, handler?: network.RouteHandler): Promise<void> {
|
||||||
|
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
|
||||||
|
for (const page of this.pages())
|
||||||
|
await (page._delegate as CRPage).updateRequestInterception();
|
||||||
|
}
|
||||||
|
|
||||||
async close() {
|
async close() {
|
||||||
if (this._closed)
|
if (this._closed)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -313,6 +313,12 @@ export class FFBrowserContext extends BrowserContextBase {
|
||||||
await this._browser._connection.send('Browser.setRequestInterception', { browserContextId: this._browserContextId || undefined, enabled: true });
|
await this._browser._connection.send('Browser.setRequestInterception', { browserContextId: this._browserContextId || undefined, enabled: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async unroute(url: types.URLMatch, handler?: network.RouteHandler): Promise<void> {
|
||||||
|
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
|
||||||
|
if (this._routes.length === 0)
|
||||||
|
await this._browser._connection.send('Browser.setRequestInterception', { browserContextId: this._browserContextId || undefined, enabled: false });
|
||||||
|
}
|
||||||
|
|
||||||
async close() {
|
async close() {
|
||||||
if (this._closed)
|
if (this._closed)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ export class Page extends ExtendedEventEmitter {
|
||||||
private _workers = new Map<string, Worker>();
|
private _workers = new Map<string, Worker>();
|
||||||
readonly pdf: ((options?: types.PDFOptions) => Promise<Buffer>) | undefined;
|
readonly pdf: ((options?: types.PDFOptions) => Promise<Buffer>) | undefined;
|
||||||
readonly coverage: any;
|
readonly coverage: any;
|
||||||
readonly _routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
|
_routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
|
||||||
_ownedContext: BrowserContext | undefined;
|
_ownedContext: BrowserContext | undefined;
|
||||||
|
|
||||||
constructor(delegate: PageDelegate, browserContext: BrowserContextBase) {
|
constructor(delegate: PageDelegate, browserContext: BrowserContextBase) {
|
||||||
|
|
@ -385,6 +385,11 @@ export class Page extends ExtendedEventEmitter {
|
||||||
await this._delegate.updateRequestInterception();
|
await this._delegate.updateRequestInterception();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async unroute(url: types.URLMatch, handler?: network.RouteHandler): Promise<void> {
|
||||||
|
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
|
||||||
|
await this._delegate.updateRequestInterception();
|
||||||
|
}
|
||||||
|
|
||||||
_requestStarted(request: network.Request) {
|
_requestStarted(request: network.Request) {
|
||||||
this.emit(Events.Page.Request, request);
|
this.emit(Events.Page.Request, request);
|
||||||
const route = request._route();
|
const route = request._route();
|
||||||
|
|
|
||||||
|
|
@ -315,6 +315,12 @@ export class WKBrowserContext extends BrowserContextBase {
|
||||||
await (page._delegate as WKPage).updateRequestInterception();
|
await (page._delegate as WKPage).updateRequestInterception();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async unroute(url: types.URLMatch, handler?: network.RouteHandler): Promise<void> {
|
||||||
|
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
|
||||||
|
for (const page of this.pages())
|
||||||
|
await (page._delegate as WKPage).updateRequestInterception();
|
||||||
|
}
|
||||||
|
|
||||||
async close() {
|
async close() {
|
||||||
if (this._closed)
|
if (this._closed)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -383,6 +383,43 @@ describe('BrowserContext.route', () => {
|
||||||
expect(intercepted).toBe(true);
|
expect(intercepted).toBe(true);
|
||||||
await context.close();
|
await context.close();
|
||||||
});
|
});
|
||||||
|
it('should unroute', async({browser, server}) => {
|
||||||
|
const context = await browser.newContext();
|
||||||
|
const page = await context.newPage();
|
||||||
|
|
||||||
|
let intercepted = [];
|
||||||
|
const handler1 = route => {
|
||||||
|
intercepted.push(1);
|
||||||
|
route.continue();
|
||||||
|
};
|
||||||
|
await context.route('**/empty.html', handler1);
|
||||||
|
await context.route('**/empty.html', route => {
|
||||||
|
intercepted.push(2);
|
||||||
|
route.continue();
|
||||||
|
});
|
||||||
|
await context.route('**/empty.html', route => {
|
||||||
|
intercepted.push(3);
|
||||||
|
route.continue();
|
||||||
|
});
|
||||||
|
await context.route('**/*', route => {
|
||||||
|
intercepted.push(4);
|
||||||
|
route.continue();
|
||||||
|
});
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
expect(intercepted).toEqual([1]);
|
||||||
|
|
||||||
|
intercepted = [];
|
||||||
|
await context.unroute('**/empty.html', handler1);
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
expect(intercepted).toEqual([2]);
|
||||||
|
|
||||||
|
intercepted = [];
|
||||||
|
await context.unroute('**/empty.html');
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
expect(intercepted).toEqual([4]);
|
||||||
|
|
||||||
|
await context.close();
|
||||||
|
});
|
||||||
it('should yield to page.route', async({browser, server}) => {
|
it('should yield to page.route', async({browser, server}) => {
|
||||||
const context = await browser.newContext();
|
const context = await browser.newContext();
|
||||||
await context.route('**/empty.html', route => {
|
await context.route('**/empty.html', route => {
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,38 @@ describe('Page.route', function() {
|
||||||
expect(response.ok()).toBe(true);
|
expect(response.ok()).toBe(true);
|
||||||
expect(intercepted).toBe(true);
|
expect(intercepted).toBe(true);
|
||||||
});
|
});
|
||||||
|
it('should unroute', async({page, server}) => {
|
||||||
|
let intercepted = [];
|
||||||
|
const handler1 = route => {
|
||||||
|
intercepted.push(1);
|
||||||
|
route.continue();
|
||||||
|
};
|
||||||
|
await page.route('**/empty.html', handler1);
|
||||||
|
await page.route('**/empty.html', route => {
|
||||||
|
intercepted.push(2);
|
||||||
|
route.continue();
|
||||||
|
});
|
||||||
|
await page.route('**/empty.html', route => {
|
||||||
|
intercepted.push(3);
|
||||||
|
route.continue();
|
||||||
|
});
|
||||||
|
await page.route('**/*', route => {
|
||||||
|
intercepted.push(4);
|
||||||
|
route.continue();
|
||||||
|
});
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
expect(intercepted).toEqual([1]);
|
||||||
|
|
||||||
|
intercepted = [];
|
||||||
|
await page.unroute('**/empty.html', handler1);
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
expect(intercepted).toEqual([2]);
|
||||||
|
|
||||||
|
intercepted = [];
|
||||||
|
await page.unroute('**/empty.html');
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
expect(intercepted).toEqual([4]);
|
||||||
|
});
|
||||||
it('should work when POST is redirected with 302', async({page, server}) => {
|
it('should work when POST is redirected with 302', async({page, server}) => {
|
||||||
server.setRedirect('/rredirect', '/empty.html');
|
server.setRedirect('/rredirect', '/empty.html');
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue