feat(trace viewer): show call duration (#8634)

This commit is contained in:
Dmitry Gozman 2021-09-01 13:41:47 -07:00 committed by GitHub
parent 4f4cf448c2
commit 9618a8477b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 20 deletions

View File

@ -64,6 +64,11 @@
text-overflow: ellipsis;
}
.action-duration {
margin-left: 4px;
color: var(--gray);
}
.action-icon {
flex: none;
display: flex;

View File

@ -19,6 +19,7 @@ import './tabbedPane.css';
import * as React from 'react';
import * as modelUtil from './modelUtil';
import { ActionTraceEvent } from '../../../server/trace/common/traceEvents';
import { msToString } from '../../uiUtils';
export interface ActionListProps {
actions: ActionTraceEvent[],
@ -88,6 +89,7 @@ export const ActionList: React.FC<ActionListProps> = ({
<span>{metadata.apiName}</span>
{metadata.params.selector && <div className='action-selector' title={metadata.params.selector}>{metadata.params.selector}</div>}
{metadata.method === 'goto' && metadata.params.url && <div className='action-url' title={metadata.params.url}>{metadata.params.url}</div>}
<span className='action-duration'> {msToString(metadata.endTime - metadata.startTime)}</span>
</div>
<div className='action-icons' onClick={() => setSelectedTab('console')}>
{!!errors && <div className='action-icon'><span className={'codicon codicon-error'}></span><span className="action-icon-value">{errors}</span></div>}

View File

@ -54,6 +54,10 @@
overflow: hidden;
}
.call-duration {
color: var(--gray);
}
.call-line .string {
color: var(--orange);
}

View File

@ -19,6 +19,7 @@ import './callTab.css';
import type { ActionTraceEvent } from '../../../server/trace/common/traceEvents';
import { CallMetadata } from '../../../protocol/callMetadata';
import { parseSerializedValue } from '../../../protocol/serializers';
import { msToString } from '../../uiUtils';
export const CallTab: React.FunctionComponent<{
action: ActionTraceEvent | undefined,
@ -36,7 +37,7 @@ export const CallTab: React.FunctionComponent<{
<div className='codicon codicon-issues'/>
{error}
</div>
<div className='call-line'>{action.metadata.apiName}</div>
<div className='call-line'>{action.metadata.apiName} <span className='call-duration'> {msToString(action.metadata.endTime - action.metadata.startTime)}</span></div>
{ !!paramKeys.length && <div className='call-section'>Parameters</div> }
{
!!paramKeys.length && paramKeys.map((name, index) => renderLine(action.metadata, name, params[name], 'param-' + index))

View File

@ -148,15 +148,16 @@ test('should show empty trace viewer', async ({ showTraceViewer }, testInfo) =>
test('should open simple trace viewer', async ({ showTraceViewer }) => {
const traceViewer = await showTraceViewer(traceFile);
await expect(traceViewer.actionTitles).toHaveText([
'page.gotodata:text/html,<html>Hello world</html>',
'page.setContent',
'page.evaluate',
'page.click\"Click\"',
'page.waitForNavigation',
'page.gotodata:text/html,<html>Hello world 2</html>',
'page.setViewportSize',
'page.hoverbody',
const actionTitles = await traceViewer.actionTitles.allTextContents();
expect(sanitize(actionTitles)).toEqual([
'page.gotodata:text/html,<html>Hello world</html>— Xms',
'page.setContent— Xms',
'page.evaluate— Xms',
'page.click\"Click\"— Xms',
'page.waitForNavigation— Xms',
'page.gotodata:text/html,<html>Hello world 2</html>— Xms',
'page.setViewportSize— Xms',
'page.hoverbody— Xms',
]);
});
@ -198,9 +199,10 @@ test('should open console errors on click', async ({ showTraceViewer, browserNam
test('should show params and return value', async ({ showTraceViewer, browserName }) => {
const traceViewer = await showTraceViewer(traceFile);
await traceViewer.selectAction('page.evaluate');
await expect(traceViewer.callLines).toHaveText([
'page.evaluate',
'expression: "({↵ a↵ }) => {↵ console.log(\'Info\');↵ console.warn(\'Warning\');↵ con…"',
const callLines = await traceViewer.callLines.allTextContents();
expect(sanitize(callLines)).toEqual([
'page.evaluate — Xms',
'expression: "({↵ a↵ }) => {↵ console.log(\'Info\');↵ console.warn(\'Warning\');↵ con…"',
'isFunction: true',
'arg: {"a":"paramA","b":4}',
'value: "return paramA"'
@ -221,16 +223,20 @@ test('should have correct stack trace', async ({ showTraceViewer }) => {
await traceViewer.selectAction('page.click');
await traceViewer.showSourceTab();
const stack1 = (await traceViewer.stackFrames.allInnerTexts()).map(s => s.replace(/\s+/g, ' ').replace(/[0-9]/g, 'X'));
expect(stack1.slice(0, 2)).toEqual([
'doClick trace-viewer.spec.ts :XXX',
'recordTrace trace-viewer.spec.ts :XXX',
const stack1 = await traceViewer.stackFrames.allInnerTexts();
expect(sanitize(stack1).slice(0, 2)).toEqual([
'doClick trace-viewer.spec.ts :X',
'recordTrace trace-viewer.spec.ts :X',
]);
await traceViewer.selectAction('page.hover');
await traceViewer.showSourceTab();
const stack2 = (await traceViewer.stackFrames.allInnerTexts()).map(s => s.replace(/\s+/g, ' ').replace(/[0-9]/g, 'X'));
expect(stack2.slice(0, 1)).toEqual([
'BrowserType.browserType._onWillCloseContext trace-viewer.spec.ts :XXX',
const stack2 = await traceViewer.stackFrames.allInnerTexts();
expect(sanitize(stack2).slice(0, 1)).toEqual([
'BrowserType.browserType._onWillCloseContext trace-viewer.spec.ts :X',
]);
});
function sanitize(texts: string[]): string[] {
return texts.map(s => s.replace(/\s+/g, ' ').replace(/\.ts :[0-9]+/g, '.ts :X').replace(/[0-9]+ms/g, 'Xms'));
}