mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-15 14:11:50 +03:00
api(network): replace redirectChain with redirectedFrom/redirectedTo (#1401)
This commit is contained in:
parent
6dcd6a6eec
commit
6731d37546
35
docs/api.md
35
docs/api.md
@ -3138,7 +3138,8 @@ If request gets a 'redirect' response, the request is successfully finished with
|
|||||||
- [request.isNavigationRequest()](#requestisnavigationrequest)
|
- [request.isNavigationRequest()](#requestisnavigationrequest)
|
||||||
- [request.method()](#requestmethod)
|
- [request.method()](#requestmethod)
|
||||||
- [request.postData()](#requestpostdata)
|
- [request.postData()](#requestpostdata)
|
||||||
- [request.redirectChain()](#requestredirectchain)
|
- [request.redirectedFrom()](#requestredirectedfrom)
|
||||||
|
- [request.redirectedTo()](#requestredirectedto)
|
||||||
- [request.resourceType()](#requestresourcetype)
|
- [request.resourceType()](#requestresourcetype)
|
||||||
- [request.response()](#requestresponse)
|
- [request.response()](#requestresponse)
|
||||||
- [request.url()](#requesturl)
|
- [request.url()](#requesturl)
|
||||||
@ -3176,31 +3177,29 @@ Whether this request is driving frame's navigation.
|
|||||||
#### request.postData()
|
#### request.postData()
|
||||||
- returns: <?[string]> Request's post body, if any.
|
- returns: <?[string]> Request's post body, if any.
|
||||||
|
|
||||||
#### request.redirectChain()
|
#### request.redirectedFrom()
|
||||||
- returns: <[Array]<[Request]>>
|
- returns: <?[Request]> Request that was redirected by the server to this one, if any.
|
||||||
|
|
||||||
A `redirectChain` is a chain of requests initiated to fetch a resource.
|
When the server responds with a redirect, Playwright creates a new [Request] object. The two requests are connected by `redirectedFrom()` and `redirectedTo()` methods. When multiple server redirects has happened, it is possible to construct the whole redirect chain by repeatedly calling `redirectedFrom()`.
|
||||||
- If there are no redirects and the request was successful, the chain will be empty.
|
|
||||||
- If a server responds with at least a single redirect, then the chain will
|
|
||||||
contain all the requests that were redirected.
|
|
||||||
|
|
||||||
`redirectChain` is shared between all the requests of the same chain.
|
|
||||||
|
|
||||||
For example, if the website `http://example.com` has a single redirect to
|
|
||||||
`https://example.com`, then the chain will contain one request:
|
|
||||||
|
|
||||||
|
For example, if the website `http://example.com` redirects to `https://example.com`:
|
||||||
```js
|
```js
|
||||||
const response = await page.goto('http://example.com');
|
const response = await page.goto('http://example.com');
|
||||||
const chain = response.request().redirectChain();
|
console.log(response.request().redirectedFrom().url()); // 'http://example.com'
|
||||||
console.log(chain.length); // 1
|
|
||||||
console.log(chain[0].url()); // 'http://example.com'
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If the website `https://google.com` has no redirects, then the chain will be empty:
|
If the website `https://google.com` has no redirects:
|
||||||
```js
|
```js
|
||||||
const response = await page.goto('https://google.com');
|
const response = await page.goto('https://google.com');
|
||||||
const chain = response.request().redirectChain();
|
console.log(response.request().redirectedFrom()); // null
|
||||||
console.log(chain.length); // 0
|
```
|
||||||
|
|
||||||
|
#### request.redirectedTo()
|
||||||
|
- returns: <?[Request]> New request issued by the browser iff the server responded with redirect.
|
||||||
|
|
||||||
|
This method is the opposite of [request.redirectedFrom()](#requestredirectedfrom):
|
||||||
|
```js
|
||||||
|
console.log(request.redirectedFrom().redirectedTo() === request); // true
|
||||||
```
|
```
|
||||||
|
|
||||||
#### request.resourceType()
|
#### request.resourceType()
|
||||||
|
@ -156,13 +156,13 @@ export class CRNetworkManager {
|
|||||||
_onRequest(workerFrame: frames.Frame | undefined, event: Protocol.Network.requestWillBeSentPayload, interceptionId: string | null) {
|
_onRequest(workerFrame: frames.Frame | undefined, event: Protocol.Network.requestWillBeSentPayload, interceptionId: string | null) {
|
||||||
if (event.request.url.startsWith('data:'))
|
if (event.request.url.startsWith('data:'))
|
||||||
return;
|
return;
|
||||||
let redirectChain: network.Request[] = [];
|
let redirectedFrom: network.Request | null = null;
|
||||||
if (event.redirectResponse) {
|
if (event.redirectResponse) {
|
||||||
const request = this._requestIdToRequest.get(event.requestId);
|
const request = this._requestIdToRequest.get(event.requestId);
|
||||||
// If we connect late to the target, we could have missed the requestWillBeSent event.
|
// If we connect late to the target, we could have missed the requestWillBeSent event.
|
||||||
if (request) {
|
if (request) {
|
||||||
this._handleRequestRedirect(request, event.redirectResponse);
|
this._handleRequestRedirect(request, event.redirectResponse);
|
||||||
redirectChain = request.request._redirectChain;
|
redirectedFrom = request.request;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const frame = event.frameId ? this._page._frameManager.frame(event.frameId) : workerFrame;
|
const frame = event.frameId ? this._page._frameManager.frame(event.frameId) : workerFrame;
|
||||||
@ -173,7 +173,7 @@ export class CRNetworkManager {
|
|||||||
}
|
}
|
||||||
const isNavigationRequest = event.requestId === event.loaderId && event.type === 'Document';
|
const isNavigationRequest = event.requestId === event.loaderId && event.type === 'Document';
|
||||||
const documentId = isNavigationRequest ? event.loaderId : undefined;
|
const documentId = isNavigationRequest ? event.loaderId : undefined;
|
||||||
const request = new InterceptableRequest(this._client, frame, interceptionId, documentId, this._userRequestInterceptionEnabled, event, redirectChain);
|
const request = new InterceptableRequest(this._client, frame, interceptionId, documentId, this._userRequestInterceptionEnabled, event, redirectedFrom);
|
||||||
this._requestIdToRequest.set(event.requestId, request);
|
this._requestIdToRequest.set(event.requestId, request);
|
||||||
this._page._frameManager.requestStarted(request.request);
|
this._page._frameManager.requestStarted(request.request);
|
||||||
}
|
}
|
||||||
@ -188,7 +188,6 @@ export class CRNetworkManager {
|
|||||||
|
|
||||||
_handleRequestRedirect(request: InterceptableRequest, responsePayload: Protocol.Network.Response) {
|
_handleRequestRedirect(request: InterceptableRequest, responsePayload: Protocol.Network.Response) {
|
||||||
const response = this._createResponse(request, responsePayload);
|
const response = this._createResponse(request, responsePayload);
|
||||||
request.request._redirectChain.push(request.request);
|
|
||||||
response._requestFinished(new Error('Response body is unavailable for redirect responses'));
|
response._requestFinished(new Error('Response body is unavailable for redirect responses'));
|
||||||
this._requestIdToRequest.delete(request._requestId);
|
this._requestIdToRequest.delete(request._requestId);
|
||||||
if (request._interceptionId)
|
if (request._interceptionId)
|
||||||
@ -248,13 +247,13 @@ class InterceptableRequest implements network.RouteDelegate {
|
|||||||
_documentId: string | undefined;
|
_documentId: string | undefined;
|
||||||
private _client: CRSession;
|
private _client: CRSession;
|
||||||
|
|
||||||
constructor(client: CRSession, frame: frames.Frame, interceptionId: string | null, documentId: string | undefined, allowInterception: boolean, event: Protocol.Network.requestWillBeSentPayload, redirectChain: network.Request[]) {
|
constructor(client: CRSession, frame: frames.Frame, interceptionId: string | null, documentId: string | undefined, allowInterception: boolean, event: Protocol.Network.requestWillBeSentPayload, redirectedFrom: network.Request | null) {
|
||||||
this._client = client;
|
this._client = client;
|
||||||
this._requestId = event.requestId;
|
this._requestId = event.requestId;
|
||||||
this._interceptionId = interceptionId;
|
this._interceptionId = interceptionId;
|
||||||
this._documentId = documentId;
|
this._documentId = documentId;
|
||||||
|
|
||||||
this.request = new network.Request(allowInterception ? this : null, frame, redirectChain, documentId,
|
this.request = new network.Request(allowInterception ? this : null, frame, redirectedFrom, documentId,
|
||||||
event.request.url, (event.type || '').toLowerCase(), event.request.method, event.request.postData || null, headersObject(event.request.headers));
|
event.request.url, (event.type || '').toLowerCase(), event.request.method, event.request.postData || null, headersObject(event.request.headers));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,17 +52,13 @@ export class FFNetworkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onRequestWillBeSent(event: Protocol.Network.requestWillBeSentPayload) {
|
_onRequestWillBeSent(event: Protocol.Network.requestWillBeSentPayload) {
|
||||||
const redirected = event.redirectedFrom ? this._requests.get(event.redirectedFrom) : null;
|
const redirectedFrom = event.redirectedFrom ? (this._requests.get(event.redirectedFrom) || null) : null;
|
||||||
const frame = redirected ? redirected.request.frame() : (event.frameId ? this._page._frameManager.frame(event.frameId) : null);
|
const frame = redirectedFrom ? redirectedFrom.request.frame() : (event.frameId ? this._page._frameManager.frame(event.frameId) : null);
|
||||||
if (!frame)
|
if (!frame)
|
||||||
return;
|
return;
|
||||||
let redirectChain: network.Request[] = [];
|
if (redirectedFrom)
|
||||||
if (redirected) {
|
this._requests.delete(redirectedFrom._id);
|
||||||
redirectChain = redirected.request._redirectChain;
|
const request = new InterceptableRequest(this._session, frame, redirectedFrom, event);
|
||||||
redirectChain.push(redirected.request);
|
|
||||||
this._requests.delete(redirected._id);
|
|
||||||
}
|
|
||||||
const request = new InterceptableRequest(this._session, frame, redirectChain, event);
|
|
||||||
this._requests.set(request._id, request);
|
this._requests.set(request._id, request);
|
||||||
this._page._frameManager.requestStarted(request.request);
|
this._page._frameManager.requestStarted(request.request);
|
||||||
}
|
}
|
||||||
@ -91,7 +87,7 @@ export class FFNetworkManager {
|
|||||||
if (!request)
|
if (!request)
|
||||||
return;
|
return;
|
||||||
const response = request.request._existingResponse()!;
|
const response = request.request._existingResponse()!;
|
||||||
// Keep redirected requests in the map for future reference in redirectChain.
|
// Keep redirected requests in the map for future reference as redirectedFrom.
|
||||||
const isRedirected = response.status() >= 300 && response.status() <= 399;
|
const isRedirected = response.status() >= 300 && response.status() <= 399;
|
||||||
if (isRedirected) {
|
if (isRedirected) {
|
||||||
response._requestFinished(new Error('Response body is unavailable for redirect responses'));
|
response._requestFinished(new Error('Response body is unavailable for redirect responses'));
|
||||||
@ -146,7 +142,7 @@ class InterceptableRequest implements network.RouteDelegate {
|
|||||||
_id: string;
|
_id: string;
|
||||||
private _session: FFSession;
|
private _session: FFSession;
|
||||||
|
|
||||||
constructor(session: FFSession, frame: frames.Frame, redirectChain: network.Request[], payload: Protocol.Network.requestWillBeSentPayload) {
|
constructor(session: FFSession, frame: frames.Frame, redirectedFrom: InterceptableRequest | null, payload: Protocol.Network.requestWillBeSentPayload) {
|
||||||
this._id = payload.requestId;
|
this._id = payload.requestId;
|
||||||
this._session = session;
|
this._session = session;
|
||||||
|
|
||||||
@ -154,7 +150,7 @@ class InterceptableRequest implements network.RouteDelegate {
|
|||||||
for (const {name, value} of payload.headers)
|
for (const {name, value} of payload.headers)
|
||||||
headers[name.toLowerCase()] = value;
|
headers[name.toLowerCase()] = value;
|
||||||
|
|
||||||
this.request = new network.Request(payload.isIntercepted ? this : null, frame, redirectChain, payload.navigationId,
|
this.request = new network.Request(payload.isIntercepted ? this : null, frame, redirectedFrom ? redirectedFrom.request : null, payload.navigationId,
|
||||||
payload.url, causeToResourceType[payload.cause] || 'other', payload.method, payload.postData || null, headers);
|
payload.url, causeToResourceType[payload.cause] || 'other', payload.method, payload.postData || null, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,7 +387,7 @@ export class Frame {
|
|||||||
|
|
||||||
disposer.dispose();
|
disposer.dispose();
|
||||||
|
|
||||||
return request ? request._finalRequest.response() : null;
|
return request ? request._finalRequest().response() : null;
|
||||||
|
|
||||||
function throwIfError(error: Error|void): asserts error is void {
|
function throwIfError(error: Error|void): asserts error is void {
|
||||||
if (!error)
|
if (!error)
|
||||||
@ -430,7 +430,7 @@ export class Frame {
|
|||||||
if (error)
|
if (error)
|
||||||
throw error;
|
throw error;
|
||||||
|
|
||||||
return request ? request._finalRequest.response() : null;
|
return request ? request._finalRequest().response() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _waitForLoadState(options: types.NavigateOptions = {}): Promise<void> {
|
async _waitForLoadState(options: types.NavigateOptions = {}): Promise<void> {
|
||||||
@ -519,7 +519,7 @@ export class Frame {
|
|||||||
this._requestWatchers.delete(onRequest);
|
this._requestWatchers.delete(onRequest);
|
||||||
};
|
};
|
||||||
const onRequest = (request: network.Request) => {
|
const onRequest = (request: network.Request) => {
|
||||||
if (!request._documentId || request.redirectChain().length)
|
if (!request._documentId || request.redirectedFrom())
|
||||||
return;
|
return;
|
||||||
requestMap.set(request._documentId, request);
|
requestMap.set(request._documentId, request);
|
||||||
};
|
};
|
||||||
|
@ -95,8 +95,8 @@ export type Headers = { [key: string]: string };
|
|||||||
export class Request {
|
export class Request {
|
||||||
readonly _routeDelegate: RouteDelegate | null;
|
readonly _routeDelegate: RouteDelegate | null;
|
||||||
private _response: Response | null = null;
|
private _response: Response | null = null;
|
||||||
_redirectChain: Request[];
|
private _redirectedFrom: Request | null;
|
||||||
_finalRequest: Request;
|
private _redirectedTo: Request | null = null;
|
||||||
readonly _documentId?: string;
|
readonly _documentId?: string;
|
||||||
readonly _isFavicon: boolean;
|
readonly _isFavicon: boolean;
|
||||||
private _failureText: string | null = null;
|
private _failureText: string | null = null;
|
||||||
@ -109,15 +109,14 @@ export class Request {
|
|||||||
private _waitForResponsePromise: Promise<Response | null>;
|
private _waitForResponsePromise: Promise<Response | null>;
|
||||||
private _waitForResponsePromiseCallback: (value: Response | null) => void = () => {};
|
private _waitForResponsePromiseCallback: (value: Response | null) => void = () => {};
|
||||||
|
|
||||||
constructor(routeDelegate: RouteDelegate | null, frame: frames.Frame, redirectChain: Request[], documentId: string | undefined,
|
constructor(routeDelegate: RouteDelegate | null, frame: frames.Frame, redirectedFrom: Request | null, documentId: string | undefined,
|
||||||
url: string, resourceType: string, method: string, postData: string | null, headers: Headers) {
|
url: string, resourceType: string, method: string, postData: string | null, headers: Headers) {
|
||||||
assert(!url.startsWith('data:'), 'Data urls should not fire requests');
|
assert(!url.startsWith('data:'), 'Data urls should not fire requests');
|
||||||
this._routeDelegate = routeDelegate;
|
this._routeDelegate = routeDelegate;
|
||||||
this._frame = frame;
|
this._frame = frame;
|
||||||
this._redirectChain = redirectChain;
|
this._redirectedFrom = redirectedFrom;
|
||||||
this._finalRequest = this;
|
if (redirectedFrom)
|
||||||
for (const request of redirectChain)
|
redirectedFrom._redirectedTo = this;
|
||||||
request._finalRequest = this;
|
|
||||||
this._documentId = documentId;
|
this._documentId = documentId;
|
||||||
this._url = stripFragmentFromUrl(url);
|
this._url = stripFragmentFromUrl(url);
|
||||||
this._resourceType = resourceType;
|
this._resourceType = resourceType;
|
||||||
@ -166,6 +165,10 @@ export class Request {
|
|||||||
this._waitForResponsePromiseCallback(response);
|
this._waitForResponsePromiseCallback(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_finalRequest(): Request {
|
||||||
|
return this._redirectedTo ? this._redirectedTo._finalRequest() : this;
|
||||||
|
}
|
||||||
|
|
||||||
frame(): frames.Frame {
|
frame(): frames.Frame {
|
||||||
return this._frame;
|
return this._frame;
|
||||||
}
|
}
|
||||||
@ -174,8 +177,12 @@ export class Request {
|
|||||||
return !!this._documentId;
|
return !!this._documentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
redirectChain(): Request[] {
|
redirectedFrom(): Request | null {
|
||||||
return this._redirectChain.slice();
|
return this._redirectedFrom;
|
||||||
|
}
|
||||||
|
|
||||||
|
redirectedTo(): Request | null {
|
||||||
|
return this._redirectedTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
failure(): { errorText: string; } | null {
|
failure(): { errorText: string; } | null {
|
||||||
|
@ -46,11 +46,12 @@ export class WKInterceptableRequest implements network.RouteDelegate {
|
|||||||
_interceptedCallback: () => void = () => {};
|
_interceptedCallback: () => void = () => {};
|
||||||
private _interceptedPromise: Promise<unknown>;
|
private _interceptedPromise: Promise<unknown>;
|
||||||
|
|
||||||
constructor(session: WKSession, allowInterception: boolean, frame: frames.Frame, event: Protocol.Network.requestWillBeSentPayload, redirectChain: network.Request[], documentId: string | undefined) {
|
constructor(session: WKSession, allowInterception: boolean, frame: frames.Frame, event: Protocol.Network.requestWillBeSentPayload, redirectedFrom: network.Request | null, documentId: string | undefined) {
|
||||||
this._session = session;
|
this._session = session;
|
||||||
this._requestId = event.requestId;
|
this._requestId = event.requestId;
|
||||||
this.request = new network.Request(allowInterception ? this : null, frame, redirectChain, documentId, event.request.url,
|
const resourceType = event.type ? event.type.toLowerCase() : (redirectedFrom ? redirectedFrom.resourceType() : 'unknown');
|
||||||
event.type ? event.type.toLowerCase() : 'Unknown', event.request.method, event.request.postData || null, headersObject(event.request.headers));
|
this.request = new network.Request(allowInterception ? this : null, frame, redirectedFrom, documentId, event.request.url,
|
||||||
|
resourceType, event.request.method, event.request.postData || null, headersObject(event.request.headers));
|
||||||
this._interceptedPromise = new Promise(f => this._interceptedCallback = f);
|
this._interceptedPromise = new Promise(f => this._interceptedCallback = f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -730,27 +730,26 @@ export class WKPage implements PageDelegate {
|
|||||||
_onRequestWillBeSent(session: WKSession, event: Protocol.Network.requestWillBeSentPayload) {
|
_onRequestWillBeSent(session: WKSession, event: Protocol.Network.requestWillBeSentPayload) {
|
||||||
if (event.request.url.startsWith('data:'))
|
if (event.request.url.startsWith('data:'))
|
||||||
return;
|
return;
|
||||||
let redirectChain: network.Request[] = [];
|
let redirectedFrom: network.Request | null = null;
|
||||||
if (event.redirectResponse) {
|
if (event.redirectResponse) {
|
||||||
const request = this._requestIdToRequest.get(event.requestId);
|
const request = this._requestIdToRequest.get(event.requestId);
|
||||||
// If we connect late to the target, we could have missed the requestWillBeSent event.
|
// If we connect late to the target, we could have missed the requestWillBeSent event.
|
||||||
if (request) {
|
if (request) {
|
||||||
this._handleRequestRedirect(request, event.redirectResponse);
|
this._handleRequestRedirect(request, event.redirectResponse);
|
||||||
redirectChain = request.request._redirectChain;
|
redirectedFrom = request.request;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const frame = this._page._frameManager.frame(event.frameId)!;
|
const frame = this._page._frameManager.frame(event.frameId)!;
|
||||||
// TODO(einbinder) this will fail if we are an XHR document request
|
// TODO(einbinder) this will fail if we are an XHR document request
|
||||||
const isNavigationRequest = event.type === 'Document';
|
const isNavigationRequest = event.type === 'Document';
|
||||||
const documentId = isNavigationRequest ? event.loaderId : undefined;
|
const documentId = isNavigationRequest ? event.loaderId : undefined;
|
||||||
const request = new WKInterceptableRequest(session, this._page._needsRequestInterception(), frame, event, redirectChain, documentId);
|
const request = new WKInterceptableRequest(session, this._page._needsRequestInterception(), frame, event, redirectedFrom, documentId);
|
||||||
this._requestIdToRequest.set(event.requestId, request);
|
this._requestIdToRequest.set(event.requestId, request);
|
||||||
this._page._frameManager.requestStarted(request.request);
|
this._page._frameManager.requestStarted(request.request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _handleRequestRedirect(request: WKInterceptableRequest, responsePayload: Protocol.Network.Response) {
|
private _handleRequestRedirect(request: WKInterceptableRequest, responsePayload: Protocol.Network.Response) {
|
||||||
const response = request.createResponse(responsePayload);
|
const response = request.createResponse(responsePayload);
|
||||||
request.request._redirectChain.push(request.request);
|
|
||||||
response._requestFinished(new Error('Response body is unavailable for redirect responses'));
|
response._requestFinished(new Error('Response body is unavailable for redirect responses'));
|
||||||
this._requestIdToRequest.delete(request._requestId);
|
this._requestIdToRequest.delete(request._requestId);
|
||||||
this._page._frameManager.requestReceivedResponse(response);
|
this._page._frameManager.requestReceivedResponse(response);
|
||||||
|
@ -488,6 +488,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, FF
|
|||||||
page.evaluate(url => window.open(url), server.EMPTY_PAGE)
|
page.evaluate(url => window.open(url), server.EMPTY_PAGE)
|
||||||
]);
|
]);
|
||||||
expect(otherPage.url()).toBe(server.EMPTY_PAGE);
|
expect(otherPage.url()).toBe(server.EMPTY_PAGE);
|
||||||
|
await context.close();
|
||||||
});
|
});
|
||||||
it.fail(CHROMIUM)('should have url with domcontentloaded', async({browser, server}) => {
|
it.fail(CHROMIUM)('should have url with domcontentloaded', async({browser, server}) => {
|
||||||
const context = await browser.newContext();
|
const context = await browser.newContext();
|
||||||
@ -497,6 +498,7 @@ module.exports.describe = function({testRunner, expect, playwright, CHROMIUM, FF
|
|||||||
page.evaluate(url => window.open(url), server.EMPTY_PAGE)
|
page.evaluate(url => window.open(url), server.EMPTY_PAGE)
|
||||||
]);
|
]);
|
||||||
expect(otherPage.url()).toBe(server.EMPTY_PAGE);
|
expect(otherPage.url()).toBe(server.EMPTY_PAGE);
|
||||||
|
await context.close();
|
||||||
});
|
});
|
||||||
it('should report when a new page is created and closed', async({browser, server}) => {
|
it('should report when a new page is created and closed', async({browser, server}) => {
|
||||||
const context = await browser.newContext();
|
const context = await browser.newContext();
|
||||||
|
@ -204,16 +204,19 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
|
|||||||
expect(response.url()).toContain('empty.html');
|
expect(response.url()).toContain('empty.html');
|
||||||
expect(requests.length).toBe(5);
|
expect(requests.length).toBe(5);
|
||||||
expect(requests[2].resourceType()).toBe('document');
|
expect(requests[2].resourceType()).toBe('document');
|
||||||
// Check redirect chain
|
const chain = [];
|
||||||
const redirectChain = response.request().redirectChain();
|
for (let r = response.request(); r; r = r.redirectedFrom()) {
|
||||||
expect(redirectChain.length).toBe(4);
|
chain.push(r);
|
||||||
expect(redirectChain[0].url()).toContain('/non-existing-page.html');
|
expect(r.isNavigationRequest()).toBe(true);
|
||||||
expect(redirectChain[2].url()).toContain('/non-existing-page-3.html');
|
|
||||||
for (let i = 0; i < redirectChain.length; ++i) {
|
|
||||||
const request = redirectChain[i];
|
|
||||||
expect(request.isNavigationRequest()).toBe(true);
|
|
||||||
expect(request.redirectChain().indexOf(request)).toBe(i);
|
|
||||||
}
|
}
|
||||||
|
expect(chain.length).toBe(5);
|
||||||
|
expect(chain[0].url()).toContain('/empty.html');
|
||||||
|
expect(chain[1].url()).toContain('/non-existing-page-4.html');
|
||||||
|
expect(chain[2].url()).toContain('/non-existing-page-3.html');
|
||||||
|
expect(chain[3].url()).toContain('/non-existing-page-2.html');
|
||||||
|
expect(chain[4].url()).toContain('/non-existing-page.html');
|
||||||
|
for (let i = 0; i < chain.length; i++)
|
||||||
|
expect(chain[i].redirectedTo()).toBe(i ? chain[i - 1] : null);
|
||||||
});
|
});
|
||||||
it('should work with redirects for subresources', async({page, server}) => {
|
it('should work with redirects for subresources', async({page, server}) => {
|
||||||
const requests = [];
|
const requests = [];
|
||||||
@ -231,12 +234,14 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p
|
|||||||
expect(response.url()).toContain('one-style.html');
|
expect(response.url()).toContain('one-style.html');
|
||||||
expect(requests.length).toBe(5);
|
expect(requests.length).toBe(5);
|
||||||
expect(requests[0].resourceType()).toBe('document');
|
expect(requests[0].resourceType()).toBe('document');
|
||||||
expect(requests[1].resourceType()).toBe('stylesheet');
|
|
||||||
// Check redirect chain
|
let r = requests.find(r => r.url().includes('/four-style.css'));
|
||||||
const redirectChain = requests[1].redirectChain();
|
for (const url of ['/four-style.css', '/three-style.css', '/two-style.css', '/one-style.css']) {
|
||||||
expect(redirectChain.length).toBe(3);
|
expect(r.resourceType()).toBe('stylesheet');
|
||||||
expect(redirectChain[0].url()).toContain('/one-style.css');
|
expect(r.url()).toContain(url);
|
||||||
expect(redirectChain[2].url()).toContain('/three-style.css');
|
r = r.redirectedFrom();
|
||||||
|
}
|
||||||
|
expect(r).toBe(null);
|
||||||
});
|
});
|
||||||
it('should work with equal requests', async({page, server}) => {
|
it('should work with equal requests', async({page, server}) => {
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
@ -130,9 +130,9 @@ module.exports.describe = function({testRunner, expect, MAC, WIN, FFOX, CHROMIUM
|
|||||||
it('should throw when requesting body of redirected response', async({page, server}) => {
|
it('should throw when requesting body of redirected response', async({page, server}) => {
|
||||||
server.setRedirect('/foo.html', '/empty.html');
|
server.setRedirect('/foo.html', '/empty.html');
|
||||||
const response = await page.goto(server.PREFIX + '/foo.html');
|
const response = await page.goto(server.PREFIX + '/foo.html');
|
||||||
const redirectChain = response.request().redirectChain();
|
const redirectedFrom = response.request().redirectedFrom();
|
||||||
expect(redirectChain.length).toBe(1);
|
expect(redirectedFrom).toBeTruthy();
|
||||||
const redirected = await redirectChain[0].response();
|
const redirected = await redirectedFrom.response();
|
||||||
expect(redirected.status()).toBe(302);
|
expect(redirected.status()).toBe(302);
|
||||||
let error = null;
|
let error = null;
|
||||||
await redirected.text().catch(e => error = e);
|
await redirected.text().catch(e => error = e);
|
||||||
@ -295,11 +295,10 @@ module.exports.describe = function({testRunner, expect, MAC, WIN, FFOX, CHROMIUM
|
|||||||
`200 ${server.EMPTY_PAGE}`,
|
`200 ${server.EMPTY_PAGE}`,
|
||||||
`DONE ${server.EMPTY_PAGE}`
|
`DONE ${server.EMPTY_PAGE}`
|
||||||
]);
|
]);
|
||||||
|
const redirectedFrom = response.request().redirectedFrom();
|
||||||
// Check redirect chain
|
expect(redirectedFrom.url()).toContain('/foo.html');
|
||||||
const redirectChain = response.request().redirectChain();
|
expect(redirectedFrom.redirectedFrom()).toBe(null);
|
||||||
expect(redirectChain.length).toBe(1);
|
expect(redirectedFrom.redirectedTo()).toBe(response.request());
|
||||||
expect(redirectChain[0].url()).toContain('/foo.html');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user