feat(route): explicitly fall back to the next handler (#14834)
This commit is contained in:
parent
05c56f5942
commit
dcdd3c3cdb
|
|
@ -114,6 +114,120 @@ If set changes the post data of request
|
||||||
|
|
||||||
If set changes the request HTTP headers. Header values will be converted to a string.
|
If set changes the request HTTP headers. Header values will be converted to a string.
|
||||||
|
|
||||||
|
## async method: Route.fallback
|
||||||
|
|
||||||
|
Proceeds to the next registered route in the route chain. If no more routes are
|
||||||
|
registered, continues the request as is. This allows registering multiple routes
|
||||||
|
with the same mask and falling back from one to another.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Handle GET requests.
|
||||||
|
await page.route('**/*', route => {
|
||||||
|
if (route.request().method() !== 'GET') {
|
||||||
|
route.fallback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Handling GET only.
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle POST requests.
|
||||||
|
await page.route('**/*', route => {
|
||||||
|
if (route.request().method() !== 'POST') {
|
||||||
|
route.fallback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Handling POST only.
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Handle GET requests.
|
||||||
|
page.route("**/*", route -> {
|
||||||
|
if (!route.request().method().equals("GET")) {
|
||||||
|
route.fallback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Handling GET only.
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle POST requests.
|
||||||
|
page.route("**/*", route -> {
|
||||||
|
if (!route.request().method().equals("POST")) {
|
||||||
|
route.fallback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Handling POST only.
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```python async
|
||||||
|
# Handle GET requests.
|
||||||
|
def handle_post(route):
|
||||||
|
if route.request.method != "GET":
|
||||||
|
route.fallback()
|
||||||
|
return
|
||||||
|
# Handling GET only.
|
||||||
|
# ...
|
||||||
|
|
||||||
|
# Handle POST requests.
|
||||||
|
def handle_post(route):
|
||||||
|
if route.request.method != "POST":
|
||||||
|
route.fallback()
|
||||||
|
return
|
||||||
|
# Handling POST only.
|
||||||
|
# ...
|
||||||
|
|
||||||
|
await page.route("**/*", handle_get)
|
||||||
|
await page.route("**/*", handle_post)
|
||||||
|
```
|
||||||
|
|
||||||
|
```python sync
|
||||||
|
# Handle GET requests.
|
||||||
|
def handle_post(route):
|
||||||
|
if route.request.method != "GET":
|
||||||
|
route.fallback()
|
||||||
|
return
|
||||||
|
# Handling GET only.
|
||||||
|
# ...
|
||||||
|
|
||||||
|
# Handle POST requests.
|
||||||
|
def handle_post(route):
|
||||||
|
if route.request.method != "POST":
|
||||||
|
route.fallback()
|
||||||
|
return
|
||||||
|
# Handling POST only.
|
||||||
|
# ...
|
||||||
|
|
||||||
|
page.route("**/*", handle_get)
|
||||||
|
page.route("**/*", handle_post)
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Handle GET requests.
|
||||||
|
await page.RouteAsync("**/*", route => {
|
||||||
|
if (route.Request.Method != "GET") {
|
||||||
|
await route.FallbackAsync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Handling GET only.
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle POST requests.
|
||||||
|
await page.RouteAsync("**/*", route => {
|
||||||
|
if (route.Request.Method != "POST") {
|
||||||
|
await route.FallbackAsync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Handling POST only.
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## async method: Route.fulfill
|
## async method: Route.fulfill
|
||||||
|
|
||||||
Fulfills route's request with given response.
|
Fulfills route's request with given response.
|
||||||
|
|
|
||||||
|
|
@ -144,31 +144,17 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onRoute(route: network.Route, request: network.Request) {
|
async _onRoute(route: network.Route, request: network.Request) {
|
||||||
const routes = this._routes.filter(r => r.matches(request.url()));
|
const routeHandlers = this._routes.filter(r => r.matches(request.url()));
|
||||||
|
for (const routeHandler of routeHandlers) {
|
||||||
const nextRoute = async () => {
|
|
||||||
const routeHandler = routes.shift();
|
|
||||||
if (!routeHandler) {
|
|
||||||
await route._finalContinue();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (routeHandler.willExpire())
|
if (routeHandler.willExpire())
|
||||||
this._routes.splice(this._routes.indexOf(routeHandler), 1);
|
this._routes.splice(this._routes.indexOf(routeHandler), 1);
|
||||||
|
const handled = await routeHandler.handle(route, request);
|
||||||
await new Promise<void>(f => {
|
if (!this._routes.length)
|
||||||
routeHandler.handle(route, request, async done => {
|
this._wrapApiCall(() => this._disableInterception(), true).catch(() => {});
|
||||||
if (!done)
|
if (handled)
|
||||||
await nextRoute();
|
return;
|
||||||
f();
|
}
|
||||||
});
|
await route._innerContinue({}, true);
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
await nextRoute();
|
|
||||||
|
|
||||||
if (!this._routes.length)
|
|
||||||
this._wrapApiCall(() => this._disableInterception(), true).catch(() => {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onBinding(bindingCall: BindingCall) {
|
async _onBinding(bindingCall: BindingCall) {
|
||||||
|
|
|
||||||
|
|
@ -229,8 +229,7 @@ type OverridesForContinue = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Route extends ChannelOwner<channels.RouteChannel> implements api.Route {
|
export class Route extends ChannelOwner<channels.RouteChannel> implements api.Route {
|
||||||
private _pendingContinueOverrides: OverridesForContinue | undefined;
|
private _handlingPromise: ManualPromise<boolean> | null = null;
|
||||||
private _routeChain: ((done: boolean) => Promise<void>) | null = null;
|
|
||||||
|
|
||||||
static from(route: channels.RouteChannel): Route {
|
static from(route: channels.RouteChannel): Route {
|
||||||
return (route as any)._object;
|
return (route as any)._object;
|
||||||
|
|
@ -255,22 +254,30 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_startHandling(routeChain: (done: boolean) => Promise<void>) {
|
_startHandling(): Promise<boolean> {
|
||||||
this._routeChain = routeChain;
|
this._handlingPromise = new ManualPromise();
|
||||||
|
return this._handlingPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fallback() {
|
||||||
|
this._checkNotHandled();
|
||||||
|
this._reportHandled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
async abort(errorCode?: string) {
|
async abort(errorCode?: string) {
|
||||||
|
this._checkNotHandled();
|
||||||
await this._raceWithPageClose(this._channel.abort({ errorCode }));
|
await this._raceWithPageClose(this._channel.abort({ errorCode }));
|
||||||
await this._followChain(true);
|
this._reportHandled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fulfill(options: { response?: api.APIResponse, status?: number, headers?: Headers, contentType?: string, body?: string | Buffer, path?: string, har?: RouteHAR } = {}) {
|
async fulfill(options: { response?: api.APIResponse, status?: number, headers?: Headers, contentType?: string, body?: string | Buffer, path?: string, har?: RouteHAR } = {}) {
|
||||||
|
this._checkNotHandled();
|
||||||
await this._wrapApiCall(async () => {
|
await this._wrapApiCall(async () => {
|
||||||
const fallback = await this._innerFulfill(options);
|
const fallback = await this._innerFulfill(options);
|
||||||
switch (fallback) {
|
switch (fallback) {
|
||||||
case 'abort': await this.abort(); break;
|
case 'abort': await this.abort(); break;
|
||||||
case 'continue': await this.continue(); break;
|
case 'continue': await this.continue(); break;
|
||||||
case 'done': await this._followChain(true); break;
|
case 'done': this._reportHandled(true); break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -354,20 +361,23 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
|
||||||
}
|
}
|
||||||
|
|
||||||
async continue(options: OverridesForContinue = {}) {
|
async continue(options: OverridesForContinue = {}) {
|
||||||
if (!this._routeChain)
|
this._checkNotHandled();
|
||||||
|
await this._innerContinue(options);
|
||||||
|
this._reportHandled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_checkNotHandled() {
|
||||||
|
if (!this._handlingPromise)
|
||||||
throw new Error('Route is already handled!');
|
throw new Error('Route is already handled!');
|
||||||
this._pendingContinueOverrides = { ...this._pendingContinueOverrides, ...options };
|
|
||||||
await this._followChain(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async _followChain(done: boolean) {
|
_reportHandled(done: boolean) {
|
||||||
const chain = this._routeChain!;
|
const chain = this._handlingPromise!;
|
||||||
this._routeChain = null;
|
this._handlingPromise = null;
|
||||||
await chain(done);
|
chain.resolve(done);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _finalContinue() {
|
async _innerContinue(options: OverridesForContinue = {}, internal = false) {
|
||||||
const options = this._pendingContinueOverrides || {};
|
|
||||||
return await this._wrapApiCall(async () => {
|
return await this._wrapApiCall(async () => {
|
||||||
const postDataBuffer = isString(options.postData) ? Buffer.from(options.postData, 'utf8') : options.postData;
|
const postDataBuffer = isString(options.postData) ? Buffer.from(options.postData, 'utf8') : options.postData;
|
||||||
await this._raceWithPageClose(this._channel.continue({
|
await this._raceWithPageClose(this._channel.continue({
|
||||||
|
|
@ -376,7 +386,7 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
|
||||||
headers: options.headers ? headersObjectToArray(options.headers) : undefined,
|
headers: options.headers ? headersObjectToArray(options.headers) : undefined,
|
||||||
postData: postDataBuffer ? postDataBuffer.toString('base64') : undefined,
|
postData: postDataBuffer ? postDataBuffer.toString('base64') : undefined,
|
||||||
}));
|
}));
|
||||||
}, !this._pendingContinueOverrides);
|
}, !!internal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -593,12 +603,16 @@ export class RouteHandler {
|
||||||
return urlMatches(this._baseURL, requestURL, this.url);
|
return urlMatches(this._baseURL, requestURL, this.url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public handle(route: Route, request: Request, routeChain: (done: boolean) => Promise<void>) {
|
public async handle(route: Route, request: Request): Promise<boolean> {
|
||||||
++this.handledCount;
|
++this.handledCount;
|
||||||
route._startHandling(routeChain);
|
const handledPromise = route._startHandling();
|
||||||
// Extract handler into a variable to avoid [RouteHandler.handler] in the stack.
|
// Extract handler into a variable to avoid [RouteHandler.handler] in the stack.
|
||||||
const handler = this.handler;
|
const handler = this.handler;
|
||||||
handler(route, request);
|
const [handled] = await Promise.all([
|
||||||
|
handledPromise,
|
||||||
|
handler(route, request),
|
||||||
|
]);
|
||||||
|
return handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public willExpire(): boolean {
|
public willExpire(): boolean {
|
||||||
|
|
|
||||||
|
|
@ -180,30 +180,17 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _onRoute(route: Route, request: Request) {
|
private async _onRoute(route: Route, request: Request) {
|
||||||
const routes = this._routes.filter(r => r.matches(request.url()));
|
const routeHandlers = this._routes.filter(r => r.matches(request.url()));
|
||||||
|
for (const routeHandler of routeHandlers) {
|
||||||
const nextRoute = async () => {
|
|
||||||
const routeHandler = routes.shift();
|
|
||||||
if (!routeHandler) {
|
|
||||||
await this._browserContext._onRoute(route, request);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (routeHandler.willExpire())
|
if (routeHandler.willExpire())
|
||||||
this._routes.splice(this._routes.indexOf(routeHandler), 1);
|
this._routes.splice(this._routes.indexOf(routeHandler), 1);
|
||||||
|
const handled = await routeHandler.handle(route, request);
|
||||||
await new Promise<void>(f => {
|
if (!this._routes.length)
|
||||||
routeHandler.handle(route, request, async done => {
|
this._wrapApiCall(() => this._disableInterception(), true).catch(() => {});
|
||||||
if (!done)
|
if (handled)
|
||||||
await nextRoute();
|
return;
|
||||||
f();
|
}
|
||||||
});
|
await this._browserContext._onRoute(route, request);
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
await nextRoute();
|
|
||||||
if (!this._routes.length)
|
|
||||||
this._wrapApiCall(() => this._disableInterception(), true).catch(() => {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onBinding(bindingCall: BindingCall) {
|
async _onBinding(bindingCall: BindingCall) {
|
||||||
|
|
|
||||||
29
packages/playwright-core/types/types.d.ts
vendored
29
packages/playwright-core/types/types.d.ts
vendored
|
|
@ -14833,6 +14833,35 @@ export interface Route {
|
||||||
url?: string;
|
url?: string;
|
||||||
}): Promise<void>;
|
}): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proceeds to the next registered route in the route chain. If no more routes are registered, continues the request as is.
|
||||||
|
* This allows registering multiple routes with the same mask and falling back from one to another.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* // Handle GET requests.
|
||||||
|
* await page.route('**\/*', route => {
|
||||||
|
* if (route.request().method() !== 'GET') {
|
||||||
|
* route.fallback();
|
||||||
|
* return;
|
||||||
|
* }
|
||||||
|
* // Handling GET only.
|
||||||
|
* // ...
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // Handle POST requests.
|
||||||
|
* await page.route('**\/*', route => {
|
||||||
|
* if (route.request().method() !== 'POST') {
|
||||||
|
* route.fallback();
|
||||||
|
* return;
|
||||||
|
* }
|
||||||
|
* // Handling POST only.
|
||||||
|
* // ...
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
fallback(): Promise<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fulfills route's request with given response.
|
* Fulfills route's request with given response.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -47,19 +47,19 @@ it('should unroute', async ({ browser, server }) => {
|
||||||
let intercepted = [];
|
let intercepted = [];
|
||||||
await context.route('**/*', route => {
|
await context.route('**/*', route => {
|
||||||
intercepted.push(1);
|
intercepted.push(1);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await context.route('**/empty.html', route => {
|
await context.route('**/empty.html', route => {
|
||||||
intercepted.push(2);
|
intercepted.push(2);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await context.route('**/empty.html', route => {
|
await context.route('**/empty.html', route => {
|
||||||
intercepted.push(3);
|
intercepted.push(3);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
const handler4 = route => {
|
const handler4 = route => {
|
||||||
intercepted.push(4);
|
intercepted.push(4);
|
||||||
route.continue();
|
route.fallback();
|
||||||
};
|
};
|
||||||
await context.route('**/empty.html', handler4);
|
await context.route('**/empty.html', handler4);
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
|
@ -250,19 +250,19 @@ it('should overwrite post body with empty string', async ({ context, server, pag
|
||||||
expect(body).toBe('');
|
expect(body).toBe('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should chain continue', async ({ context, page, server }) => {
|
it('should chain fallback', async ({ context, page, server }) => {
|
||||||
const intercepted = [];
|
const intercepted = [];
|
||||||
await context.route('**/empty.html', route => {
|
await context.route('**/empty.html', route => {
|
||||||
intercepted.push(1);
|
intercepted.push(1);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await context.route('**/empty.html', route => {
|
await context.route('**/empty.html', route => {
|
||||||
intercepted.push(2);
|
intercepted.push(2);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await context.route('**/empty.html', route => {
|
await context.route('**/empty.html', route => {
|
||||||
intercepted.push(3);
|
intercepted.push(3);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
expect(intercepted).toEqual([3, 2, 1]);
|
expect(intercepted).toEqual([3, 2, 1]);
|
||||||
|
|
@ -277,7 +277,7 @@ it('should not chain fulfill', async ({ context, page, server }) => {
|
||||||
route.fulfill({ status: 200, body: 'fulfilled' });
|
route.fulfill({ status: 200, body: 'fulfilled' });
|
||||||
});
|
});
|
||||||
await context.route('**/empty.html', route => {
|
await context.route('**/empty.html', route => {
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
const response = await page.goto(server.EMPTY_PAGE);
|
const response = await page.goto(server.EMPTY_PAGE);
|
||||||
const body = await response.body();
|
const body = await response.body();
|
||||||
|
|
@ -294,38 +294,38 @@ it('should not chain abort', async ({ context, page, server }) => {
|
||||||
route.abort();
|
route.abort();
|
||||||
});
|
});
|
||||||
await context.route('**/empty.html', route => {
|
await context.route('**/empty.html', route => {
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
const e = await page.goto(server.EMPTY_PAGE).catch(e => e);
|
const e = await page.goto(server.EMPTY_PAGE).catch(e => e);
|
||||||
expect(e).toBeTruthy();
|
expect(e).toBeTruthy();
|
||||||
expect(failed).toBeFalsy();
|
expect(failed).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should chain continue into page', async ({ context, page, server }) => {
|
it('should chain fallback into page', async ({ context, page, server }) => {
|
||||||
const intercepted = [];
|
const intercepted = [];
|
||||||
await context.route('**/empty.html', route => {
|
await context.route('**/empty.html', route => {
|
||||||
intercepted.push(1);
|
intercepted.push(1);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await context.route('**/empty.html', route => {
|
await context.route('**/empty.html', route => {
|
||||||
intercepted.push(2);
|
intercepted.push(2);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await context.route('**/empty.html', route => {
|
await context.route('**/empty.html', route => {
|
||||||
intercepted.push(3);
|
intercepted.push(3);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await page.route('**/empty.html', route => {
|
await page.route('**/empty.html', route => {
|
||||||
intercepted.push(4);
|
intercepted.push(4);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await page.route('**/empty.html', route => {
|
await page.route('**/empty.html', route => {
|
||||||
intercepted.push(5);
|
intercepted.push(5);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await page.route('**/empty.html', route => {
|
await page.route('**/empty.html', route => {
|
||||||
intercepted.push(6);
|
intercepted.push(6);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
expect(intercepted).toEqual([6, 5, 4, 3, 2, 1]);
|
expect(intercepted).toEqual([6, 5, 4, 3, 2, 1]);
|
||||||
|
|
|
||||||
|
|
@ -43,19 +43,19 @@ it('should unroute', async ({ page, server }) => {
|
||||||
let intercepted = [];
|
let intercepted = [];
|
||||||
await page.route('**/*', route => {
|
await page.route('**/*', route => {
|
||||||
intercepted.push(1);
|
intercepted.push(1);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await page.route('**/empty.html', route => {
|
await page.route('**/empty.html', route => {
|
||||||
intercepted.push(2);
|
intercepted.push(2);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await page.route('**/empty.html', route => {
|
await page.route('**/empty.html', route => {
|
||||||
intercepted.push(3);
|
intercepted.push(3);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
const handler4 = route => {
|
const handler4 = route => {
|
||||||
intercepted.push(4);
|
intercepted.push(4);
|
||||||
route.continue();
|
route.fallback();
|
||||||
};
|
};
|
||||||
await page.route('**/empty.html', handler4);
|
await page.route('**/empty.html', handler4);
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
|
@ -825,10 +825,10 @@ it('should contain raw response header after fulfill', async ({ page, server })
|
||||||
expect(headers['content-type']).toBeTruthy();
|
expect(headers['content-type']).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const method of ['fulfill', 'continue', 'abort'] as const) {
|
for (const method of ['fulfill', 'continue', 'fallback', 'abort'] as const) {
|
||||||
it(`route.${method} should throw if called twice`, async ({ page, server }) => {
|
it(`route.${method} should throw if called twice`, async ({ page, server }) => {
|
||||||
const routePromise = new Promise<Route>(async resove => {
|
const routePromise = new Promise<Route>(async resolve => {
|
||||||
await page.route('**/*', resove);
|
await page.route('**/*', resolve);
|
||||||
});
|
});
|
||||||
page.goto(server.PREFIX + '/empty.html').catch(() => {});
|
page.goto(server.PREFIX + '/empty.html').catch(() => {});
|
||||||
const route = await routePromise;
|
const route = await routePromise;
|
||||||
|
|
@ -838,19 +838,19 @@ for (const method of ['fulfill', 'continue', 'abort'] as const) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should chain continue', async ({ page, server }) => {
|
it('should fall back', async ({ page, server }) => {
|
||||||
const intercepted = [];
|
const intercepted = [];
|
||||||
await page.route('**/empty.html', route => {
|
await page.route('**/empty.html', route => {
|
||||||
intercepted.push(1);
|
intercepted.push(1);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await page.route('**/empty.html', route => {
|
await page.route('**/empty.html', route => {
|
||||||
intercepted.push(2);
|
intercepted.push(2);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await page.route('**/empty.html', route => {
|
await page.route('**/empty.html', route => {
|
||||||
intercepted.push(3);
|
intercepted.push(3);
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
expect(intercepted).toEqual([3, 2, 1]);
|
expect(intercepted).toEqual([3, 2, 1]);
|
||||||
|
|
@ -865,7 +865,7 @@ it('should not chain fulfill', async ({ page, server }) => {
|
||||||
route.fulfill({ status: 200, body: 'fulfilled' });
|
route.fulfill({ status: 200, body: 'fulfilled' });
|
||||||
});
|
});
|
||||||
await page.route('**/empty.html', route => {
|
await page.route('**/empty.html', route => {
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
const response = await page.goto(server.EMPTY_PAGE);
|
const response = await page.goto(server.EMPTY_PAGE);
|
||||||
const body = await response.body();
|
const body = await response.body();
|
||||||
|
|
@ -882,14 +882,14 @@ it('should not chain abort', async ({ page, server }) => {
|
||||||
route.abort();
|
route.abort();
|
||||||
});
|
});
|
||||||
await page.route('**/empty.html', route => {
|
await page.route('**/empty.html', route => {
|
||||||
route.continue();
|
route.fallback();
|
||||||
});
|
});
|
||||||
const e = await page.goto(server.EMPTY_PAGE).catch(e => e);
|
const e = await page.goto(server.EMPTY_PAGE).catch(e => e);
|
||||||
expect(e).toBeTruthy();
|
expect(e).toBeTruthy();
|
||||||
expect(failed).toBeFalsy();
|
expect(failed).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should continue after exception', async ({ page, server }) => {
|
it('should fall back after exception', async ({ page, server }) => {
|
||||||
await page.route('**/empty.html', route => {
|
await page.route('**/empty.html', route => {
|
||||||
route.continue();
|
route.continue();
|
||||||
});
|
});
|
||||||
|
|
@ -897,7 +897,7 @@ it('should continue after exception', async ({ page, server }) => {
|
||||||
try {
|
try {
|
||||||
await route.fulfill({ har: { path: 'file' }, response: {} as any });
|
await route.fulfill({ har: { path: 'file' }, response: {} as any });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
route.continue();
|
route.fallback();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
|
@ -908,7 +908,7 @@ it('should chain once', async ({ page, server }) => {
|
||||||
route.fulfill({ status: 200, body: 'fulfilled one' });
|
route.fulfill({ status: 200, body: 'fulfilled one' });
|
||||||
}, { times: 1 });
|
}, { times: 1 });
|
||||||
await page.route('**/empty.html', route => {
|
await page.route('**/empty.html', route => {
|
||||||
route.continue();
|
route.fallback();
|
||||||
}, { times: 1 });
|
}, { times: 1 });
|
||||||
const response = await page.goto(server.EMPTY_PAGE);
|
const response = await page.goto(server.EMPTY_PAGE);
|
||||||
const body = await response.body();
|
const body = await response.body();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue