feat(tracing): capture network failures (#11237)
This commit is contained in:
parent
058f98d3dd
commit
37a97c4201
|
|
@ -85,6 +85,7 @@ export type Response = {
|
|||
headersSize: number;
|
||||
bodySize: number;
|
||||
_transferSize: number;
|
||||
_failureText?: string
|
||||
};
|
||||
|
||||
export type Cookie = {
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ export class HarTracer {
|
|||
eventsHelper.addEventListener(this._context, BrowserContext.Events.Page, (page: Page) => this._ensurePageEntry(page)),
|
||||
eventsHelper.addEventListener(this._context, BrowserContext.Events.Request, (request: network.Request) => this._onRequest(request)),
|
||||
eventsHelper.addEventListener(this._context, BrowserContext.Events.RequestFinished, ({ request, response }) => this._onRequestFinished(request, response).catch(() => {})),
|
||||
eventsHelper.addEventListener(this._context, BrowserContext.Events.RequestFailed, request => this._onRequestFailed(request)),
|
||||
eventsHelper.addEventListener(this._context, BrowserContext.Events.Response, (response: network.Response) => this._onResponse(response)),
|
||||
eventsHelper.addEventListener(this._context.fetchRequest, APIRequestContext.Events.Request, (event: APIRequestEvent) => this._onAPIRequest(event)),
|
||||
eventsHelper.addEventListener(this._context.fetchRequest, APIRequestContext.Events.RequestFinished, (event: APIRequestFinishedEvent) => this._onAPIRequestFinished(event)),
|
||||
|
|
@ -264,6 +265,17 @@ export class HarTracer {
|
|||
}));
|
||||
}
|
||||
|
||||
private async _onRequestFailed(request: network.Request) {
|
||||
const harEntry = this._entryForRequest(request);
|
||||
if (!harEntry)
|
||||
return;
|
||||
|
||||
if (request._failureText !== null)
|
||||
harEntry.response._failureText = request._failureText;
|
||||
if (this._started)
|
||||
this._delegate.onEntryFinished(harEntry);
|
||||
}
|
||||
|
||||
private _storeResponseContent(buffer: Buffer | undefined, content: har.Content) {
|
||||
if (!buffer) {
|
||||
content.size = 0;
|
||||
|
|
|
|||
|
|
@ -106,16 +106,26 @@ export const NetworkResourceDetails: React.FunctionComponent<{
|
|||
if (charset)
|
||||
contentType = charset[1];
|
||||
|
||||
return <div
|
||||
className={'network-request ' + (selected ? 'selected' : '')} onClick={() => setSelected(index)}>
|
||||
<Expandable expanded={expanded} setExpanded={setExpanded} style={{ width: '100%' }} title={
|
||||
<div className='network-request-title'>
|
||||
const renderTitle = () => {
|
||||
if (resource.response._failureText) {
|
||||
return <div className='network-request-title'>
|
||||
<div className={'network-request-title-status status-failure'}>{resource.response._failureText}</div>
|
||||
<div className='network-request-title-method'>{resource.request.method}</div>
|
||||
<div className='network-request-title-url'>{resource.request.url}</div>
|
||||
</div>;
|
||||
} else {
|
||||
return <div className='network-request-title'>
|
||||
<div className={'network-request-title-status ' + formatStatus(resource.response.status)}>{resource.response.status}</div>
|
||||
<div className='network-request-title-method'>{resource.request.method}</div>
|
||||
<div className='network-request-title-url'>{resourceName}</div>
|
||||
<div className='network-request-title-content-type'>{contentType}</div>
|
||||
</div>
|
||||
} body={
|
||||
</div>;
|
||||
}
|
||||
};
|
||||
|
||||
return <div
|
||||
className={'network-request ' + (selected ? 'selected' : '')} onClick={() => setSelected(index)}>
|
||||
<Expandable expanded={expanded} setExpanded={setExpanded} style={{ width: '100%' }} title={ renderTitle() } body={
|
||||
<div className='network-request-details'>
|
||||
<div className='network-request-details-header'>URL</div>
|
||||
<div className='network-request-details-url'>{resource.request.url}</div>
|
||||
|
|
|
|||
|
|
@ -205,6 +205,17 @@ test('should collect sources', async ({ context, page, server }, testInfo) => {
|
|||
expect(sourceFile).toEqual(thisFile);
|
||||
});
|
||||
|
||||
test('should record network failures', async ({ context, page, server }, testInfo) => {
|
||||
await context.tracing.start({ snapshots: true });
|
||||
await page.route('**/*', route => route.abort('connectionaborted'));
|
||||
await page.goto(server.EMPTY_PAGE).catch(e => {});
|
||||
await context.tracing.stop({ path: testInfo.outputPath('trace1.zip') });
|
||||
|
||||
const { events } = await parseTrace(testInfo.outputPath('trace1.zip'));
|
||||
const requestEvent = events.find(e => e.type === 'resource-snapshot' && !!e.snapshot.response._failureText);
|
||||
expect(requestEvent).toBeTruthy();
|
||||
});
|
||||
|
||||
test('should not stall on dialogs', async ({ page, context, server }) => {
|
||||
await context.tracing.start({ screenshots: true, snapshots: true });
|
||||
await page.goto(server.EMPTY_PAGE);
|
||||
|
|
|
|||
Loading…
Reference in a new issue