feat(api): page.unroute to remove routes (#1813)

This commit is contained in:
Dmitry Gozman 2020-04-15 19:55:22 -07:00 коммит произвёл GitHub
Родитель 0426354451
Коммит ba36860d79
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 114 добавлений и 3 удалений

Просмотреть файл

@ -305,6 +305,7 @@ await context.close();
- [browserContext.setGeolocation(geolocation)](#browsercontextsetgeolocationgeolocation)
- [browserContext.setHTTPCredentials(httpCredentials)](#browsercontextsethttpcredentialshttpcredentials)
- [browserContext.setOffline(offline)](#browsercontextsetofflineoffline)
- [browserContext.unroute(url[, handler])](#browsercontextunrouteurl-handler)
- [browserContext.waitForEvent(event[, optionsOrPredicate])](#browsercontextwaitforeventevent-optionsorpredicate)
<!-- GEN:stop -->
@ -576,6 +577,13 @@ To disable authentication, pass `null`.
- `offline` <[boolean]> Whether to emulate network being offline for the browser context.
- 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])
- `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.
@ -694,6 +702,7 @@ page.removeListener('request', logRequest);
- [page.title()](#pagetitle)
- [page.type(selector, text[, options])](#pagetypeselector-text-options)
- [page.uncheck(selector, [options])](#pageuncheckselector-options)
- [page.unroute(url[, handler])](#pageunrouteurl-handler)
- [page.url()](#pageurl)
- [page.viewportSize()](#pageviewportsize)
- [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).
#### 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()
- returns: <[string]>
@ -3976,6 +3992,7 @@ const backgroundPage = await context.waitForEvent('backgroundpage');
- [browserContext.setGeolocation(geolocation)](#browsercontextsetgeolocationgeolocation)
- [browserContext.setHTTPCredentials(httpCredentials)](#browsercontextsethttpcredentialshttpcredentials)
- [browserContext.setOffline(offline)](#browsercontextsetofflineoffline)
- [browserContext.unroute(url[, handler])](#browsercontextunrouteurl-handler)
- [browserContext.waitForEvent(event[, optionsOrPredicate])](#browsercontextwaitforeventevent-optionsorpredicate)
<!-- GEN:stop -->

Просмотреть файл

@ -61,6 +61,7 @@ export interface BrowserContext {
addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any): Promise<void>;
exposeFunction(name: string, playwrightFunction: Function): 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>;
close(): Promise<void>;
}
@ -69,7 +70,7 @@ export abstract class BrowserContextBase extends ExtendedEventEmitter implements
readonly _timeoutSettings = new TimeoutSettings();
readonly _pageBindings = new Map<string, PageBinding>();
readonly _options: BrowserContextOptions;
readonly _routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
_routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
_closed = false;
private readonly _closePromise: Promise<Error>;
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 exposeFunction(name: string, playwrightFunction: Function): 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>;
async grantPermissions(permissions: string[], options?: { origin?: string }) {

Просмотреть файл

@ -422,6 +422,12 @@ export class CRBrowserContext extends BrowserContextBase {
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() {
if (this._closed)
return;

Просмотреть файл

@ -313,6 +313,12 @@ export class FFBrowserContext extends BrowserContextBase {
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() {
if (this._closed)
return;

Просмотреть файл

@ -108,7 +108,7 @@ export class Page extends ExtendedEventEmitter {
private _workers = new Map<string, Worker>();
readonly pdf: ((options?: types.PDFOptions) => Promise<Buffer>) | undefined;
readonly coverage: any;
readonly _routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
_routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
_ownedContext: BrowserContext | undefined;
constructor(delegate: PageDelegate, browserContext: BrowserContextBase) {
@ -385,6 +385,11 @@ export class Page extends ExtendedEventEmitter {
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) {
this.emit(Events.Page.Request, request);
const route = request._route();

Просмотреть файл

@ -315,6 +315,12 @@ export class WKBrowserContext extends BrowserContextBase {
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() {
if (this._closed)
return;

Просмотреть файл

@ -383,6 +383,43 @@ describe('BrowserContext.route', () => {
expect(intercepted).toBe(true);
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}) => {
const context = await browser.newContext();
await context.route('**/empty.html', route => {

Просмотреть файл

@ -41,6 +41,38 @@ describe('Page.route', function() {
expect(response.ok()).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}) => {
server.setRedirect('/rredirect', '/empty.html');
await page.goto(server.EMPTY_PAGE);
@ -346,7 +378,7 @@ describe('Page.route', function() {
status: 301,
headers: {
'location': '/empty.html',
}
}
});
});