fix(har): rewrite sizes and make transferSize work in WK/Linux (#8504)
This commit is contained in:
parent
621af2c737
commit
89245de0ef
|
|
@ -361,8 +361,11 @@ export class CRNetworkManager {
|
||||||
// Under certain conditions we never get the Network.responseReceived
|
// Under certain conditions we never get the Network.responseReceived
|
||||||
// event from protocol. @see https://crbug.com/883475
|
// event from protocol. @see https://crbug.com/883475
|
||||||
const response = request.request._existingResponse();
|
const response = request.request._existingResponse();
|
||||||
if (response)
|
if (response) {
|
||||||
response._requestFinished(helper.secondsToRoundishMillis(event.timestamp - request._timestamp), undefined, event.encodedDataLength);
|
request.request._sizes.transferSize = event.encodedDataLength;
|
||||||
|
request.request._sizes.responseBodySize = event.encodedDataLength - response?.headersSize();
|
||||||
|
response._requestFinished(helper.secondsToRoundishMillis(event.timestamp - request._timestamp), undefined);
|
||||||
|
}
|
||||||
this._requestIdToRequest.delete(request._requestId);
|
this._requestIdToRequest.delete(request._requestId);
|
||||||
if (request._interceptionId)
|
if (request._interceptionId)
|
||||||
this._attemptedAuthentications.delete(request._interceptionId);
|
this._attemptedAuthentications.delete(request._interceptionId);
|
||||||
|
|
|
||||||
|
|
@ -116,13 +116,17 @@ export class FFNetworkManager {
|
||||||
if (!request)
|
if (!request)
|
||||||
return;
|
return;
|
||||||
const response = request.request._existingResponse()!;
|
const response = request.request._existingResponse()!;
|
||||||
|
|
||||||
|
request.request._sizes.transferSize = event.transferSize;
|
||||||
|
request.request._sizes.responseBodySize = event.transferSize - response.headersSize();
|
||||||
|
|
||||||
// Keep redirected requests in the map for future reference as redirectedFrom.
|
// 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(this._relativeTiming(event.responseEndTime), 'Response body is unavailable for redirect responses');
|
response._requestFinished(this._relativeTiming(event.responseEndTime), 'Response body is unavailable for redirect responses');
|
||||||
} else {
|
} else {
|
||||||
this._requests.delete(request._id);
|
this._requests.delete(request._id);
|
||||||
response._requestFinished(this._relativeTiming(event.responseEndTime), undefined, event.transferSize);
|
response._requestFinished(this._relativeTiming(event.responseEndTime), undefined);
|
||||||
}
|
}
|
||||||
this._page._frameManager.requestFinished(request.request);
|
this._page._frameManager.requestFinished(request.request);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,11 @@ export function stripFragmentFromUrl(url: string): string {
|
||||||
return url.substring(0, url.indexOf('#'));
|
return url.substring(0, url.indexOf('#'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RequestSizes = {
|
||||||
|
responseBodySize: number;
|
||||||
|
transferSize: number;
|
||||||
|
};
|
||||||
|
|
||||||
export class Request extends SdkObject {
|
export class Request extends SdkObject {
|
||||||
private _response: Response | null = null;
|
private _response: Response | null = null;
|
||||||
private _redirectedFrom: Request | null;
|
private _redirectedFrom: Request | null;
|
||||||
|
|
@ -95,6 +100,7 @@ export class Request extends SdkObject {
|
||||||
private _waitForResponsePromise: Promise<Response | null>;
|
private _waitForResponsePromise: Promise<Response | null>;
|
||||||
private _waitForResponsePromiseCallback: (value: Response | null) => void = () => {};
|
private _waitForResponsePromiseCallback: (value: Response | null) => void = () => {};
|
||||||
_responseEndTiming = -1;
|
_responseEndTiming = -1;
|
||||||
|
_sizes: RequestSizes = { responseBodySize: 0, transferSize: 0 };
|
||||||
|
|
||||||
constructor(frame: frames.Frame, redirectedFrom: Request | null, documentId: string | undefined,
|
constructor(frame: frames.Frame, redirectedFrom: Request | null, documentId: string | undefined,
|
||||||
url: string, resourceType: string, method: string, postData: Buffer | null, headers: types.HeadersArray) {
|
url: string, resourceType: string, method: string, postData: Buffer | null, headers: types.HeadersArray) {
|
||||||
|
|
@ -193,6 +199,22 @@ export class Request extends SdkObject {
|
||||||
this._headersMap.set('host', host);
|
this._headersMap.set('host', host);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bodySize(): number {
|
||||||
|
return this.postDataBuffer()?.length || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
headersSize(): number {
|
||||||
|
if (!this._response)
|
||||||
|
return 0;
|
||||||
|
let headersSize = 4; // 4 = 2 spaces + 2 line breaks (GET /path \r\n)
|
||||||
|
headersSize += this.method().length;
|
||||||
|
headersSize += (new URL(this.url())).pathname.length;
|
||||||
|
headersSize += 8; // httpVersion
|
||||||
|
for (const header of this._headers)
|
||||||
|
headersSize += header.name.length + header.value.length + 4; // 4 = ': ' + '\r\n'
|
||||||
|
return headersSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Route extends SdkObject {
|
export class Route extends SdkObject {
|
||||||
|
|
@ -302,8 +324,7 @@ export class Response extends SdkObject {
|
||||||
private _serverAddrPromiseCallback: (arg?: RemoteAddr) => void = () => {};
|
private _serverAddrPromiseCallback: (arg?: RemoteAddr) => void = () => {};
|
||||||
private _securityDetailsPromise: Promise<SecurityDetails|undefined>;
|
private _securityDetailsPromise: Promise<SecurityDetails|undefined>;
|
||||||
private _securityDetailsPromiseCallback: (arg?: SecurityDetails) => void = () => {};
|
private _securityDetailsPromiseCallback: (arg?: SecurityDetails) => void = () => {};
|
||||||
_httpVersion: string | undefined;
|
private _httpVersion: string | undefined;
|
||||||
_transferSize: number | undefined;
|
|
||||||
|
|
||||||
constructor(request: Request, status: number, statusText: string, headers: types.HeadersArray, timing: ResourceTiming, getResponseBodyCallback: GetResponseBodyCallback, httpVersion?: string) {
|
constructor(request: Request, status: number, statusText: string, headers: types.HeadersArray, timing: ResourceTiming, getResponseBodyCallback: GetResponseBodyCallback, httpVersion?: string) {
|
||||||
super(request.frame(), 'response');
|
super(request.frame(), 'response');
|
||||||
|
|
@ -337,9 +358,8 @@ export class Response extends SdkObject {
|
||||||
this._securityDetailsPromiseCallback(securityDetails);
|
this._securityDetailsPromiseCallback(securityDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
_requestFinished(responseEndTiming: number, error?: string, transferSize?: number) {
|
_requestFinished(responseEndTiming: number, error?: string) {
|
||||||
this._request._responseEndTiming = Math.max(responseEndTiming, this._timing.responseStart);
|
this._request._responseEndTiming = Math.max(responseEndTiming, this._timing.responseStart);
|
||||||
this._transferSize = transferSize;
|
|
||||||
this._finishedPromiseCallback({ error });
|
this._finishedPromiseCallback({ error });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -401,6 +421,33 @@ export class Response extends SdkObject {
|
||||||
frame(): frames.Frame {
|
frame(): frames.Frame {
|
||||||
return this._request.frame();
|
return this._request.frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transferSize(): number | undefined {
|
||||||
|
return this._request._sizes.transferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bodySize(): number {
|
||||||
|
return this._request._sizes.responseBodySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
httpVersion(): string {
|
||||||
|
if (!this._httpVersion)
|
||||||
|
return 'HTTP/1.1';
|
||||||
|
if (this._httpVersion === 'http/1.1')
|
||||||
|
return 'HTTP/1.1';
|
||||||
|
return this._httpVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
headersSize(): number {
|
||||||
|
let headersSize = 4; // 4 = 2 spaces + 2 line breaks (HTTP/1.1 200 Ok\r\n)
|
||||||
|
headersSize += 8; // httpVersion;
|
||||||
|
headersSize += 3; // statusCode;
|
||||||
|
headersSize += this.statusText().length;
|
||||||
|
for (const header of this.headers())
|
||||||
|
headersSize += header.name.length + header.value.length + 4; // 4 = ': ' + '\r\n'
|
||||||
|
headersSize += 2; // '\r\n'
|
||||||
|
return headersSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InterceptedResponse extends SdkObject {
|
export class InterceptedResponse extends SdkObject {
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { URL } from 'url';
|
|
||||||
import { BrowserContext } from '../../browserContext';
|
import { BrowserContext } from '../../browserContext';
|
||||||
import { helper } from '../../helper';
|
import { helper } from '../../helper';
|
||||||
import * as network from '../../network';
|
import * as network from '../../network';
|
||||||
import { Page } from '../../page';
|
import { Page } from '../../page';
|
||||||
import * as har from './har';
|
import * as har from './har';
|
||||||
import * as types from '../../types';
|
|
||||||
import { calculateSha1, monotonicTime } from '../../../utils/utils';
|
import { calculateSha1, monotonicTime } from '../../../utils/utils';
|
||||||
import { eventsHelper, RegisteredListener } from '../../../utils/eventsHelper';
|
import { eventsHelper, RegisteredListener } from '../../../utils/eventsHelper';
|
||||||
import * as mime from 'mime';
|
import * as mime from 'mime';
|
||||||
|
|
@ -158,7 +156,7 @@ export class HarTracer {
|
||||||
queryString: [...url.searchParams].map(e => ({ name: e[0], value: e[1] })),
|
queryString: [...url.searchParams].map(e => ({ name: e[0], value: e[1] })),
|
||||||
postData: postDataForHar(request, this._options.content),
|
postData: postDataForHar(request, this._options.content),
|
||||||
headersSize: -1,
|
headersSize: -1,
|
||||||
bodySize: calculateRequestBodySize(request) || 0,
|
bodySize: request.bodySize(),
|
||||||
},
|
},
|
||||||
response: {
|
response: {
|
||||||
status: -1,
|
status: -1,
|
||||||
|
|
@ -204,16 +202,15 @@ export class HarTracer {
|
||||||
if (!response)
|
if (!response)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const httpVersion = normaliseHttpVersion(response._httpVersion);
|
const httpVersion = response.httpVersion();
|
||||||
const transferSize = response._transferSize || -1;
|
const transferSize = response.transferSize() || -1;
|
||||||
const headersSize = calculateResponseHeadersSize(httpVersion, response.status(), response.statusText(), response.headers());
|
const responseHeadersSize = response.headersSize();
|
||||||
const bodySize = transferSize !== -1 ? transferSize - headersSize : -1;
|
|
||||||
|
|
||||||
harEntry.request.httpVersion = httpVersion;
|
harEntry.request.httpVersion = httpVersion;
|
||||||
harEntry.response.bodySize = bodySize;
|
harEntry.response.bodySize = response.bodySize();
|
||||||
harEntry.response.headersSize = headersSize;
|
harEntry.response.headersSize = responseHeadersSize;
|
||||||
harEntry.response._transferSize = transferSize;
|
harEntry.response._transferSize = transferSize;
|
||||||
harEntry.request.headersSize = calculateRequestHeadersSize(request.method(), request.url(), httpVersion, request.headers());
|
harEntry.request.headersSize = request.headersSize();
|
||||||
|
|
||||||
const promise = response.body().then(buffer => {
|
const promise = response.body().then(buffer => {
|
||||||
const content = harEntry.response.content;
|
const content = harEntry.response.content;
|
||||||
|
|
@ -258,7 +255,7 @@ export class HarTracer {
|
||||||
harEntry.response = {
|
harEntry.response = {
|
||||||
status: response.status(),
|
status: response.status(),
|
||||||
statusText: response.statusText(),
|
statusText: response.statusText(),
|
||||||
httpVersion: normaliseHttpVersion(response._httpVersion),
|
httpVersion: response.httpVersion(),
|
||||||
cookies: cookiesForHar(response.headerValue('set-cookie'), '\n'),
|
cookies: cookiesForHar(response.headerValue('set-cookie'), '\n'),
|
||||||
headers: response.headers().map(header => ({ name: header.name, value: header.value })),
|
headers: response.headers().map(header => ({ name: header.name, value: header.value })),
|
||||||
content: {
|
content: {
|
||||||
|
|
@ -397,33 +394,3 @@ function parseCookie(c: string): har.Cookie {
|
||||||
}
|
}
|
||||||
return cookie;
|
return cookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateResponseHeadersSize(protocol: string, status: number, statusText: string , headers: types.HeadersArray) {
|
|
||||||
let rawHeaders = `${protocol} ${status} ${statusText}\r\n`;
|
|
||||||
for (const header of headers)
|
|
||||||
rawHeaders += `${header.name}: ${header.value}\r\n`;
|
|
||||||
rawHeaders += '\r\n';
|
|
||||||
return rawHeaders.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
function calculateRequestHeadersSize(method: string, url: string, httpVersion: string, headers: types.HeadersArray) {
|
|
||||||
let rawHeaders = `${method} ${(new URL(url)).pathname} ${httpVersion}\r\n`;
|
|
||||||
for (const header of headers)
|
|
||||||
rawHeaders += `${header.name}: ${header.value}\r\n`;
|
|
||||||
return rawHeaders.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
function normaliseHttpVersion(httpVersion?: string) {
|
|
||||||
if (!httpVersion)
|
|
||||||
return FALLBACK_HTTP_VERSION;
|
|
||||||
if (httpVersion === 'http/1.1')
|
|
||||||
return 'HTTP/1.1';
|
|
||||||
return httpVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
function calculateRequestBodySize(request: network.Request): number|undefined {
|
|
||||||
const postData = request.postDataBuffer();
|
|
||||||
if (!postData)
|
|
||||||
return;
|
|
||||||
return new TextEncoder().encode(postData.toString('utf8')).length;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -380,6 +380,7 @@ export class WKPage implements PageDelegate {
|
||||||
eventsHelper.addEventListener(this._session, 'Network.responseReceived', e => this._onResponseReceived(e)),
|
eventsHelper.addEventListener(this._session, 'Network.responseReceived', e => this._onResponseReceived(e)),
|
||||||
eventsHelper.addEventListener(this._session, 'Network.loadingFinished', e => this._onLoadingFinished(e)),
|
eventsHelper.addEventListener(this._session, 'Network.loadingFinished', e => this._onLoadingFinished(e)),
|
||||||
eventsHelper.addEventListener(this._session, 'Network.loadingFailed', e => this._onLoadingFailed(e)),
|
eventsHelper.addEventListener(this._session, 'Network.loadingFailed', e => this._onLoadingFailed(e)),
|
||||||
|
eventsHelper.addEventListener(this._session, 'Network.dataReceived', e => this._onDataReceived(e)),
|
||||||
eventsHelper.addEventListener(this._session, 'Network.webSocketCreated', e => this._page._frameManager.onWebSocketCreated(e.requestId, e.url)),
|
eventsHelper.addEventListener(this._session, 'Network.webSocketCreated', e => this._page._frameManager.onWebSocketCreated(e.requestId, e.url)),
|
||||||
eventsHelper.addEventListener(this._session, 'Network.webSocketWillSendHandshakeRequest', e => this._page._frameManager.onWebSocketRequest(e.requestId)),
|
eventsHelper.addEventListener(this._session, 'Network.webSocketWillSendHandshakeRequest', e => this._page._frameManager.onWebSocketRequest(e.requestId)),
|
||||||
eventsHelper.addEventListener(this._session, 'Network.webSocketHandshakeResponseReceived', e => this._page._frameManager.onWebSocketResponse(e.requestId, e.response.status, e.response.statusText)),
|
eventsHelper.addEventListener(this._session, 'Network.webSocketHandshakeResponseReceived', e => this._page._frameManager.onWebSocketResponse(e.requestId, e.response.status, e.response.statusText)),
|
||||||
|
|
@ -1049,11 +1050,10 @@ export class WKPage implements PageDelegate {
|
||||||
validFrom: responseReceivedPayload?.response.security?.certificate?.validFrom,
|
validFrom: responseReceivedPayload?.response.security?.certificate?.validFrom,
|
||||||
validTo: responseReceivedPayload?.response.security?.certificate?.validUntil,
|
validTo: responseReceivedPayload?.response.security?.certificate?.validUntil,
|
||||||
});
|
});
|
||||||
const { responseBodyBytesReceived, responseHeaderBytesReceived } = event.metrics || {};
|
request.request._sizes.transferSize += response.headersSize();
|
||||||
const transferSize = responseBodyBytesReceived ? responseBodyBytesReceived + (responseHeaderBytesReceived || 0) : undefined;
|
|
||||||
if (event.metrics?.protocol)
|
if (event.metrics?.protocol)
|
||||||
response._setHttpVersion(event.metrics.protocol);
|
response._setHttpVersion(event.metrics.protocol);
|
||||||
response._requestFinished(helper.secondsToRoundishMillis(event.timestamp - request._timestamp), undefined, transferSize);
|
response._requestFinished(helper.secondsToRoundishMillis(event.timestamp - request._timestamp), undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._requestIdToResponseReceivedPayloadEvent.delete(request._requestId);
|
this._requestIdToResponseReceivedPayloadEvent.delete(request._requestId);
|
||||||
|
|
@ -1081,6 +1081,14 @@ export class WKPage implements PageDelegate {
|
||||||
this._page._frameManager.requestFailed(request.request, event.errorText.includes('cancelled'));
|
this._page._frameManager.requestFailed(request.request, event.errorText.includes('cancelled'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onDataReceived(event: Protocol.Network.dataReceivedPayload) {
|
||||||
|
const request = this._requestIdToRequest.get(event.requestId);
|
||||||
|
if (!request)
|
||||||
|
return;
|
||||||
|
request.request._sizes.responseBodySize += event.encodedDataLength === -1 ? event.dataLength : event.encodedDataLength;
|
||||||
|
request.request._sizes.transferSize += event.encodedDataLength === -1 ? event.dataLength : event.encodedDataLength;
|
||||||
|
}
|
||||||
|
|
||||||
async _grantPermissions(origin: string, permissions: string[]) {
|
async _grantPermissions(origin: string, permissions: string[]) {
|
||||||
const webPermissionToProtocol = new Map<string, string>([
|
const webPermissionToProtocol = new Map<string, string>([
|
||||||
['geolocation', 'geolocation'],
|
['geolocation', 'geolocation'],
|
||||||
|
|
|
||||||
|
|
@ -262,23 +262,34 @@ it('should include content', async ({ contextFactory, server }, testInfo) => {
|
||||||
expect(log.entries[1].response.content.compression).toBe(0);
|
expect(log.entries[1].response.content.compression).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should include sizes', async ({ contextFactory, server, browserName, platform }, testInfo) => {
|
it('should include sizes', async ({ contextFactory, server, asset }, testInfo) => {
|
||||||
it.fixme(browserName === 'webkit' && platform === 'linux', 'blocked by libsoup3');
|
|
||||||
|
|
||||||
const { page, getLog } = await pageWithHar(contextFactory, testInfo);
|
const { page, getLog } = await pageWithHar(contextFactory, testInfo);
|
||||||
await page.goto(server.PREFIX + '/har.html');
|
await page.goto(server.PREFIX + '/har.html');
|
||||||
const log = await getLog();
|
const log = await getLog();
|
||||||
|
expect(log.entries.length).toBe(2);
|
||||||
|
expect(log.entries[0].request.url.endsWith('har.html')).toBe(true);
|
||||||
expect(log.entries[0].request.headersSize).toBeGreaterThanOrEqual(280);
|
expect(log.entries[0].request.headersSize).toBeGreaterThanOrEqual(280);
|
||||||
expect(log.entries[0].response.bodySize).toBeGreaterThanOrEqual(96);
|
expect(log.entries[0].response.bodySize).toBe(fs.statSync(asset('har.html')).size);
|
||||||
expect(log.entries[0].response.headersSize).toBe(198);
|
expect(log.entries[0].response.headersSize).toBeGreaterThanOrEqual(198);
|
||||||
expect(log.entries[0].response._transferSize).toBeGreaterThanOrEqual(294);
|
expect(log.entries[0].response._transferSize).toBeGreaterThanOrEqual(294);
|
||||||
|
|
||||||
expect(log.entries[1].response.bodySize).toBeGreaterThanOrEqual(37);
|
expect(log.entries[1].request.url.endsWith('one-style.css')).toBe(true);
|
||||||
expect(log.entries[1].response.headersSize).toBe(197);
|
expect(log.entries[1].response.bodySize).toBe(fs.statSync(asset('one-style.css')).size);
|
||||||
|
expect(log.entries[1].response.headersSize).toBeGreaterThanOrEqual(197);
|
||||||
expect(log.entries[1].response._transferSize).toBeGreaterThanOrEqual(234);
|
expect(log.entries[1].response._transferSize).toBeGreaterThanOrEqual(234);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should work with gzip compression', async ({ contextFactory, server, browserName }, testInfo) => {
|
||||||
|
it.fixme(browserName === 'webkit');
|
||||||
|
const { page, getLog } = await pageWithHar(contextFactory, testInfo);
|
||||||
|
server.enableGzip('/simple.json');
|
||||||
|
const response = await page.goto(server.PREFIX + '/simple.json');
|
||||||
|
expect(response.headers()['content-encoding']).toBe('gzip');
|
||||||
|
const log = await getLog();
|
||||||
|
expect(log.entries.length).toBe(1);
|
||||||
|
expect(log.entries[0].response.content.compression).toBe(-20);
|
||||||
|
});
|
||||||
|
|
||||||
it('should calculate time', async ({ contextFactory, server }, testInfo) => {
|
it('should calculate time', async ({ contextFactory, server }, testInfo) => {
|
||||||
const { page, getLog } = await pageWithHar(contextFactory, testInfo);
|
const { page, getLog } = await pageWithHar(contextFactory, testInfo);
|
||||||
await page.goto(server.PREFIX + '/har.html');
|
await page.goto(server.PREFIX + '/har.html');
|
||||||
|
|
@ -286,15 +297,14 @@ it('should calculate time', async ({ contextFactory, server }, testInfo) => {
|
||||||
expect(log.entries[0].time).toBeGreaterThan(0);
|
expect(log.entries[0].time).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should report the correct _transferSize with PNG files', async ({ contextFactory, server, browserName, platform }, testInfo) => {
|
it('should report the correct _transferSize with PNG files', async ({ contextFactory, server, asset }, testInfo) => {
|
||||||
it.fixme(browserName === 'webkit' && platform === 'linux', 'blocked by libsoup3');
|
|
||||||
const { page, getLog } = await pageWithHar(contextFactory, testInfo);
|
const { page, getLog } = await pageWithHar(contextFactory, testInfo);
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
await page.setContent(`
|
await page.setContent(`
|
||||||
<img src="${server.PREFIX}/pptr.png" />
|
<img src="${server.PREFIX}/pptr.png" />
|
||||||
`);
|
`);
|
||||||
const log = await getLog();
|
const log = await getLog();
|
||||||
expect(log.entries[1].response._transferSize).toBe(6323);
|
expect(log.entries[1].response._transferSize).toBeGreaterThan(fs.statSync(asset('pptr.png')).size);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have -1 _transferSize when its a failed request', async ({ contextFactory, server }, testInfo) => {
|
it('should have -1 _transferSize when its a failed request', async ({ contextFactory, server }, testInfo) => {
|
||||||
|
|
@ -311,14 +321,14 @@ it('should have -1 _transferSize when its a failed request', async ({ contextFac
|
||||||
expect(log.entries[1].response._transferSize).toBe(-1);
|
expect(log.entries[1].response._transferSize).toBe(-1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should report the correct body size', async ({ contextFactory, server }, testInfo) => {
|
it('should report the correct request body size', async ({ contextFactory, server }, testInfo) => {
|
||||||
server.setRoute('/api', (req, res) => res.end());
|
server.setRoute('/api', (req, res) => res.end());
|
||||||
const { page, getLog } = await pageWithHar(contextFactory, testInfo);
|
const { page, getLog } = await pageWithHar(contextFactory, testInfo);
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
page.waitForResponse(server.PREFIX + '/api'),
|
page.waitForResponse(server.PREFIX + '/api1'),
|
||||||
page.evaluate(() => {
|
page.evaluate(() => {
|
||||||
fetch('/api', {
|
fetch('/api1', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: 'abc123'
|
body: 'abc123'
|
||||||
});
|
});
|
||||||
|
|
@ -328,6 +338,31 @@ it('should report the correct body size', async ({ contextFactory, server }, tes
|
||||||
expect(log.entries[1].request.bodySize).toBe(6);
|
expect(log.entries[1].request.bodySize).toBe(6);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should report the correct request body size when the bodySize is 0', async ({ contextFactory, server }, testInfo) => {
|
||||||
|
server.setRoute('/api', (req, res) => res.end());
|
||||||
|
const { page, getLog } = await pageWithHar(contextFactory, testInfo);
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
await Promise.all([
|
||||||
|
page.waitForResponse(server.PREFIX + '/api2'),
|
||||||
|
page.evaluate(() => {
|
||||||
|
fetch('/api2', {
|
||||||
|
method: 'POST',
|
||||||
|
body: ''
|
||||||
|
});
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
const log = await getLog();
|
||||||
|
expect(log.entries[1].request.bodySize).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should report the correct response body size when the bodySize is 0', async ({ contextFactory, server }, testInfo) => {
|
||||||
|
server.setRoute('/empty.html', (req, res) => res.end(''));
|
||||||
|
const { page, getLog } = await pageWithHar(contextFactory, testInfo);
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
const log = await getLog();
|
||||||
|
expect(log.entries[0].response.bodySize).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
it('should have popup requests', async ({ contextFactory, server }, testInfo) => {
|
it('should have popup requests', async ({ contextFactory, server }, testInfo) => {
|
||||||
const { page, getLog } = await pageWithHar(contextFactory, testInfo);
|
const { page, getLog } = await pageWithHar(contextFactory, testInfo);
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue